Skip to content

Commit

Permalink
run basic api test
Browse files Browse the repository at this point in the history
  • Loading branch information
dmdhrumilmistry committed Jul 13, 2024
1 parent 838f340 commit cda96f2
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 36 deletions.
43 changes: 22 additions & 21 deletions src/cmd/offat/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import (
"github.com/OWASP/OFFAT/src/pkg/http"
_ "github.com/OWASP/OFFAT/src/pkg/logging"
"github.com/OWASP/OFFAT/src/pkg/parser"
"github.com/OWASP/OFFAT/src/pkg/tgen"
"github.com/OWASP/OFFAT/src/pkg/utils"
c "github.com/dmdhrumilmistry/fasthttpclient/client"
"github.com/rs/zerolog/log"

"github.com/valyala/fasthttp"
)

type CliConfig struct {
Expand Down Expand Up @@ -76,40 +74,43 @@ func main() {
os.Exit(1)
}

err := parser.Doc.SetBaseUrl(*config.BaseUrl)
if err != nil {
log.Error().Err(err).Msg("failed to set baseUrl")
}
log.Print(parser.Doc.GetBaseUrl())

if err := parser.Doc.SetDocHttpParams(); err != nil {
log.Error().Stack().Err(err).Msg("failed while fetching doc http params")
}

log.Info().Msg("fuzzing doc http params")
parser.FuzzDocHttpParams()
log.Info().Msgf("%v", parser.Doc.GetDocHttpParams())
// log.Info().Msgf("%v", parser.Doc.GetDocHttpParams())

// http client
httpCfg := http.NewConfig(config.RequestsPerSecond, config.SkipTlsVerfication)
hc := http.NewHttp(httpCfg)
client := hc.Client.FHClient

err := parser.Doc.SetBaseUrl(*config.BaseUrl)
if err != nil {
log.Error().Err(err).Msg("failed to set baseUrl")
}

// TODO: check whether host is up
url := *parser.Doc.GetBaseUrl()
log.Info().Msg(url)

hc.Requests = append(hc.Requests, c.NewRequest(url, fasthttp.MethodGet, nil, nil, nil))
hc.Requests = append(hc.Requests, c.NewRequest(url, fasthttp.MethodGet, nil, nil, nil))
hc.Requests = append(hc.Requests, c.NewRequest(url, fasthttp.MethodGet, nil, nil, nil))
hc.Requests = append(hc.Requests, c.NewRequest(url, fasthttp.MethodGet, nil, nil, nil))

hc.Responses = c.MakeConcurrentRequests(hc.Requests, client)
for _, connResp := range hc.Responses {
if connResp.Error != nil {
log.Error().Stack().Err(connResp.Error).Msg("request failed")
} else {
log.Info().Msgf("Status Code: %v - Time: %v", connResp.Response.StatusCode, connResp.Response.TimeElapsed)
}
// generate and run tests
apiTestHandler := tgen.TGenHandler{
Doc: parser.Doc.GetDocHttpParams(),

// Tests
RunUnrestrictedHttpMethodTest: true,
}

apiTests := apiTestHandler.GenerateTests()

apiTestHandler.RunApiTests(hc, client, apiTests)

log.Info().Msgf("Total Requests: %d", len(hc.Requests))

elapsed := time.Since(now)
log.Info().Msgf("Time: %v", elapsed)
}
7 changes: 6 additions & 1 deletion src/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/OWASP/OFFAT/src
go 1.22.4

require (
github.com/dmdhrumilmistry/fasthttpclient v1.1.0
github.com/dmdhrumilmistry/fasthttpclient v1.2.0
github.com/getkin/kin-openapi v0.126.0
github.com/rs/zerolog v1.33.0
github.com/valyala/fasthttp v1.55.0
Expand All @@ -19,17 +19,22 @@ require (
github.com/go-resty/resty/v2 v2.13.1 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/li-jin-gou/http2curl v0.1.2 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/schollz/progressbar/v3 v3.14.4 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/term v0.22.0 // indirect
golang.org/x/time v0.5.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
15 changes: 13 additions & 2 deletions src/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dmdhrumilmistry/fasthttpclient v1.1.0 h1:Uz6PJ/vNeM0ZUdMwYPkNJ2K+nUpJKV8Ss4tKmdCovno=
github.com/dmdhrumilmistry/fasthttpclient v1.1.0/go.mod h1:fo/plSd6tHxOK7xLptYrU4hM/dpRc9mSg0uqyPkWmrg=
github.com/dmdhrumilmistry/fasthttpclient v1.2.0 h1:cKwDbKirg7FUIdV55iVPyUcLBeO+lOAYxRU1D4YO1ZY=
github.com/dmdhrumilmistry/fasthttpclient v1.2.0/go.mod h1:9pu2ZL89sQPO1RD2me+YBOo8nnslsqnRNJb8S0zBBa0=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/getkin/kin-openapi v0.126.0 h1:c2cSgLnAsS0xYfKsgt5oBV6MYRM/giU8/RtwUY4wyfY=
github.com/getkin/kin-openapi v0.126.0/go.mod h1:7mONz8IwmSRg6RttPu6v8U/OJ+gr+J99qSFNjPGSQqw=
Expand All @@ -43,6 +43,8 @@ github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
Expand All @@ -60,6 +62,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/nyaruka/phonenumbers v1.0.55/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U=
Expand All @@ -69,16 +73,21 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/schollz/progressbar/v3 v3.14.4 h1:W9ZrDSJk7eqmQhd3uxFNNcTr0QL+xuGNI9dEMrw0r74=
github.com/schollz/progressbar/v3 v3.14.4/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down Expand Up @@ -145,6 +154,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
Expand Down
18 changes: 11 additions & 7 deletions src/pkg/parser/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/OWASP/OFFAT/src/pkg/utils"
"github.com/getkin/kin-openapi/openapi3"
"github.com/rs/zerolog/log"
"github.com/valyala/fasthttp"
)

Expand Down Expand Up @@ -62,7 +63,7 @@ func (o *OpenApi) AssignParamsToSlices(params openapi3.Parameters, httpPathParam
}
}

func (o *OpenApi) HttpOperationToDocHttpParams(HttpMethod string, path string, httpOperation *openapi3.Operation, pathParams []Param) []*DocHttpParams {
func (o *OpenApi) HttpOperationToDocHttpParams(HttpMethod, path string, httpOperation *openapi3.Operation, pathParams []Param) []*DocHttpParams {
var docHttpParams []*DocHttpParams
var queryParams []Param
var bodyParams []Param
Expand Down Expand Up @@ -121,8 +122,17 @@ func (o *OpenApi) HttpOperationToDocHttpParams(HttpMethod string, path string, h
}
}

var url string
if o.BaseUrl == nil {
log.Error().Msg("field BaseUrl not set")
url = ""
} else {
url = *o.BaseUrl + path
}

// Create DocHttpParams Instance
docHttpParam := &DocHttpParams{
Url: url,
HttpMethod: HttpMethod,
Path: path,
Security: securitySchemes,
Expand All @@ -145,12 +155,6 @@ func (o *OpenApi) SetBaseUrl(baseUrl string) error {
if utils.ValidateURL(baseUrl) {
o.BaseUrl = &baseUrl
} else {
// basePath, err := o.doc.Servers.BasePath()
// if err != nil {
// return err
// }
// o.BaseUrl = &basePath

for _, server := range o.doc.Servers {
o.BaseUrl = &server.URL
if strings.HasPrefix(server.URL, "https://") {
Expand Down
1 change: 1 addition & 0 deletions src/pkg/parser/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func (p *Param) String() string {
type DocHttpParams struct {
// Request Information
HttpMethod string
Url string
Path string

// Security Requirements
Expand Down
14 changes: 10 additions & 4 deletions src/pkg/tgen/struct.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package tgen

type TestSchema struct {
TestName string
import "github.com/dmdhrumilmistry/fasthttpclient/client"

// Holds data related for API testing
type ApiTests struct {
// Fields to be populated before making HTTP request
TestName string
Request *client.Request

// Fields to be populated after making HTTP request
IsVulnerable bool
IsDataLeak bool
Request interface{}
Response interface{}
Response *client.Response
}
42 changes: 42 additions & 0 deletions src/pkg/tgen/tgen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package tgen

import (
"fmt"

"github.com/OWASP/OFFAT/src/pkg/http"
_ "github.com/OWASP/OFFAT/src/pkg/logging"
"github.com/OWASP/OFFAT/src/pkg/parser"
c "github.com/dmdhrumilmistry/fasthttpclient/client"
"github.com/rs/zerolog/log"
)

type TGenHandler struct {
RunUnrestrictedHttpMethodTest bool

Doc []*parser.DocHttpParams
DefaultQueryParams map[string]string
DefaultHeaders map[string]string
}

func (t *TGenHandler) GenerateTests() []*ApiTests {
tests := []*ApiTests{}
if t.RunUnrestrictedHttpMethodTest {
newTests := UnrestrictedHttpMethods(t.Doc, t.DefaultQueryParams, t.DefaultHeaders)
tests = append(tests, newTests...)

log.Info().Msgf("%d tests generated for Unrestricted HTTP Methods/Verbs", len(newTests))
}

return tests
}

func (t *TGenHandler) RunApiTests(hc *http.Http, client c.ClientInterface, apiTests []*ApiTests) {
// generate requests
for _, apiTest := range apiTests {
hc.Requests = append(hc.Requests, apiTest.Request)
}

// make requests to the server concurrently
hc.Responses = c.MakeConcurrentRequests(hc.Requests, client)
fmt.Print("\n")
}
40 changes: 39 additions & 1 deletion src/pkg/tgen/unrestrictedmethods.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
// Tests for unrestricted HTTP methods/verbs
package tgen

// use parser.DocHttpParams.
import (
"encoding/json"

_ "github.com/OWASP/OFFAT/src/pkg/logging"
"github.com/OWASP/OFFAT/src/pkg/parser"
c "github.com/dmdhrumilmistry/fasthttpclient/client"
"github.com/rs/zerolog/log"
)

// returns a new map with k:parser.DocHttpParams.Name, v:parser.DocHttpParams.Value
func UnrestrictedHttpMethods(docParams []*parser.DocHttpParams, queryParams any, headers any) []*ApiTests {
var tests []*ApiTests
testName := "Unrestricted HTTP Methods/Verbs"

for _, docParam := range docParams {
bodyMap := ParamsToMap(docParam.BodyParams) // convert it to map[string]interface{}

// convert it to JSON
jsonData, err := json.Marshal(bodyMap)
if err != nil {
log.Error().Stack().Err(err).Msg("failed to convert bodyMap to JSON")
} else {
jsonData = nil
}

// TODO: negate HTTP methods and add it to requests
// currently below request is only for testing purpose
log.Print(docParam.Url)
request := c.NewRequest(docParam.Url, docParam.HttpMethod, queryParams, headers, jsonData)

test := ApiTests{
TestName: testName,
Request: request,
}
tests = append(tests, &test)
}

return tests
}
14 changes: 14 additions & 0 deletions src/pkg/tgen/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package tgen

import "github.com/OWASP/OFFAT/src/pkg/parser"

// convert parser.Param to map
func ParamsToMap(params []parser.Param) map[string]interface{} {
paramMap := make(map[string]interface{})

for _, param := range params {
paramMap[param.Name] = param.Value
}

return paramMap
}

0 comments on commit cda96f2

Please sign in to comment.