Skip to content

Commit

Permalink
Added URL Query fuzzing attack. Very basic at the moment. Will need s…
Browse files Browse the repository at this point in the history
…ome work
  • Loading branch information
ChrisCooney committed Sep 1, 2017
1 parent 4462d86 commit a08b0de
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 20 deletions.
35 changes: 33 additions & 2 deletions attacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func readResponseFromChannel(responses []*http.Response, c chan *http.Response)

// Fires off the requested number of concurrent messages at an endpoint and tests response.
func RunHTTPSpam(endpointConfig EndpointConfig, attackConfig AttackConfig, responseChannel chan Response) error {
fmt.Printf("🔥 Running HTTP Spam against %s 🔥\n", endpointConfig.Name)
fmt.Printf("🔥 Running HTTP Spam against %s \n", endpointConfig.Name)

c := make(chan *http.Response)

Expand Down Expand Up @@ -112,7 +112,7 @@ func RunHTTPSpam(endpointConfig EndpointConfig, attackConfig AttackConfig, respo

// Fires off a Corrupted HTTP request at the specific endpoint.
func RunCorruptHTTP(endpointConfig EndpointConfig, attackConfig AttackConfig, responseChannel chan Response) error {
fmt.Printf("🔥 Running Corrupt HTTP against %s 🔥\n", endpointConfig.Name)
fmt.Printf("🔥 Running Corrupt HTTP against %s \n", endpointConfig.Name)
c := make(chan string)
endpoint := BuildNetworkPath("", endpointConfig.Host, endpointConfig.Port, "")

Expand All @@ -131,3 +131,34 @@ func RunCorruptHTTP(endpointConfig EndpointConfig, attackConfig AttackConfig, re
responseChannel <- Response{AttackConfig: attackConfig, Passed: true, Report: fmt.Sprintf("Corrupt HTTP Test passed for endpoint %s", endpointConfig.Name)}
return nil
}

func RunUrlQuery(endpointConfig EndpointConfig, attackConfig AttackConfig, responseChannel chan Response) error {
fmt.Printf("🔥 Running URL Query Spam against %s \n", endpointConfig.Name)
c := make(chan *http.Response)

endpoint := BuildNetworkPath(endpointConfig.Protocol, endpointConfig.Host, endpointConfig.Port, endpointConfig.Path)

params := strings.Split(attackConfig.Parameters, ",")

for _,param := range params {
attackPoint := fmt.Sprintf("%s?%s=themonkeysayshello", endpoint, param)
go SendHTTPRequest(attackPoint, c, "GET")
}

responses := collectConcurrentHTTPResponses(c, len(params))

if len(responses) == 0 {
responseChannel <- Response{AttackConfig: attackConfig, Passed: false, Report: "Error occurred during URL Query Spam."}
return nil
}

passed, reason, expected, actual := checkHTTPResponses(responses, attackConfig)

if !passed {
responseChannel <- Response{Expected: expected, Actual: actual, AttackConfig: attackConfig, Passed: false, Report: fmt.Sprintf("Failure during URL Query Spam. %s", reason)}
return nil
}

responseChannel <- Response{AttackConfig: attackConfig, Passed: true, Report: fmt.Sprintf("URL Query Spam passed for endpoint %s", endpointConfig.Name)}
return nil
}
45 changes: 37 additions & 8 deletions attacks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (

func TestRunHTTPSpam(t *testing.T) {
t.Run("Test run HTTP spam correctly reports on endpoints", func(t *testing.T) {
createMockHTTPServer()
createMockHTTPServer(200)
defer httpmock.DeactivateAndReset()
c := createResponseChannel()

endpoint, attack := CreateTestEndpointAndAttackConfiguration("200")
endpoint, attack := CreateTestEndpointAndAttackConfiguration("200", "HTTP_SPAM")

go RunHTTPSpam(endpoint, attack, c)

Expand All @@ -23,7 +23,7 @@ func TestRunHTTPSpam(t *testing.T) {
t.Error("Valid config provided to HTTP Spam. HTTP SPAM did not return a passing report.")
}

endpoint, attack = CreateTestEndpointAndAttackConfiguration("404")
endpoint, attack = CreateTestEndpointAndAttackConfiguration("404", "HTTP_SPAM")

go RunHTTPSpam(endpoint, attack, c)

Expand All @@ -39,7 +39,7 @@ func TestRunCorruptHTTP(t *testing.T) {
t.Run("Test run Corrupt HTTP correctly reports on endpoints", func(t *testing.T) {
go createMockTcpServer()
c := createResponseChannel()
endpoint, attack := CreateTestEndpointAndAttackConfiguration("200")
endpoint, attack := CreateTestEndpointAndAttackConfiguration("200", "CORRUPT_HTTP")

go RunCorruptHTTP(endpoint, attack, c)

Expand All @@ -49,7 +49,7 @@ func TestRunCorruptHTTP(t *testing.T) {
t.Errorf("Valid config provided to corrupt HTTP. Corrupt HTTP did not return a passing report. %v", response)
}

endpoint, attack = CreateTestEndpointAndAttackConfiguration("404")
endpoint, attack = CreateTestEndpointAndAttackConfiguration("404", "CORRUPT_HTTP")

go RunCorruptHTTP(endpoint, attack, c)

Expand All @@ -61,11 +61,40 @@ func TestRunCorruptHTTP(t *testing.T) {
})
}

func createMockHTTPServer() {
func TestRunURLQuery(t *testing.T) {
t.Run("Test run URL Query attack correctly reports on endpoints", func(t *testing.T) {
// Spin up a HTTP server with the right values
createMockHTTPServer(400)
defer httpmock.DeactivateAndReset()
c := createResponseChannel()

endpoint, attack := CreateTestEndpointAndAttackConfiguration("400", "URL_QUERY_SPAM")

go RunUrlQuery(endpoint, attack, c)

response := <- c

if !response.Passed {
t.Error("Valid config which should have passed provided, but reported as failing")
}

endpoint, attack = CreateTestEndpointAndAttackConfiguration("200", "URL_QUERY_SPAM")

go RunUrlQuery(endpoint, attack, c)

response = <- c

if response.Passed {
t.Error("Valid config which should not have passed provided, but reported as passing.")
}
})
}

func createMockHTTPServer(status int) {
httpmock.Activate()

httpmock.RegisterResponder("GET", "http://localhost:8080/my-endpoint",
httpmock.NewStringResponder(200, `[{"something": 1}]`))
httpmock.NewStringResponder(status, `[{"something": 1}]`))
}

func createMockTcpServer() {
Expand All @@ -81,7 +110,7 @@ func createMockTcpServer() {
fmt.Println("Mock TCP Server returning 200")
conn.Write([]byte("MOCK RESPONSE: 200\n"))
defer conn.Close()

count ++

if(count == 2) {
Expand Down
1 change: 1 addition & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type AttackConfig struct {
Concurrents int `json:"concurrents"`
MessagesPerConcurrent int `json:"messagesPerConcurrent"`
Method string `json:"method"`
Parameters string `json:"parameters"`
}

func GetConfig(configPath string) (*Config) {
Expand Down
5 changes: 5 additions & 0 deletions examples/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
{
"type": "CORRUPT_HTTP",
"expectedStatus": "400"
},
{
"type": "URL_QUERY_SPAM",
"expectedStatus": "400",
"parameters": "a,b,c"
}
]
},
Expand Down
10 changes: 5 additions & 5 deletions monkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func main() {
}

func wakeTheMonkey(config *Config) {
fmt.Println("🐒 Waking the Monkey 🐒")
fmt.Println("🐒 Waking the Monkey")
responseChannel := make(chan Response)
SetupTargets(config, responseChannel)
listenForResponses(responseChannel)
Expand All @@ -28,18 +28,18 @@ func listenForResponses(responseChannel chan Response) {
response := <- responseChannel

if response.Passed {
fmt.Printf("✅ Attack %s Passed\n", response.AttackConfig.Type)
fmt.Printf("✅ Attack %s Passed\n", response.AttackConfig.Type)
} else {
fmt.Printf("❌ Attack %s Failed\n", response.AttackConfig.Type)
fmt.Printf("❌ Reason: %s\n", response.Report)
fmt.Printf("❌ Attack %s Failed\n", response.AttackConfig.Type)
fmt.Printf("❌ Reason: %s\n", response.Report)
}
}
}

// Sets up the targets in the config file for attack.
func SetupTargets(config *Config, responseChannel chan Response) {
for _,endpoint := range config.Endpoints {
fmt.Printf("🎯 Setting up %s 🎯\n", endpoint.Name)
fmt.Printf("🎯 Setting up %s\n", endpoint.Name)
setupAttackThreads(endpoint, responseChannel)
}
}
Expand Down
2 changes: 1 addition & 1 deletion monkey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ func TestSetupAttackThreads(t *testing.T) {
t.Run("Test that the monkey correctly reports failing attacks", func(t *testing.T) {
MAX_TIME_BETWEEN_ATTACKS = 20
responseChannel := make(chan Response)
config := CreateFullTestConfiguration()
config := CreateFullTestConfiguration("200", "HTTP_SPAM")

go SetupTargets(&config, responseChannel)

Expand Down
8 changes: 4 additions & 4 deletions testingUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
package main

// Creates configuration objects for an endpoint and an attack. Useful for testing specific attacks.
func CreateTestEndpointAndAttackConfiguration(expectedStatus string) (EndpointConfig, AttackConfig) {
func CreateTestEndpointAndAttackConfiguration(expectedStatus string, attackType string) (EndpointConfig, AttackConfig) {
endpoint := EndpointConfig{Name:"Test Endpoint", Protocol:"http",Host:"localhost",Port:"8080",Path:"/my-endpoint"}
attack := AttackConfig{Type:"HTTP_SPAM",Concurrents:1,MessagesPerConcurrent:1,ExpectedStatus:expectedStatus,Method:"GET"}
attack := AttackConfig{Type:attackType,Parameters:"a,b,c",Concurrents:1,MessagesPerConcurrent:1,ExpectedStatus:expectedStatus,Method:"GET"}

return endpoint, attack
}

// Creates a full config object with an endpoint and an attack. Useful for testing whole app.
func CreateFullTestConfiguration() Config {
func CreateFullTestConfiguration(expectedStatus string, attackType string) Config {
config := Config{}

endpoint, attack := CreateTestEndpointAndAttackConfiguration("200")
endpoint, attack := CreateTestEndpointAndAttackConfiguration(expectedStatus, attackType)

config.Endpoints = append(config.Endpoints, endpoint)
config.Endpoints[0].Attacks = append(config.Endpoints[0].Attacks, attack)
Expand Down

0 comments on commit a08b0de

Please sign in to comment.