Skip to content

Commit 0f5100b

Browse files
implement basic ssrf tests
1 parent 9a695a7 commit 0f5100b

7 files changed

Lines changed: 61 additions & 11 deletions

File tree

src/cmd/offat/flag.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ type FlagConfig struct {
2424
QueryParams KeyValueMap
2525
Proxy *string
2626

27+
// SSRF Test
28+
SsrfUrl *string
29+
2730
// Report
2831
AvoidImmuneFilter *bool
2932
OutputFilePath *string

src/cmd/offat/main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ func main() {
3333
config.DisableSchemaDefaultsValidation = flag.Bool("ds", false, "disable schema defaults validation for OAS files")
3434
config.DisableSchemaPatternValidation = flag.Bool("dp", false, "disable schema patterns validation for OAS files")
3535

36+
config.SsrfUrl = flag.String("ssrf", "", "injects user defined SSRF url payload in http request components")
37+
3638
config.RequestsPerSecond = flag.Int("r", 60, "number of requests per second")
3739
config.SkipTlsVerification = flag.Bool("ns", false, "disable TLS/SSL Verfication")
3840
config.Proxy = flag.String("p", "", "specify proxy for capturing requests, supports http and socks urls. example: http://localhost:8080")
@@ -111,7 +113,11 @@ func main() {
111113

112114
// Tests
113115
RunUnrestrictedHttpMethodTest: true,
114-
RunSimpleSQLiTest: true,
116+
RunBasicSQLiTest: true,
117+
RunBasicSSRFTest: true,
118+
119+
// SSRF Test
120+
SsrfUrl: *config.SsrfUrl,
115121
}
116122

117123
// generate and run api tests
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import (
55
)
66

77
// generates very basic sqli API tests
8-
func SimpleSQLiTest(baseUrl string, docParams []*parser.DocHttpParams, queryParams map[string]string, headers map[string]string, injectionConfig InjectionConfig) []*ApiTest {
8+
func BasicSqliTest(baseUrl string, docParams []*parser.DocHttpParams, queryParams map[string]string, headers map[string]string, injectionConfig InjectionConfig) []*ApiTest {
99
testName := "Basic SQLI Test"
1010
vulnResponseCodes := []int{500}
1111
immuneResponseCodes := []int{}
12+
// TODO: implement injection in both keys and values
1213
payloads := []string{
1314
"' OR 1=1 ;--",
1415
"' UNION SELECT 1,2,3 -- -",

src/pkg/tgen/basicSsrf.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package tgen
2+
3+
import "github.com/OWASP/OFFAT/src/pkg/parser"
4+
5+
// generates very basic SSRF API tests by injecting provided URL
6+
func BasicSsrfTest(ssrfUrl, baseUrl string, docParams []*parser.DocHttpParams, queryParams map[string]string, headers map[string]string, injectionConfig InjectionConfig) []*ApiTest {
7+
testName := "Basic SSRF Test"
8+
vulnResponseCodes := []int{500}
9+
immuneResponseCodes := []int{}
10+
payloads := []string{ssrfUrl}
11+
12+
injectionConfig.Payloads = payloads
13+
14+
tests := injectParamIntoApiTest(baseUrl, docParams, queryParams, headers, testName, vulnResponseCodes, immuneResponseCodes, injectionConfig)
15+
16+
return tests
17+
}

src/pkg/tgen/payloadInjection.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ func injectParamInParam(params *[]parser.Param, payload string) {
3030
}
3131
}
3232

33-
// generates Api tests based on provided payloads
33+
// generates Api tests by injecting payloads in values
3434
func injectParamIntoApiTest(url string, docParams []*parser.DocHttpParams, queryParams map[string]string, headers map[string]string, testName string, vulnResponseCodes, immuneResponseCodes []int, injectionConfig InjectionConfig) []*ApiTest {
3535
var tests []*ApiTest
3636
// TODO: only inject payloads if any payload is accepted by the endpoint, else ignore injection
3737
// as this will reduce number of tests generated and increase efficiency
3838
for _, payload := range injectionConfig.Payloads {
39+
// TODO: implement injection in both key or value at a time
3940
for _, docParam := range docParams {
4041
// inject payloads into string before converting it to map[string]string
4142
if injectionConfig.InBody {

src/pkg/tgen/tgen.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@ package tgen
33
import (
44
_ "github.com/OWASP/OFFAT/src/pkg/logging"
55
"github.com/OWASP/OFFAT/src/pkg/parser"
6+
"github.com/OWASP/OFFAT/src/pkg/utils"
67
"github.com/rs/zerolog/log"
78
)
89

910
type TGenHandler struct {
10-
RunUnrestrictedHttpMethodTest bool
11-
RunSimpleSQLiTest bool
12-
1311
Doc []*parser.DocHttpParams
1412
DefaultQueryParams map[string]string
1513
DefaultHeaders map[string]string
1614
BaseUrl string
15+
16+
// Register all tests using bool values below
17+
RunUnrestrictedHttpMethodTest bool
18+
RunBasicSQLiTest bool
19+
RunBasicSSRFTest bool
20+
21+
// SSRF Test related data
22+
SsrfUrl string
1723
}
1824

1925
func (t *TGenHandler) GenerateTests() []*ApiTest {
@@ -25,18 +31,33 @@ func (t *TGenHandler) GenerateTests() []*ApiTest {
2531
log.Info().Msgf("%d tests generated for Unrestricted HTTP Methods/Verbs", len(newTests))
2632
}
2733

28-
if t.RunSimpleSQLiTest {
34+
// Basic SQLI Test
35+
if t.RunBasicSQLiTest {
36+
injectionConfig := InjectionConfig{
37+
InBody: true,
38+
InCookie: true,
39+
InHeader: true,
40+
InPath: true,
41+
InQuery: true,
42+
}
43+
newTests := BasicSqliTest(t.BaseUrl, t.Doc, t.DefaultQueryParams, t.DefaultHeaders, injectionConfig)
44+
tests = append(tests, newTests...)
45+
46+
log.Info().Msgf("%d tests generated for Basic SQLI", len(newTests))
47+
}
48+
49+
if t.RunBasicSSRFTest && utils.ValidateURL(t.SsrfUrl) {
2950
injectionConfig := InjectionConfig{
3051
InBody: true,
3152
InCookie: true,
32-
InHeader: false,
53+
InHeader: true,
3354
InPath: true,
3455
InQuery: true,
3556
}
36-
newTests := SimpleSQLiTest(t.BaseUrl, t.Doc, t.DefaultQueryParams, t.DefaultHeaders, injectionConfig)
57+
newTests := BasicSsrfTest(t.SsrfUrl, t.BaseUrl, t.Doc, t.DefaultQueryParams, t.DefaultHeaders, injectionConfig)
3758
tests = append(tests, newTests...)
3859

39-
log.Info().Msgf("%d tests generated for Simple SQLI", len(newTests))
60+
log.Info().Msgf("%d tests generated for Basic SSRF", len(newTests))
4061
}
4162

4263
return tests

src/pkg/utils/validation.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import (
44
"net/url"
55
)
66

7-
// ValidateURL checks if the provided URL is valid
7+
// ValidateURL checks if the provided URL is valid.
8+
// Note it doesn't make request to the server.
89
func ValidateURL(u string) bool {
910
parsedURL, err := url.Parse(u)
1011
if err != nil {

0 commit comments

Comments
 (0)