Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ Usage: ./gotestwaf [OPTIONS] --url <URL>

Options:
--addDebugHeader Add header "X-GoTestWAF-Test" with a hash of the test information in each request
--addContentLength If present, manually set Content-Length header for requests
--addHeader string An HTTP header to add to requests
--blockConnReset If present, connection resets will be considered as block
--blockRegex string Regex to detect a blocking page with the same HTTP response status code as a not blocked request
Expand Down
1 change: 1 addition & 0 deletions cmd/gotestwaf/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func parseFlags() (args []string, err error) {
flag.String("proxy", "", "Proxy URL to use")
flag.String("addHeader", "", "An HTTP header to add to requests")
flag.Bool("addDebugHeader", false, "Add header \"X-GoTestWAF-Test\" with a hash of the test information in each request")
flag.Bool("addContentLength", false, "If present, manually set Content-Length header for requests")

// GoHTTP client only settings
flag.Int("maxIdleConns", 2, "The maximum number of keep-alive connections (gohttp only)")
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Config struct {
Proxy string `mapstructure:"proxy"`
AddHeader string `mapstructure:"addHeader"`
AddDebugHeader bool `mapstructure:"addDebugHeader"`
AddContentLength bool `mapstructure:"addContentLength"`

// GoHTTP client only settings
MaxIdleConns int `mapstructure:"maxIdleConns"`
Expand Down
5 changes: 5 additions & 0 deletions internal/payload/placeholder/htmlform.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"html/template"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/chromedp/chromedp"
Expand Down Expand Up @@ -59,6 +60,10 @@ func (p *HTMLForm) prepareGoHTTPClientRequest(requestURL, payload string, config
}

req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
// Manually set Content-Length header if configured
if globalConfig != nil && globalConfig.AddContentLength {
req.Header.Set("Content-Length", strconv.Itoa(len(payload)))
}

return &types.GoHTTPRequest{Req: req}, nil
}
Expand Down
22 changes: 15 additions & 7 deletions internal/payload/placeholder/htmlmultpartform.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"mime/multipart"
"net/http"
"net/url"
"strconv"

"github.com/chromedp/chromedp"
"github.com/wallarm/gotestwaf/internal/scanner/clients/chrome/helpers"
Expand Down Expand Up @@ -47,32 +48,39 @@ func (p *HTMLMultipartForm) CreateRequest(requestURL, payload string, config Pla
}

func (p *HTMLMultipartForm) prepareGoHTTPClientRequest(requestURL, payload string, config PlaceholderConfig) (*types.GoHTTPRequest, error) {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

randomName, err := RandomHex(Seed)
if err != nil {
return nil, err
}

body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

fw, err := writer.CreateFormField(randomName)
part, err := writer.CreateFormFile(randomName, "file")
if err != nil {
return nil, err
}

_, err = fw.Write([]byte(payload))
_, err = part.Write([]byte(payload))
if err != nil {
return nil, err
}

writer.Close()
err = writer.Close()
if err != nil {
return nil, err
}

req, err := http.NewRequest(http.MethodPost, requestURL, bytes.NewReader(body.Bytes()))
req, err := http.NewRequest(http.MethodPost, requestURL, body)
if err != nil {
return nil, err
}

req.Header.Add("Content-Type", writer.FormDataContentType())
// Manually set Content-Length header if configured
if globalConfig != nil && globalConfig.AddContentLength {
req.Header.Set("Content-Length", strconv.Itoa(body.Len()))
}

return &types.GoHTTPRequest{Req: req}, nil
}
Expand Down
5 changes: 5 additions & 0 deletions internal/payload/placeholder/jsonbody.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"html/template"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/chromedp/chromedp"
Expand Down Expand Up @@ -52,6 +53,10 @@ func (p *JSONBody) prepareGoHTTPClientRequest(requestURL, payload string, config
}

req.Header.Add("Content-Type", "application/json")
// Manually set Content-Length header if configured
if globalConfig != nil && globalConfig.AddContentLength {
req.Header.Set("Content-Length", strconv.Itoa(len(payload)))
}

return &types.GoHTTPRequest{Req: req}, nil
}
Expand Down
5 changes: 5 additions & 0 deletions internal/payload/placeholder/jsonrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"html/template"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/chromedp/chromedp"
Expand Down Expand Up @@ -68,6 +69,10 @@ func (p *JSONRequest) prepareGoHTTPClientRequest(requestURL, payload string, con
}

req.Header.Add("Content-Type", "application/json")
// Manually set Content-Length header if configured
if globalConfig != nil && globalConfig.AddContentLength {
req.Header.Set("Content-Length", strconv.Itoa(len(payload)))
}

return &types.GoHTTPRequest{Req: req}, nil
}
Expand Down
8 changes: 8 additions & 0 deletions internal/payload/placeholder/placeholder.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/wallarm/gotestwaf/internal/helpers"
"github.com/wallarm/gotestwaf/internal/scanner/types"
"github.com/wallarm/gotestwaf/internal/config"
)

const (
Expand All @@ -28,6 +29,13 @@ type PlaceholderConfig interface {
helpers.Hash
}

var globalConfig *config.Config

// SetGlobalConfig sets the global configuration for placeholders
func SetGlobalConfig(cfg *config.Config) {
globalConfig = cfg
}

var Placeholders map[string]Placeholder

var placeholders = []Placeholder{
Expand Down
7 changes: 6 additions & 1 deletion internal/payload/placeholder/requestbody.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"html/template"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/wallarm/gotestwaf/internal/scanner/clients/chrome/helpers"
Expand Down Expand Up @@ -47,12 +48,16 @@ func (p *RequestBody) CreateRequest(requestURL, payload string, config Placehold
}

func (p *RequestBody) prepareGoHTTPClientRequest(requestURL, payload string, config PlaceholderConfig) (*types.GoHTTPRequest, error) {
// check if we need to set Content-Length manually here
req, err := http.NewRequest(http.MethodPost, requestURL, strings.NewReader(payload))
if err != nil {
return nil, err
}

// Manually set Content-Length header if configured
if globalConfig != nil && globalConfig.AddContentLength {
req.Header.Set("Content-Length", strconv.Itoa(len(payload)))
}

return &types.GoHTTPRequest{Req: req}, nil
}

Expand Down
5 changes: 5 additions & 0 deletions internal/payload/placeholder/soapbody.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"html/template"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/chromedp/chromedp"
Expand Down Expand Up @@ -86,6 +87,10 @@ func (p *SOAPBody) prepareGoHTTPClientRequest(requestURL, payload string, config

req.Header.Add("SOAPAction", `"http://schemas.xmlsoap.org/soap/actor/next"`)
req.Header.Add("Content-Type", "text/xml")
// Manually set Content-Length header if configured
if globalConfig != nil && globalConfig.AddContentLength {
req.Header.Set("Content-Length", strconv.Itoa(len(payload)))
}

return &types.GoHTTPRequest{Req: req}, nil
}
Expand Down
5 changes: 5 additions & 0 deletions internal/payload/placeholder/xmlbody.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"html/template"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/chromedp/chromedp"
Expand Down Expand Up @@ -52,6 +53,10 @@ func (p *XMLBody) prepareGoHTTPClientRequest(requestURL, payload string, config
}

req.Header.Add("Content-Type", "application/xml")
// Manually set Content-Length header if configured
if globalConfig != nil && globalConfig.AddContentLength {
req.Header.Set("Content-Length", strconv.Itoa(len(payload)))
}

return &types.GoHTTPRequest{Req: req}, nil
}
Expand Down
9 changes: 7 additions & 2 deletions internal/scanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func New(
return nil, errors.Wrap(err, "couldn't create GraphQL client")
}

return &Scanner{
scanner := &Scanner{
logger: logger,
cfg: cfg,
db: db,
Expand All @@ -136,7 +136,12 @@ func New(
requestTemplates: requestTemplates,
router: router,
enableDebugHeader: enableDebugHeader,
}, nil
}

// Set global configuration for placeholders
placeholder.SetGlobalConfig(cfg)

return scanner, nil
}

func (s *Scanner) CheckIfJavaScriptRequired(ctx context.Context) (bool, error) {
Expand Down