/modsecurity-go

ModSecurity Golang port

Primary LanguageGoMIT LicenseMIT

This Project Is WIP.

This Project is work in progress. Api will be changed frequently. Not recommended for production use.

ModSecurity-Go

GoDoc CI Status Coverage Status codebeat badge License

ModSecurity-Go is golang port for ModSecurity.

Project is Working in progress.

The current goal is to implement ModSecurity Rules Language Porting Specification Level 1

TODO:

  • SecLang parser
  • Implement SecLang Processor
  • Implement SecLang Level 1(WIP)
  • Compatible with OWASP

Usage

Build Rules with SecLang

For full example see Rules with SecLang Example

rule := `SecRuleEngine On
             SecRule REQUEST_URI '@rx cmd' \
                        "id:123,\
                         phase:2,\
                         t:lowercase,\
                         deny"`

eng := modsecurity.NewEngine()
rs, err := seclang.NewRuleSetFromSecLangString(rule)
if err != nil {
	panic(err)
}
err = rs.Execute(eng)
if err != nil {
	panic(err)
}

ts, _ := eng.NewTransaction()
ts.ProcessConnection("127.0.0.1", "12345", "127.0.0.1", "80")
u, err := url.Parse(`/search?="a';CMD echo '1"`)
if err != nil {
	panic(err)
}
ts.ProcessRequestURL(u, "GET", "HTTP/1.1")
ts.ProcessRequestHeader(nil)
i := ts.Result()
utils.Pprint(i)
// Output:
// (*modsecurity.Intervention)({
//  Status: (int) 403,
//  Pause: (time.Duration) 0s,
//  Url: (*url.URL)(<nil>),
//  Log: ([]string) (len=1 cap=1) {
//   (string) (len=73) "[client 127.0.0.1:12345](phase 2)ModSecurity: Access denied with code 403"
//  },
//  Disruptive: (bool) true
// })

Build Rules with Go

For full example see Rules with Go Example

e := modsecurity.NewEngine()
// enable engine
e.Enable(modsecurity.StatusOn)
// make rule set
ruleSet := modsecurity.NewSecRuleSet()
// make rule
rule := &modsecurity.SecRule{
	Phase: modsecurity.PhaseRequestHeaders,
}
// Variable: REQUEST_URI
rule.AppendVariables(modsecurity.NewVariableRequestURI())
// Operation: rx select
op, err := modsecurity.NewOperatorRx("select")
if err != nil {
	panic(err)
}
rule.SetOperator(op)
// Action: deny
rule.AppendActions(modsecurity.NewActionDeny())
ruleSet.AddRules(rule)

// running rule
// make Transaction
ts, _ := modsecurity.NewTransaction(e, ruleSet)

// request header phase
ts.ProcessConnection("127.0.0.1", "12345", "127.0.0.1", "80")

u, err := url.Parse(`/search?="a';select '1"`)
if err != nil {
	panic(err)
}

ts.ProcessRequestURL(u, "GET", "HTTP/1.1")
ts.ProcessRequestHeader(nil)
i := ts.Result()
pprint := spew.NewDefaultConfig()
pprint.DisablePointerAddresses = true
pprint.Dump(i)
// Output:
// (*modsecurity.Intervention)({
//  Status: (int) 403,
//  Pause: (time.Duration) 0s,
//  Url: (*url.URL)(<nil>),
//  Log: ([]string) (len=1 cap=1) {
//   (string) (len=73) "[client 127.0.0.1:12345](phase 2)ModSecurity: Access denied with code 403"
//  },
//  Disruptive: (bool) true
// })

Seclang Parsing

For full example see Parser Example


import "github.com/senghoo/modsecurity-go/seclang/parser"

var rules = `<<<some modsecurity rules>>`
scaner := parser.NewSecLangScannerFromString(rules)
d, err := scaner.AllDirective()
if err != nil {
	panic(err)
}
fmt.Printf("%#v\n", d)
    

Supported Features

Directives

  • SecRuleEngine
  • SecRule
  • SecRequestBodyAccess
  • SecResponseBodyAccess

Variables

  • ARGS
  • ARGS_NAMES
  • QUERY_STRING
  • REMOTE_ADDR
  • REQUEST_BASENAME
  • REQUEST_BODY
  • REQUEST_COOKIES
  • REQUEST_COOKIES_NAMES
  • REQUEST_FILENAME
  • REQUEST_HEADERS
  • REQUEST_HEADERS_NAMES
  • REQUEST_METHOD
  • REQUEST_PROTOCOL
  • REQUEST_URI
  • RESPONSE_BODY
  • RESPONSE_CONTENT_LENGTH
  • RESPONSE_CONTENT_TYPE
  • RESPONSE_HEADERS
  • RESPONSE_HEADERS_NAMES
  • RESPONSE_PROTOCOL
  • RESPONSE_STATUS
  • XML

Operators

  • rx
  • eq
  • ge
  • gt
  • le
  • lt

Actions

  • allow
  • msg
  • id
  • rev
  • ver
  • severity
  • log
  • deny
  • block
  • status
  • phase
  • t
  • skip
  • chain
  • logdata
  • setvar
  • capture
  • pass

Transformation Functions

  • lowercase
  • urlDecode
  • urlDecodeUni
  • none
  • compressWhitespace
  • removeWhitespace
  • replaceNulls
  • removeNulls