Skip to content

Commit cd3cdbc

Browse files
handle http params
1 parent fb8b3eb commit cd3cdbc

8 files changed

Lines changed: 86 additions & 30 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ bin
4242

4343
# Go workspace file
4444
go.work
45+
.idea
4546

4647
# envs
4748
.env

src/cmd/offat/main.go

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package main
22

33
import (
44
"flag"
5+
"fmt"
56
"os"
7+
"strings"
68
"time"
79

810
"github.com/OWASP/OFFAT/src/pkg/http"
@@ -28,14 +30,46 @@ type FlagConfig struct {
2830
BaseUrl *string
2931

3032
// HTTP
31-
RequestsPerSecond *int
32-
SkipTlsVerfication *bool
33+
RequestsPerSecond *int
34+
SkipTlsVerification *bool
35+
Headers KeyValueMap
36+
QueryParams KeyValueMap
3337

3438
// Report
3539
AvoidImmuneFilter *bool
3640
OutputFilePath *string
3741
}
3842

43+
// Custom type for headers
44+
type KeyValueMap map[string]string
45+
46+
// Implement the String method for headers
47+
func (h *KeyValueMap) String() string {
48+
var keyValueList []string
49+
for k, v := range *h {
50+
keyValueList = append(keyValueList, fmt.Sprintf("%s=%s", k, v))
51+
}
52+
return strings.Join(keyValueList, ", ")
53+
}
54+
55+
// Implement the Set method for headers
56+
func (h *KeyValueMap) Set(value string) error {
57+
if *h == nil {
58+
*h = make(KeyValueMap)
59+
}
60+
61+
parts := strings.SplitN(value, "=", 2)
62+
if len(parts) != 2 {
63+
return fmt.Errorf("invalid key value format, expected key=value but got %s", value)
64+
}
65+
(*h)[parts[0]] = parts[1]
66+
return nil
67+
}
68+
69+
func (h *KeyValueMap) ToMap() map[string]string {
70+
return *h
71+
}
72+
3973
func main() {
4074

4175
// Parse CLI args
@@ -50,7 +84,9 @@ func main() {
5084
config.DisableSchemaPatternValidation = flag.Bool("dp", false, "disable schema patterns validation for OAS files")
5185

5286
config.RequestsPerSecond = flag.Int("r", 60, "number of requests per second")
53-
config.SkipTlsVerfication = flag.Bool("ns", false, "disable TLS/SSL Verfication")
87+
config.SkipTlsVerification = flag.Bool("ns", false, "disable TLS/SSL Verfication")
88+
flag.Var(&config.Headers, "H", "HTTP headers in the format key=value")
89+
flag.Var(&config.QueryParams, "q", "HTTP query parameter in the format key=value")
5490

5591
config.OutputFilePath = flag.String("o", "output.json", "JSON report output file path. default: output.json")
5692
config.AvoidImmuneFilter = flag.Bool("ai", true, "does not filter immune endpoint from results if used")
@@ -99,7 +135,7 @@ func main() {
99135
// log.Info().Msgf("%v", parser.Doc.GetDocHttpParams())
100136

101137
// http client
102-
httpCfg := http.NewConfig(config.RequestsPerSecond, config.SkipTlsVerfication)
138+
httpCfg := http.NewConfig(config.RequestsPerSecond, config.SkipTlsVerification)
103139
hc := http.NewHttp(httpCfg)
104140

105141
url := *parser.Doc.GetBaseUrl()
@@ -117,7 +153,9 @@ func main() {
117153

118154
// generate and run tests
119155
apiTestHandler := tgen.TGenHandler{
120-
Doc: parser.Doc.GetDocHttpParams(),
156+
Doc: parser.Doc.GetDocHttpParams(),
157+
DefaultHeaders: config.Headers.ToMap(),
158+
DefaultQueryParams: config.QueryParams.ToMap(),
121159

122160
// Tests
123161
RunUnrestrictedHttpMethodTest: true,

src/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/OWASP/OFFAT/src
33
go 1.22.4
44

55
require (
6-
github.com/dmdhrumilmistry/fasthttpclient v1.2.0
6+
github.com/dmdhrumilmistry/fasthttpclient v1.2.3
77
github.com/getkin/kin-openapi v0.126.0
88
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213
99
github.com/olekukonko/tablewriter v0.0.5

src/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
1717
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1818
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1919
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
20-
github.com/dmdhrumilmistry/fasthttpclient v1.2.0 h1:cKwDbKirg7FUIdV55iVPyUcLBeO+lOAYxRU1D4YO1ZY=
21-
github.com/dmdhrumilmistry/fasthttpclient v1.2.0/go.mod h1:9pu2ZL89sQPO1RD2me+YBOo8nnslsqnRNJb8S0zBBa0=
20+
github.com/dmdhrumilmistry/fasthttpclient v1.2.3 h1:asEKkB1UxSnaCPlW7YEthMJBN3jAf01bjfMgln5FWRQ=
21+
github.com/dmdhrumilmistry/fasthttpclient v1.2.3/go.mod h1:9pu2ZL89sQPO1RD2me+YBOo8nnslsqnRNJb8S0zBBa0=
2222
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
2323
github.com/getkin/kin-openapi v0.126.0 h1:c2cSgLnAsS0xYfKsgt5oBV6MYRM/giU8/RtwUY4wyfY=
2424
github.com/getkin/kin-openapi v0.126.0/go.mod h1:7mONz8IwmSRg6RttPu6v8U/OJ+gr+J99qSFNjPGSQqw=

src/pkg/parser/fuzz.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ func FillHttpParams(params *[]Param) {
6464
wg.Add(1)
6565
go func(idx int) {
6666
defer wg.Done()
67-
FillHttpParam(&(*params)[idx]) // Pass a pointer to the Param element
68-
67+
if !FillHttpParam(&(*params)[idx]) { // Pass a pointer to the Param element
68+
log.Error().Msgf("failed to populate value %v:", (*params)[idx])
69+
}
6970
// remove below print statement after debugging
7071
// log.Print((*params)[idx].Name, ": ", (*params)[idx].Value)
7172
}(i)

src/pkg/parser/openapi.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func (o *OpenApi) AssignParamsToSlices(params openapi3.Parameters, httpPathParam
4646
In: param.Value.In,
4747
Name: param.Value.Name,
4848
Required: param.Value.Required,
49+
Type: param.Value.Schema.Value.Type.Slice(),
4950
}
5051

5152
switch param.Value.In {
@@ -84,14 +85,16 @@ func (o *OpenApi) HttpOperationToDocHttpParams(HttpMethod, path string, httpOper
8485
bodyParams = append(bodyParams, Param{
8586
Name: paramName,
8687
In: ParameterInBody,
87-
Required: true,
88+
Required: true, // TODO: make this hard coded value dynamic
8889
Type: paramData.Value.Type.Slice(),
8990
ContentType: contentType,
9091
})
9192
}
9293
}
9394
}
9495

96+
// // TODO: parse path params
97+
9598
// Parse Security Scheme data
9699
var securitySchemes []map[string][]string
97100
if httpOperation.Security != nil {

src/pkg/tgen/unrestrictedmethods.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,33 @@ import (
1212
)
1313

1414
// returns a new map with k:parser.DocHttpParams.Name, v:parser.DocHttpParams.Value
15-
func UnrestrictedHttpMethods(docParams []*parser.DocHttpParams, queryParams any, headers any) []*ApiTest {
15+
func UnrestrictedHttpMethods(docParams []*parser.DocHttpParams, queryParams map[string]string, headers map[string]string) []*ApiTest {
1616
var tests []*ApiTest
1717
testName := "Unrestricted HTTP Methods/Verbs"
1818
// successCodes := []int{200, 201, 202, 204, 301, 302, 400}
1919
immuneResponseCode := []int{404, 405, 502, 503, 504}
2020

2121
for _, docParam := range docParams {
22-
bodyMap := ParamsToMap(docParam.BodyParams) // convert it to map[string]interface{}
23-
// convert it to JSON
24-
jsonData, err := json.Marshal(bodyMap)
22+
// parse params and convert it to map[string]interface{}
23+
parsedbodyMap := ParamsToMap(docParam.BodyParams)
24+
parsedQueryParamsMap := ParamsToMap(docParam.QueryParams)
25+
parsedHeaderParamsMap := ParamsToMap(docParam.HeaderParams)
26+
// parsedPathParamsMap := ParamsToMap(docParam.PathParams)
27+
// TODO: handle cookie params
28+
29+
// convert body to JSON
30+
jsonData, err := json.Marshal(parsedbodyMap)
2531
if err != nil {
2632
log.Error().Stack().Err(err).Msg("failed to convert bodyMap to JSON")
2733
jsonData = nil
2834
}
2935

36+
// combine maps with default values
37+
mergedHeaderParams := MergeMaps(headers, parsedHeaderParamsMap)
38+
mergedQueryParams := MergeMaps(queryParams, parsedQueryParamsMap)
39+
3040
for _, httpMethod := range utils.RemoveElement(HttpMethodsSlice, docParam.HttpMethod) {
31-
request := c.NewRequest(docParam.Url, httpMethod, queryParams, headers, jsonData)
41+
request := c.NewRequest(docParam.Url, httpMethod, mergedQueryParams, mergedHeaderParams, jsonData)
3242

3343
test := ApiTest{
3444
TestName: testName,

src/pkg/tgen/utils.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package tgen
22

33
import (
4-
"reflect"
4+
"fmt"
55

66
"github.com/OWASP/OFFAT/src/pkg/parser"
7+
"github.com/rs/zerolog/log"
78
)
89

910
// convert parser.Param to map
@@ -17,22 +18,24 @@ func ParamsToMap(params []parser.Param) map[string]interface{} {
1718
return paramMap
1819
}
1920

20-
func MergeMaps(dst, src any) any {
21-
dstVal := reflect.ValueOf(dst)
22-
srcVal := reflect.ValueOf(src)
21+
// MergeMaps merges two maps and returns a map[string]string and an error if any value in map2 cannot be converted to a string
22+
func MergeMaps(map1 map[string]string, map2 map[string]interface{}) map[string]string {
23+
mergedMap := map[string]string{}
2324

24-
// Create a new map of the same type as dst
25-
result := reflect.MakeMap(dstVal.Type())
26-
27-
// Copy all elements from dst to result
28-
for _, key := range dstVal.MapKeys() {
29-
result.SetMapIndex(key, dstVal.MapIndex(key))
25+
// Copy all key-value pairs from map1 to mergedMap
26+
for k, v := range map1 {
27+
mergedMap[k] = v
3028
}
3129

32-
// Overwrite or add elements from src to result
33-
for _, key := range srcVal.MapKeys() {
34-
result.SetMapIndex(key, srcVal.MapIndex(key))
30+
// Copy all key-value pairs from map2 to mergedMap, checking types
31+
for k, v := range map2 {
32+
strValue, ok := v.(string)
33+
if !ok {
34+
log.Error().Stack().Err(fmt.Errorf("failed to convert %v to string", v))
35+
continue
36+
}
37+
mergedMap[k] = strValue
3538
}
3639

37-
return result.Interface()
40+
return mergedMap
3841
}

0 commit comments

Comments
 (0)