Skip to content

Commit

Permalink
feat: add matching for headers and body
Browse files Browse the repository at this point in the history
  • Loading branch information
louonezime committed Jul 16, 2024
1 parent 67fbe65 commit 80bb47e
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 11 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ For example, `./bruteforce -status-codes="200,201,202,401,404"`.

*By default* : 200, 401, 403, 404, 429, 500

`-header` : match based on a header.

For example, `./bruteforce -header="Content-Type: application/json"`.

`-body` : match based on a body.

For example, `./bruteforce -body="Hello World"`.

## Get involved

You're invited to join this project ! Check out the [contributing guide](./CONTRIBUTING.md).
Expand Down
4 changes: 3 additions & 1 deletion src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
func main() {
usagePtr := flag.Bool("help", false, "a bool")
statusPtr := flag.String("status-codes", "200,401,403,404,429,500", "Comma-separated list of status codes to match")
headerPtr := flag.String("header", "", "Header to match")
bodyPtr := flag.String("body", "", "String to match in response body")

flag.Parse()
if *usagePtr {
Expand All @@ -18,5 +20,5 @@ func main() {
fmt.Println("\t\t\t[By default: 200,401,403,404,429,500]")
return;
}
matcher.MatchParser("http://example.com", *statusPtr)
matcher.MatchParser("http://example.com", *statusPtr, *headerPtr, *bodyPtr)
}
10 changes: 10 additions & 0 deletions src/matching/body.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package matcher

import "strings"

func matchContents(body []byte, criteria MatchCriteria) (bool, string) {
if criteria.BodyContains != "" && !strings.Contains(string(body), criteria.BodyContains) {
return false, "body content mismatch"
}
return true, "body content matches"
}
36 changes: 36 additions & 0 deletions src/matching/headers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package matcher

import (
"fmt"
"strings"
"net/http"
"log"
)

func matchHeaders(resp *http.Response, criteria MatchCriteria) (bool, string) {
for key, value := range criteria.Headers {
if resp.Header.Get(key) != value {
return false, fmt.Sprintf("header mismatch: %s=%s", key, value)
}
}
return true, "headers match"
}

func parseHeaders(headersList string) map[string]string {
if headersList == "" {
return nil
}

headers := make(map[string]string)
headerPairs := strings.Split(headersList, ",")

for _, pair := range headerPairs {
parts := strings.SplitN(pair, ":", 2)
if len(parts) == 2 {
headers[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
} else {
log.Printf("[WARN] Invalid header format: %s", pair)
}
}
return headers
}
39 changes: 37 additions & 2 deletions src/matching/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,50 @@ package matcher

import (
"log"
"io/ioutil"
"fmt"
"net/http"
)

func MatchParser(url string, statuses string) {
type MatchCriteria struct {
StatusCodes []int
Headers map[string]string
BodyContains string
}

func matchResponse(url string, criteria MatchCriteria) (bool, string) {
resp, err := http.Get(url)
if err != nil {
return false, err.Error()
}
defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return false, err.Error()
}

matchStatusCode(resp, criteria.StatusCodes)
matchHeaders(resp, criteria)
matchContents(body, criteria)

return false, fmt.Sprintf("status code is %d", resp.StatusCode)
}

func MatchParser(url string, statuses string, headers string, bodyContains string) {
matchCodes, err := parseStatusCodes(statuses)
if err != nil {
log.Fatal("Error parsing status codes:", err)
}

matched, msg := matchStatusCode(url, matchCodes)
matchHeaders := parseHeaders(headers)
criteria := MatchCriteria{
StatusCodes: matchCodes,
Headers: matchHeaders,
BodyContains: bodyContains,
}

matched, msg := matchResponse(url, criteria)
if matched {
log.Println("Matched:", msg)
} else {
Expand Down
9 changes: 1 addition & 8 deletions src/matching/status_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,8 @@ import (
"log"
)


func matchStatusCode(url string, matchCodes []int) (bool, string) {
func matchStatusCode(resp *http.Response, matchCodes []int) (bool, string) {
isAll := false
resp, err := http.Get(url)
if err != nil {
return false, err.Error()
}
defer resp.Body.Close()

if matchCodes[0] == 0 {
isAll = !isAll;
Expand All @@ -31,7 +25,6 @@ func matchStatusCode(url string, matchCodes []int) (bool, string) {

func parseStatusCodes(statusCodeList string) ([]int, error) {
codeStrs := strings.Split(statusCodeList, ",")

if statusCodeList == "all" {
log.Println("Matching all status codes")
return []int{0}, nil
Expand Down

0 comments on commit 80bb47e

Please sign in to comment.