Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added --data and --method #21

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 36 additions & 21 deletions autocompletion/bash/_bruteforce
Original file line number Diff line number Diff line change
@@ -1,28 +1,43 @@
#!/bin/bash
_bruteforce() {
local cur prev opts methods

_bruteforce_completion() {
local cur prev opts
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--threads -v --status-codes --header --body --wordlist"

if [[ ${COMP_CWORD} -eq 1 ]]; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
elif [[ ${COMP_CWORD} -eq 2 ]]; then
case "${prev}" in
--threads)
COMPREPLY=( $(compgen -W "1 2 4 8 16 32" -- "${cur}") )
;;
--status-codes)
COMPREPLY=( $(compgen -W "200 401 403 404 429 500" -- "${cur}") )
;;
--header|--body|--wordlist)
COMPREPLY=()
;;
esac
else
COMPREPLY=( $(compgen -W "http:// https://" -- "${cur}") )
opts="-v --threads --status-codes --header --body --wordlist --method --data"

methods="POST GET PUT PATCH DELETE HEAD OPTIONS"

case "$prev" in
--threads)
COMPREPLY=( $(compgen -W "1 2 4 8 16 32" -- "$cur") )
return 0
;;
--status-codes)
COMPREPLY=( $(compgen -W "200 401 403 404 429 500" -- "$cur") )
return 0
;;
--method)
COMPREPLY=( $(compgen -W "$methods" -- "$cur") )
return 0
;;
--wordlist)
COMPREPLY=( $(compgen -f -- "$cur") )
return 0
;;
--header|--body|--data)
return 0
;;
*)
;;
esac

if [[ "$cur" == http* ]]; then
COMPREPLY=( $(compgen -W "http:// https://" -- "$cur") )
return 0
fi

COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
}

complete -F _bruteforce_completion bruteforce
complete -F _bruteforce bruteforce
4 changes: 3 additions & 1 deletion autocompletion/zsh/_bruteforce
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ _bruteforce() {
args=(
'-v[verbose mode]'
'--threads=[number of threads]:number of threads:(1 2 4 8 16 32)'
'--status-codes=[Comma-separated list of status codes to match]:status codes:'
'--status-codes=[Comma-separated list of status codes to match]:codes:(200 401 403 404 429 500)'
'--header=[Header to match]:header:'
'--body=[String to match in response body]:body:'
'--wordlist=[Wordlist to bruteforce URLs with]:wordlist:_files'
'--method=[Method to bruteforce with]:methodes:(POST GET PUT PATCH DELETE HEAD OPTIONS)'
'--data=[JSON Data to inlude in body when bruteforcing]':data
'*:url:_bruteforce_urls'
)

Expand Down
45 changes: 33 additions & 12 deletions src/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,49 @@ package cli
import (
"bruteforce/src/matching"
"bruteforce/src/models"
"encoding/json"
"errors"
"flag"
"fmt"
"os"
)

func errorHandling(params models.ForcingParams) (models.ForcingParams, error) {
ThreadsError := errors.New("wrong number of threads given")
WordListError := errors.New("no wordlist given")
DataError := errors.New("Invalid JSON data")
methodError := errors.New("Invalid HTTP method")
var method_list = [7]string{"POST", "GET", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}

if params.Data != "" && !json.Valid([]byte(params.Data)) {
return params, DataError
}
if params.Workers < 1 {
return params, ThreadsError
}
if params.Wordlist == "" {
return params, WordListError
}
for i := 0; i < 7; i++ {
if params.Method == method_list[i] {
return params, nil
}
}
return params, methodError
}

func ParseCliArgs() (models.ForcingParams, error) {
var params models.ForcingParams

UrlError := errors.New("no url given")
ThreadsError := errors.New("wrong number of threads given")
WordListError := errors.New("no wordlist given")

forkptr := flag.Bool("v", false, "Verbose program")
printbodyptr := flag.Bool("p", false, "Prints body when matched")
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, formatted as \"key: value\"")
bodyPtr := flag.String("body", "", "String to match in response body")
wordlistPtr := flag.String("wordlist", "default-wordlist.txt", "Wordlist to bruteforce url with")
wordlistPtr := flag.String("wordlist", "", "Wordlist to bruteforce url with")
methodPtr := flag.String("method", "POST", "Method to bruteforce with")
postDataptr := flag.String("data", "", "JSON Data to inlude in body when bruteforcing")
flag.IntVar(&params.Workers, "threads", 1, "Number of threads to be used")

flag.Usage = func() {
Expand All @@ -39,13 +64,9 @@ func ParseCliArgs() (models.ForcingParams, error) {
params.BoolFlags.Verbose = *forkptr
params.Wordlist = *wordlistPtr
params.Criteria = matcher.MatchParser(*statusPtr, *headerPtr, *bodyPtr)
params.Data = *postDataptr
params.Method = *methodPtr
params.BoolFlags.BodyToFile = *printbodyptr

if params.Workers < 1 {
return params, ThreadsError
}
if params.Wordlist == "" {
return params, WordListError
}

return params, nil
return errorHandling(params)
}
5 changes: 2 additions & 3 deletions src/matching/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"net/http"
)

func MatchResponse(response *http.Response, body []byte, criteria models.MatchCriteria) error {
if err := matchStatusCode(response, criteria); err != nil {
func MatchResponse(response *http.Response, body []byte, criteria models.MatchCriteria, params *models.ForcingParams) error {
if err := matchStatusCode(response, criteria, params); err != nil {
return err
}
if err := matchHeaders(response, criteria); err != nil {
Expand All @@ -16,7 +16,6 @@ func MatchResponse(response *http.Response, body []byte, criteria models.MatchCr
if err := matchContents(body, criteria); err != nil {
return err
}

return nil
}

Expand Down
6 changes: 4 additions & 2 deletions src/matching/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (
"strings"
)

func matchStatusCode(resp *http.Response, criteria models.MatchCriteria) error {
func matchStatusCode(resp *http.Response, criteria models.MatchCriteria, params *models.ForcingParams) error {
isAll := false

if criteria.StatusCodes[0] == 0 {
isAll = !isAll
} else {
log.Printf("Matching status codes %d...", criteria.StatusCodes)
if params.BoolFlags.Verbose {
log.Printf("Matching status codes %d...", criteria.StatusCodes)
}
}
for _, code := range criteria.StatusCodes {
if resp.StatusCode == code || isAll {
Expand Down
5 changes: 4 additions & 1 deletion src/models/models.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package models

type boolflags struct {
Verbose bool
Verbose bool
BodyToFile bool
}

type HeaderMatch struct {
Expand All @@ -26,4 +27,6 @@ type ForcingParams struct {
Wordlist string
BoolFlags boolflags
Criteria MatchCriteria
Data string
Method string
}
2 changes: 1 addition & 1 deletion src/query/callWorker.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func executeQueryFromFile(wg *sync.WaitGroup, params *models.ForcingParams, curr
}

for taskData := range currentPath {
QueryExecute(params, taskData, "POST")
QueryExecute(params, taskData, params.Method)
}
}

Expand Down
22 changes: 16 additions & 6 deletions src/query/queryExecute.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package query
import (
"bruteforce/src/matching"
"bruteforce/src/models"
"bytes"
"fmt"
"io"
"log"
Expand All @@ -11,12 +12,16 @@ import (

func QueryExecute(params *models.ForcingParams, path string, method string) {
client := &http.Client{}
req, err := http.NewRequest(method, params.Url+path, nil)
body_req := []byte(params.Data)

req, err := http.NewRequest(method, params.Url+path, bytes.NewBuffer(body_req))

if err != nil {
log.Fatal(err)
}
log.Printf("NewRequest(%s)", params.Url+path)

if params.BoolFlags.Verbose {
log.Printf("NewRequest(%s)", params.Url+path)
}
q := req.URL.Query()
req.URL.RawQuery = q.Encode()

Expand All @@ -31,9 +36,14 @@ func QueryExecute(params *models.ForcingParams, path string, method string) {
log.Fatal(err)
}

if err := matcher.MatchResponse(resp, body, params.Criteria); err == nil {
fmt.Println(string(body))
if err := matcher.MatchResponse(resp, body, params.Criteria, params); err == nil {
if params.BoolFlags.BodyToFile {
fmt.Println(string(body))
}
log.Printf("Successfully Matched %s", params.Url+path)
} else {
log.Println(err)
if params.BoolFlags.Verbose {
log.Println(err)
}
}
}
Loading