Skip to content

Commit

Permalink
merge upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
blotus committed Dec 13, 2023
2 parents c5b03c9 + 968dc71 commit 222e5ca
Show file tree
Hide file tree
Showing 28 changed files with 714 additions and 242 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/close-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
days-before-issue-stale: 30
days-before-issue-close: 14
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/fix-dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: v1.19.x
cache: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
- uses: actions/setup-go@v5
with:
go-version: '>=1.19.0'
- run: go run mage.go fuzz
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: v1.19.x
cache: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tinygo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@v4

- name: Install Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: true
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ coraza-waf
__debug_bin

build/

go.work.sum
52 changes: 27 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,34 @@ Coraza can be used as a library for your Go program to implement a security midd
package main

import (
"fmt"
"github.com/corazawaf/coraza/v3"
"fmt"

"github.com/corazawaf/coraza/v3"
)

func main() {
// First we initialize our waf and our seclang parser
waf, err := coraza.NewWAF(coraza.NewWAFConfig().
WithDirectives(`SecRule REMOTE_ADDR "@rx .*" "id:1,phase:1,deny,status:403"`))
// Now we parse our rules
if err != nil {
fmt.Println(err)
}

// Then we create a transaction and assign some variables
tx := waf.NewTransaction()
defer func() {
tx.ProcessLogging()
tx.Close()
}()
tx.ProcessConnection("127.0.0.1", 8080, "127.0.0.1", 12345)

// Finally we process the request headers phase, which may return an interruption
if it := tx.ProcessRequestHeaders(); it != nil {
fmt.Printf("Transaction was interrupted with status %d\n", it.Status)
}
// First we initialize our waf and our seclang parser
waf, err := coraza.NewWAF(coraza.NewWAFConfig().
WithDirectives(`SecRule REMOTE_ADDR "@rx .*" "id:1,phase:1,deny,status:403"`))
// Now we parse our rules
if err != nil {
fmt.Println(err)
}

// Then we create a transaction and assign some variables
tx := waf.NewTransaction()
defer func() {
tx.ProcessLogging()
tx.Close()
}()
tx.ProcessConnection("127.0.0.1", 8080, "127.0.0.1", 12345)

// Finally we process the request headers phase, which may return an interruption
if it := tx.ProcessRequestHeaders(); it != nil {
fmt.Printf("Transaction was interrupted with status %d\n", it.Status)
}
}

```

[Examples/http-server](./examples/http-server/) provides an example to practice with Coraza.
Expand Down Expand Up @@ -132,8 +134,8 @@ Coraza only requires Go for development. You can run `mage.go` to issue developm

See the list of commands

```shell
go run mage.go -l
```
$ go run mage.go -l
Targets:
check runs lint and tests.
coverage runs tests with coverage and race detector enabled.
Expand Down Expand Up @@ -163,8 +165,8 @@ Our vulnerability management team will respond within 3 working days of your rep

## Thanks

* Modsecurity team for creating ModSecurity
* OWASP Coreruleset team for the CRS and their help
* Ivan Ristić for creating ModSecurity

### Coraza on Twitter

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
github.com/mccutchen/go-httpbin/v2 v2.12.0
github.com/petar-dambovaliev/aho-corasick v0.0.0-20230725210150-fb29fc3c913e
github.com/tidwall/gjson v1.17.0
golang.org/x/net v0.18.0
golang.org/x/net v0.19.0
golang.org/x/sync v0.5.0
rsc.io/binaryregexp v0.2.0
)
Expand All @@ -33,6 +33,6 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/tools v0.6.0 // indirect
)
12 changes: 4 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6
github.com/foxcpp/go-mockdns v1.0.0/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4=
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mccutchen/go-httpbin/v2 v2.9.0 h1:0c8loz/kMEdBmcHJZh0MUgKX84U19AlLk7h6nf2Wkx4=
github.com/mccutchen/go-httpbin/v2 v2.9.0/go.mod h1:+DBHcmg6EOeoizuiOI8iL12VIHXx+9YQNlz+gjB9uxk=
github.com/mccutchen/go-httpbin/v2 v2.12.0 h1:MPrFw/Avug0E83SN/j5SYDuD9By0GDAJ9hNTR4RwjyU=
github.com/mccutchen/go-httpbin/v2 v2.12.0/go.mod h1:f4DUXYlU6yH0V81O4lJIwqpmYdTXXmYwzxMnYEimFPk=
github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
Expand All @@ -34,12 +32,10 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -51,8 +47,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
Expand Down
10 changes: 0 additions & 10 deletions go.work.sum

This file was deleted.

114 changes: 24 additions & 90 deletions http/interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,23 @@ func (i *rwInterceptor) Header() http.Header {
return i.w.Header()
}

var _ http.ResponseWriter = (*rwInterceptor)(nil)
func (i *rwInterceptor) ReadFrom(r io.Reader) (n int64, err error) {
return io.Copy(struct{ io.Writer }{i}, r)
}

func (i *rwInterceptor) Flush() {
if !i.wroteHeader {
i.WriteHeader(http.StatusOK)
}
}

type responseWriter interface {
http.ResponseWriter
io.ReaderFrom
http.Flusher
}

var _ responseWriter = (*rwInterceptor)(nil)

// wrap wraps the interceptor into a response writer that also preserves
// the http interfaces implemented by the original response writer to avoid
Expand Down Expand Up @@ -168,110 +184,28 @@ func wrap(w http.ResponseWriter, r *http.Request, tx types.Transaction) (
var (
hijacker, isHijacker = i.w.(http.Hijacker)
pusher, isPusher = i.w.(http.Pusher)
flusher, isFlusher = i.w.(http.Flusher)
reader, isReader = i.w.(io.ReaderFrom)
)

switch {
case !isHijacker && !isPusher && !isFlusher && !isReader:
case !isHijacker && isPusher:
return struct {
http.ResponseWriter
}{i}, responseProcessor
case !isHijacker && !isPusher && !isFlusher && isReader:
return struct {
http.ResponseWriter
io.ReaderFrom
}{i, reader}, responseProcessor
case !isHijacker && !isPusher && isFlusher && !isReader:
return struct {
http.ResponseWriter
http.Flusher
}{i, flusher}, responseProcessor
case !isHijacker && !isPusher && isFlusher && isReader:
return struct {
http.ResponseWriter
http.Flusher
io.ReaderFrom
}{i, flusher, reader}, responseProcessor
case !isHijacker && isPusher && !isFlusher && !isReader:
return struct {
http.ResponseWriter
responseWriter
http.Pusher
}{i, pusher}, responseProcessor
case !isHijacker && isPusher && !isFlusher && isReader:
return struct {
http.ResponseWriter
http.Pusher
io.ReaderFrom
}{i, pusher, reader}, responseProcessor
case !isHijacker && isPusher && isFlusher && !isReader:
return struct {
http.ResponseWriter
http.Pusher
http.Flusher
}{i, pusher, flusher}, responseProcessor
case !isHijacker && isPusher && isFlusher && isReader:
case isHijacker && !isPusher:
return struct {
http.ResponseWriter
http.Pusher
http.Flusher
io.ReaderFrom
}{i, pusher, flusher, reader}, responseProcessor
case isHijacker && !isPusher && !isFlusher && !isReader:
return struct {
http.ResponseWriter
responseWriter
http.Hijacker
}{i, hijacker}, responseProcessor
case isHijacker && !isPusher && !isFlusher && isReader:
case isHijacker && isPusher:
return struct {
http.ResponseWriter
http.Hijacker
io.ReaderFrom
}{i, hijacker, reader}, responseProcessor
case isHijacker && !isPusher && isFlusher && !isReader:
return struct {
http.ResponseWriter
http.Hijacker
http.Flusher
}{i, hijacker, flusher}, responseProcessor
case isHijacker && !isPusher && isFlusher && isReader:
return struct {
http.ResponseWriter
http.Hijacker
http.Flusher
io.ReaderFrom
}{i, hijacker, flusher, reader}, responseProcessor
case isHijacker && isPusher && !isFlusher && !isReader:
return struct {
http.ResponseWriter
responseWriter
http.Hijacker
http.Pusher
}{i, hijacker, pusher}, responseProcessor
case isHijacker && isPusher && !isFlusher && isReader:
return struct {
http.ResponseWriter
http.Hijacker
http.Pusher
io.ReaderFrom
}{i, hijacker, pusher, reader}, responseProcessor
case isHijacker && isPusher && isFlusher && !isReader:
return struct {
http.ResponseWriter
http.Hijacker
http.Pusher
http.Flusher
}{i, hijacker, pusher, flusher}, responseProcessor
case isHijacker && isPusher && isFlusher && isReader:
return struct {
http.ResponseWriter
http.Hijacker
http.Pusher
http.Flusher
io.ReaderFrom
}{i, hijacker, pusher, flusher, reader}, responseProcessor
default:
return struct {
http.ResponseWriter
responseWriter
}{i}, responseProcessor
}
}
Loading

0 comments on commit 222e5ca

Please sign in to comment.