Skip to content

Commit

Permalink
Added CI mode into the cli and into the app.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisCooney committed Sep 1, 2017
1 parent 105b0e0 commit c6867bf
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 22 deletions.
12 changes: 4 additions & 8 deletions attacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ 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)

c := make(chan *http.Response)

endpoint := BuildNetworkPath(endpointConfig.Protocol, endpointConfig.Host, endpointConfig.Port, endpointConfig.Path)
Expand Down Expand Up @@ -112,28 +110,26 @@ 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)
c := make(chan string)
endpoint := BuildNetworkPath("", endpointConfig.Host, endpointConfig.Port, "")

go SendCorruptHTTPData(endpoint, c)
rawResponse := <- c

if rawResponse == "" {
responseChannel <- Response{AttackConfig: attackConfig, Passed: false, Report: "Error occurred during corrupt HTTP attack. Expected valid response but got empty String."}
responseChannel <- Response{AttackConfig: attackConfig, Passed: false, Report: "Expected valid response but got empty String."}
return nil
}

if !strings.Contains(rawResponse, attackConfig.ExpectedStatus) {
responseChannel <- Response{AttackConfig: attackConfig, Passed: false, Report: fmt.Sprintf("Failure during Corrupt HTTP. Expected Status = %s | Actual Response = %s", attackConfig.ExpectedStatus, rawResponse)}
responseChannel <- Response{AttackConfig: attackConfig, Passed: false, Report: fmt.Sprintf("Expected Status = %s | Actual Response = %s", attackConfig.ExpectedStatus, rawResponse)}
}

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)
Expand All @@ -153,14 +149,14 @@ func RunUrlQuery(endpointConfig EndpointConfig, attackConfig AttackConfig, respo
responses := collectConcurrentHTTPResponses(c, len(params) * len(fakeValues))

if len(responses) == 0 {
responseChannel <- Response{AttackConfig: attackConfig, Passed: false, Report: "Error occurred during URL Query Spam."}
responseChannel <- Response{AttackConfig: attackConfig, Passed: false, Report: "Web Error Occurred."}
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)}
responseChannel <- Response{Expected: expected, Actual: actual, AttackConfig: attackConfig, Passed: false, Report: reason}
return nil
}

Expand Down
7 changes: 6 additions & 1 deletion cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ import (
)

var (
configPath = kingpin.Arg("config", "📚 Fuzz Monkey application configuration JSON file 📚").String()
ciMode = kingpin.Flag("ci-mode", "CI Mode").Short('c').Bool()
configPath = kingpin.Arg("config", "📚 Fuzz Monkey application configuration JSON file").String()
)

func GetConfigFromCli() (*Config) {
kingpin.Parse()
return GetConfig(*configPath)
}

func IsCIMode() bool {
return *ciMode
}
72 changes: 59 additions & 13 deletions monkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math/rand"
"time"
"errors"
"os"
)

var MAX_TIME_BETWEEN_ATTACKS = 60
Expand All @@ -13,7 +14,32 @@ var ATTACKS_STRATEGY = map[string](func(endpointConfig EndpointConfig, attackCon

func main() {
config := GetConfigFromCli()
wakeTheMonkey(config)

if IsCIMode() {
fmt.Println("🔨 CI Mode detected. Each attack configuration will be ran in sequence for all endpoints.")
performSequentialAttack(config)
} else {
wakeTheMonkey(config)
}
}

func performSequentialAttack(config *Config) {
isFailure := false;

for _,endpoint := range config.Endpoints {
for _,attack := range endpoint.Attacks {
response := executeAttackSync(endpoint, attack)

isFailure = isFailure && response.Passed
logResponse(response)
}
}

if isFailure {
os.Exit(1)
}

os.Exit(0)
}

func wakeTheMonkey(config *Config) {
Expand All @@ -26,13 +52,15 @@ func wakeTheMonkey(config *Config) {
func listenForResponses(responseChannel chan Response) {
for {
response := <- responseChannel
logResponse(response)
}
}

if response.Passed {
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)
}
func logResponse(response Response) {
if response.Passed {
fmt.Printf("✅ Attack %s Passed\n", response.AttackConfig.Type)
} else {
fmt.Printf("❌ Attack %s Failed: %s\n", response.AttackConfig.Type, response.Report)
}
}

Expand All @@ -52,15 +80,33 @@ func setupAttackThreads(endpoint EndpointConfig, responseChannel chan Response)

func beginHarassment(endpoint EndpointConfig, attack AttackConfig, responseChannel chan Response) {
for {
attackFunc, present := ATTACKS_STRATEGY[attack.Type]
executeAttack(endpoint, attack, responseChannel)
pauseForRandomDuration()
}
}

if !present {
panic(errors.New(fmt.Sprintf("Unknown attack type %s", attack.Type)))
}
func executeAttack(endpoint EndpointConfig, attack AttackConfig, responseChannel chan Response) {
attackFunc := getAttackFunction(attack)
go attackFunc(endpoint, attack, responseChannel)
}

go attackFunc(endpoint, attack, responseChannel)
pauseForRandomDuration()
func executeAttackSync(endpoint EndpointConfig, attack AttackConfig) Response {
attackFunc := getAttackFunction(attack)
responseChannel := make(chan Response)
go attackFunc(endpoint, attack, responseChannel)
response := <- responseChannel

return response
}

func getAttackFunction(attack AttackConfig) (func(endpointConfig EndpointConfig, attackConfig AttackConfig, responseChannel chan Response) error) {
attackFunc, present := ATTACKS_STRATEGY[attack.Type]

if !present {
panic(errors.New(fmt.Sprintf("Unknown attack type %s", attack.Type)))
}

return attackFunc
}

func pauseForRandomDuration() {
Expand Down

0 comments on commit c6867bf

Please sign in to comment.