diff --git a/src/README.md b/src/README.md index d355eaf..d04f614 100644 --- a/src/README.md +++ b/src/README.md @@ -6,6 +6,10 @@ Automatically Tests for vulnerabilities after generating tests from openapi spec ![UnDocumented petstore API endpoint HTTP method results](/assets/images/tests/offat-v0.5.0.png) +> [!WARNING] +> At the moment HTTP 2/3 aren't supported since fasthttpclient is used under the hood to increase performance. +> Visit [FastHTTP README](https://github.com/valyala/fasthttp) for more details + ## Security Checks - [x] Restricted HTTP Method/Verb diff --git a/src/cmd/offat/main.go b/src/cmd/offat/main.go index 92ad6ab..340f92e 100644 --- a/src/cmd/offat/main.go +++ b/src/cmd/offat/main.go @@ -153,14 +153,15 @@ func main() { DefaultQueryParams: config.QueryParams.ToMap(), // Tests - RunUnrestrictedHttpMethodTest: true, - RunBasicSQLiTest: true, - RunBasicSSRFTest: true, - RunOsCommandInjectionTest: true, - RunXssHtmlInjectionTest: true, - RunSstiInjectionTest: true, - RunBolaTest: true, - RunBolaTrailingPathTest: true, + RunUnrestrictedHttpMethodTest: true, + RunBasicSQLiTest: true, + RunBasicSSRFTest: true, + RunOsCommandInjectionTest: true, + RunXssHtmlInjectionTest: true, + RunSstiInjectionTest: true, + RunBolaTest: true, + RunBolaTrailingPathTest: true, + RunMissingAuthImplementationTest: true, // SSRF Test SsrfUrl: *config.SsrfUrl, diff --git a/src/pkg/tgen/missingAuth.go b/src/pkg/tgen/missingAuth.go new file mode 100644 index 0000000..71ab786 --- /dev/null +++ b/src/pkg/tgen/missingAuth.go @@ -0,0 +1,58 @@ +package tgen + +import ( + "github.com/OWASP/OFFAT/src/pkg/parser" + "github.com/OWASP/OFFAT/src/pkg/utils" + c "github.com/dmdhrumilmistry/fasthttpclient/client" + "github.com/rs/zerolog/log" +) + +func MissingAuthTest(baseUrl string, docParams []*parser.DocHttpParams, queryParams map[string]string, headers map[string]string) []*ApiTest { + var tests []*ApiTest + testName := "Missing Auth Implementation Test" + immuneResponseCode := []int{401, 403, 404, 405} + authKeys := []string{ + "Authorization", + "authorization", + "X-API-Key", + "x-api-key", + "API_KEY", + "api_key", + } + + for _, docParam := range docParams { + // skip test generation if there are no security schemes + if len(docParam.Security) < 1 { + continue + } + + url, headersMap, queryMap, bodyData, pathWithParams, err := httpParamToRequest(baseUrl, docParam, queryParams, headers, utils.JSON) + if err != nil { + log.Error().Err(err).Msgf("failed to generate request params from DocHttpParams, skipping test for this case %v due to error %v", *docParam, err) + continue + } + + // Delete auth data from header and query + DeleteAuthFromMap(headersMap, authKeys) + DeleteAuthFromMap(queryMap, authKeys) + + request := c.NewRequest(url, docParam.HttpMethod, queryMap, headersMap, bodyData) + + test := ApiTest{ + TestName: testName, + Request: request, + Path: docParam.Path, + PathWithParams: pathWithParams, + ImmuneResponseCodes: immuneResponseCode, + } + tests = append(tests, &test) + } + + return tests +} + +func DeleteAuthFromMap(authMap map[string]string, keys []string) { + for _, key := range keys { + delete(authMap, key) + } +} diff --git a/src/pkg/tgen/tgen.go b/src/pkg/tgen/tgen.go index 7fe0b13..aeb84a9 100644 --- a/src/pkg/tgen/tgen.go +++ b/src/pkg/tgen/tgen.go @@ -16,14 +16,15 @@ type TGenHandler struct { BaseUrl string // Register all tests using bool values below - RunUnrestrictedHttpMethodTest bool - RunBasicSQLiTest bool - RunBasicSSRFTest bool - RunOsCommandInjectionTest bool - RunXssHtmlInjectionTest bool - RunSstiInjectionTest bool - RunBolaTest bool - RunBolaTrailingPathTest bool + RunUnrestrictedHttpMethodTest bool + RunBasicSQLiTest bool + RunBasicSSRFTest bool + RunOsCommandInjectionTest bool + RunXssHtmlInjectionTest bool + RunSstiInjectionTest bool + RunBolaTest bool + RunBolaTrailingPathTest bool + RunMissingAuthImplementationTest bool // SSRF Test related data SsrfUrl string @@ -73,6 +74,14 @@ func (t *TGenHandler) GenerateTests() []*ApiTest { log.Info().Msgf("%d tests generated for BOLA Trailing Path", len(newTests)) } + // Missing Auth Implementation Test + if t.RunMissingAuthImplementationTest { + newTests := MissingAuthTest(t.BaseUrl, t.Doc, t.DefaultQueryParams, t.DefaultHeaders) + tests = append(tests, newTests...) + + log.Info().Msgf("%d tests generated for Missing Auth Implementation", len(newTests)) + } + // Basic SQLI Test if t.RunBasicSQLiTest { injectionConfig := InjectionConfig{ @@ -133,6 +142,7 @@ func (t *TGenHandler) GenerateTests() []*ApiTest { log.Info().Msgf("%d tests generated for Basic OS Command Injection", len(newTests)) } + // SSRF Test if t.RunBasicSSRFTest && utils.ValidateURL(t.SsrfUrl) { injectionConfig := InjectionConfig{ InBody: true,