Skip to content

Commit

Permalink
Match: Request & response matching
Browse files Browse the repository at this point in the history
  • Loading branch information
joanlopez committed Apr 7, 2024
1 parent 0586a02 commit 9c70938
Show file tree
Hide file tree
Showing 11 changed files with 780 additions and 0 deletions.
57 changes: 57 additions & 0 deletions internal/match/extractor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package match

import (
"strconv"
"strings"

"github.com/bountysecurity/gbounty/internal/profile"
"github.com/bountysecurity/gbounty/internal/request"
"github.com/bountysecurity/gbounty/internal/response"
)

func bytesToFindIn(g profile.Grep, req *request.Request, res *response.Response) (int, []byte) {
if len(g.Where) == 0 && res == nil ||
len(g.Where) > 0 && req == nil {
return 0, []byte{}
}

// Find grep in response
if len(g.Where) == 0 {
return resBytesToFindIn(g, res)
}

// Find grep in request
return reqBytesToFindIn(g.Where, req)
}

func resBytesToFindIn(g profile.Grep, res *response.Response) (int, []byte) {
headers := res.BytesOnlyHeaders()
lenHeaders := len(headers) + len("\r\n")
lenStatusLine := len(res.Proto + " " + strconv.Itoa(res.Code) + " " + res.Status + "\r\n")

switch {
case g.Option.OnlyInHeaders():
return lenStatusLine, res.BytesOnlyHeaders()
case g.Option.NotInHeaders():
return lenHeaders, res.BytesWithoutHeaders()
default:
return 0, res.Bytes()
}
}

func reqBytesToFindIn(where string, req *request.Request) (int, []byte) {
switch {
case strings.HasPrefix(where, "All"):
return reqBytesToFindInAll(where, req)
case strings.HasPrefix(where, "Url"):
return reqBytesToFindInURL(where, req)
case strings.HasPrefix(where, "Param"):
return reqBytesToFindInParam(where, req)
case strings.HasPrefix(where, "Entire"):
return reqBytesToFindInEntire(where, req)
case strings.HasPrefix(where, "HTTP"):
return reqBytesToFindInHTTP(where, req)
}

return 0, []byte{}
}
162 changes: 162 additions & 0 deletions internal/match/extractor_req.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package match

import (
"github.com/bountysecurity/gbounty/internal/request"
)

func reqBytesToFindInAll(where string, req *request.Request) (int, []byte) {
switch where {
case "All request":
return 0, req.Bytes()
case "All parameters name":
return 0, reqParamNameBytes(req)
case "All parameters value":
return 0, reqParamValueBytes(req)
case "All HTTP headers value":
return 0, req.HeaderBytes()
}

return 0, []byte{}
}

func reqBytesToFindInURL(where string, req *request.Request) (int, []byte) {
switch where {
case "Url path folder":
return 0, reqURLFolderBytes(req)
case "Url path filename":
return 0, reqURLFileBytes(req)
}

return 0, []byte{}
}

func reqBytesToFindInParam(where string, req *request.Request) (int, []byte) {
switch where {
case "Param url name":
return 0, reqQueryNameBytes(req)
case "Param url value":
return 0, reqQueryValueBytes(req)
case "Param body name":
return 0, reqBodyNameBytes(req)
case "Param body value":
return 0, reqBodyValueBytes(req)
case "Param cookie name":
return 0, reqCookieNameBytes(req)
case "Param cookie value":
return 0, reqCookieValueBytes(req)
case "Param json name":
return 0, reqJSONNameBytes(req)
case "Param json value":
return 0, reqJSONValueBytes(req)
case "Param xml name":
return 0, reqXMLNameBytes(req)
case "Param xml value":
return 0, reqXMLValueBytes(req)
case "Param xml attr name":
return 0, reqXMLAttrNameBytes(req)
case "Param xml attr value":
return 0, reqXMLAttrValueBytes(req)
case "Param multipart attr name":
return 0, reqMultipartNameBytes(req)
case "Param multipart attr value":
return 0, reqMultipartValueBytes(req)
}

return 0, []byte{}
}

func reqBytesToFindInEntire(where string, req *request.Request) (int, []byte) {
switch where {
case "Entire body":
return 0, req.Body
case "Entire body xml":
return 0, reqBodyXMLBytes(req)
case "Entire body json":
return 0, reqBodyJSONBytes(req)
case "Entire body multipart":
return 0, reqBodyMultipartBytes(req)
}

return 0, []byte{}
}

func reqBytesToFindInHTTP(where string, req *request.Request) (int, []byte) {
switch where {
case "HTTP host header":
return 0, []byte(req.Header("Host"))
case "HTTP user agent header":
return 0, []byte(req.Header("User-Agent"))
case "HTTP content type header":
return 0, []byte(req.Header("Content-Type"))
case "HTTP referer header":
return 0, []byte(req.Header("Referer"))
case "HTTP origin header":
return 0, []byte(req.Header("Origin"))
case "HTTP accept encoding header":
return 0, []byte(req.Header("Accept-Encoding"))
case "HTTP accept header":
return 0, []byte(req.Header("Accept"))
case "HTTP accept language header":
return 0, []byte(req.Header("Accept-Language"))
}

return 0, []byte{}
}

func reqParamNameBytes(req *request.Request) []byte {
bodyNameBytes := reqBodyNameBytes(req)
cookieNameBytes := reqCookieNameBytes(req)
jsonNameBytes := reqJSONNameBytes(req)
multipartNameBytes := reqMultipartNameBytes(req)
queryNameBytes := reqQueryNameBytes(req)
xmlNameBytes := reqXMLNameBytes(req)
xmlAttrNameBytes := reqXMLAttrNameBytes(req)

totalLen := len(bodyNameBytes) + len(cookieNameBytes) + len(jsonNameBytes) +
len(multipartNameBytes) + len(queryNameBytes) + len(xmlNameBytes) + len(xmlAttrNameBytes)

paramNameBytes := make([]byte, 0, totalLen)

for _, b := range [][]byte{
bodyNameBytes,
cookieNameBytes,
jsonNameBytes,
multipartNameBytes,
queryNameBytes,
xmlNameBytes,
xmlAttrNameBytes,
} {
paramNameBytes = append(paramNameBytes, b...)
}

return paramNameBytes
}

func reqParamValueBytes(req *request.Request) []byte {
bodyValueBytes := reqBodyValueBytes(req)
cookieValueBytes := reqCookieValueBytes(req)
jsonValueBytes := reqJSONValueBytes(req)
multipartValueBytes := reqMultipartValueBytes(req)
queryValueBytes := reqQueryValueBytes(req)
xmlValueBytes := reqXMLValueBytes(req)
xmlAttrValueBytes := reqXMLAttrValueBytes(req)

totalLen := len(bodyValueBytes) + len(cookieValueBytes) + len(jsonValueBytes) +
len(multipartValueBytes) + len(queryValueBytes) + len(xmlValueBytes) + len(xmlAttrValueBytes)

paramValueBytes := make([]byte, 0, totalLen)

for _, b := range [][]byte{
bodyValueBytes,
cookieValueBytes,
jsonValueBytes,
multipartValueBytes,
queryValueBytes,
xmlValueBytes,
xmlAttrValueBytes,
} {
paramValueBytes = append(paramValueBytes, b...)
}

return paramValueBytes
}
49 changes: 49 additions & 0 deletions internal/match/extractor_req_body.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package match

import (
"github.com/bountysecurity/gbounty/internal/entrypoint"
"github.com/bountysecurity/gbounty/internal/profile"
"github.com/bountysecurity/gbounty/internal/request"
)

func reqBodyXMLBytes(req *request.Request) []byte {
if !req.HasXMLBody() {
return []byte{}
}

return req.Body
}

func reqBodyJSONBytes(req *request.Request) []byte {
if !req.HasJSONBody() {
return []byte{}
}

return req.Body
}

func reqBodyMultipartBytes(req *request.Request) []byte {
if !req.HasMultipartBody() {
return []byte{}
}

return req.Body
}

func reqBodyNameBytes(req *request.Request) []byte {
return reqBodyBytes(req, profile.ParamBodyName)
}

func reqBodyValueBytes(req *request.Request) []byte {
return reqBodyBytes(req, profile.ParamBodyValue)
}

func reqBodyBytes(req *request.Request, ipt profile.InsertionPointType) []byte {
var b []byte
for _, e := range entrypoint.NewBodyParamFinder().Find(*req) {
if v, ok := e.(entrypoint.BodyParam); ok && v.InsertionPointType() == ipt {
b = append(b, []byte(v.Value())...)
}
}
return b
}
25 changes: 25 additions & 0 deletions internal/match/extractor_req_cookie.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package match

import (
"github.com/bountysecurity/gbounty/internal/entrypoint"
"github.com/bountysecurity/gbounty/internal/profile"
"github.com/bountysecurity/gbounty/internal/request"
)

func reqCookieNameBytes(req *request.Request) []byte {
return reqCookieBytes(req, profile.CookieName)
}

func reqCookieValueBytes(req *request.Request) []byte {
return reqCookieBytes(req, profile.CookieValue)
}

func reqCookieBytes(req *request.Request, ipt profile.InsertionPointType) []byte {
var b []byte
for _, e := range entrypoint.NewCookieFinder().Find(*req) {
if v, ok := e.(entrypoint.Cookie); ok && v.InsertionPointType() == ipt {
b = append(b, []byte(v.Value())...)
}
}
return b
}
25 changes: 25 additions & 0 deletions internal/match/extractor_req_json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package match

import (
"github.com/bountysecurity/gbounty/internal/entrypoint"
"github.com/bountysecurity/gbounty/internal/profile"
"github.com/bountysecurity/gbounty/internal/request"
)

func reqJSONNameBytes(req *request.Request) []byte {
return reqJSONBytes(req, profile.ParamJSONName)
}

func reqJSONValueBytes(req *request.Request) []byte {
return reqJSONBytes(req, profile.ParamJSONValue)
}

func reqJSONBytes(req *request.Request, ipt profile.InsertionPointType) []byte {
var b []byte
for _, e := range entrypoint.NewJSONParamFinder().Find(*req) {
if v, ok := e.(entrypoint.JSONParam); ok && v.InsertionPointType() == ipt {
b = append(b, []byte(v.Value())...)
}
}
return b
}
25 changes: 25 additions & 0 deletions internal/match/extractor_req_multipart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package match

import (
"github.com/bountysecurity/gbounty/internal/entrypoint"
"github.com/bountysecurity/gbounty/internal/profile"
"github.com/bountysecurity/gbounty/internal/request"
)

func reqMultipartNameBytes(req *request.Request) []byte {
return reqMultipartBytes(req, profile.ParamMultiAttrName)
}

func reqMultipartValueBytes(req *request.Request) []byte {
return reqMultipartBytes(req, profile.ParamMultiAttrValue)
}

func reqMultipartBytes(req *request.Request, ipt profile.InsertionPointType) []byte {
var b []byte
for _, e := range entrypoint.NewMultipartFinder().Find(*req) {
if v, ok := e.(entrypoint.Multipart); ok && v.InsertionPointType() == ipt {
b = append(b, []byte(v.Value())...)
}
}
return b
}
25 changes: 25 additions & 0 deletions internal/match/extractor_req_query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package match

import (
"github.com/bountysecurity/gbounty/internal/entrypoint"
"github.com/bountysecurity/gbounty/internal/profile"
"github.com/bountysecurity/gbounty/internal/request"
)

func reqQueryNameBytes(req *request.Request) []byte {
return reqQueryBytes(req, profile.ParamURLName)
}

func reqQueryValueBytes(req *request.Request) []byte {
return reqQueryBytes(req, profile.ParamURLValue)
}

func reqQueryBytes(req *request.Request, ipt profile.InsertionPointType) []byte {
var b []byte
for _, e := range entrypoint.NewQueryFinder().Find(*req) {
if v, ok := e.(entrypoint.Query); ok && v.InsertionPointType() == ipt {
b = append(b, []byte(v.Value())...)
}
}
return b
}
Loading

0 comments on commit 9c70938

Please sign in to comment.