Giter Club home page Giter Club logo

coraza-caddy's People

Contributors

andremralves avatar anuraaga avatar dependabot[bot] avatar emileperron avatar fzipi avatar jcchavezs avatar jptosso avatar m4tteop avatar renovate[bot] avatar skixmix avatar syinwu avatar w0n9 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coraza-caddy's Issues

Missing hostname in logs, SecRule SERVER_NAME rules not working

Hi, when using the recommended files and configuration with 4.0/dev for coreruleset there is no hostname value in logs and all SecRule SERVER_NAME will not match as a consequence

FYI the same rules do work on modsecurity + nginx so they are NOT the issue

Relevant logs:

Dec 09 18:40:41 nginx caddy[34591]: {"level":"error","ts":1670611241.6194084,"logger":"http.handlers.waf","msg":"[client \"[2a077e813a390698224611e3abd9d]\"] Coraza: Warning. Request content type is not allowed by policy [file \"/etc/caddy/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\"] [line \"0\"] [id \"920420\"] [rev \"\"] [msg \"Request content type is not allowed by policy\"] [data \"text/plain;charset=UTF-8\"] [severity \"critical\"] [ver \"OWASP_CRS/4.0.0-rc1\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-protocol\"] [tag \"paranoia-level/1\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/255/153\"] [tag \"PCI/12.1\"] [hostname \"\"] [uri \"/auth/login_flow\"] [unique_id \"bberzX58CQInOuGRpJV\"]\n[client \"[2a077e813a390698224611e3abd9d]\"] Coraza: Warning. Request content type is not allowed by policy [file \"/etc/caddy/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\"] [line \"0\"] [id \"920420\"] [rev \"\"] [msg \"\"] [data \"\"] [severity \"critical\"] [ver \"OWASP_CRS/4.0.0-rc1\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-protocol\"] [tag \"paranoia-level/1\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/255/153\"] [tag \"PCI/12.1\"] [hostname \"\"] [uri \"/auth/login_flow\"] [unique_id \"bberzX58CQInOuGRpJV\"]\n"}

Unsure if load_owasp_crs is required for using the OWASP core rule set

I'm trying to use Coraza and the OWASP ruleset with Caddy 2.6.4 (this version of Caddy as it's the latest stable, and I'm using API Platform and its Caddyfile).

I need to use the following lines to build caddy:

RUN xcaddy build \
	--with github.com/corazawaf/coraza-caddy \
	--with github.com/corazawaf/coraza-coreruleset

...otherwise the conf files mentioned in the README don't exist anywhere: @coraza.conf-recommended, @crs-setup.conf.example, @owasp_crs/*.conf. I manually copy those files to the correct locations:

cp /go/pkg/mod/github.com/corazawaf/coraza-coreruleset*/rules/@coraza.conf-recommended /etc/caddy/@coraza.conf-recommended
cp /go/pkg/mod/github.com/corazawaf/coraza-coreruleset*/rules/@crs-setup.conf.example /etc/caddy/@crs-setup.conf.example
cp /go/pkg/mod/github.com/corazawaf/coraza-coreruleset*/rules/@owasp_crs/* /etc/caddy/@owasp_crs/

My Caddyfile is as follows:

{
        # Debug
        {$CADDY_DEBUG}

        # must be always included in your Caddyfile for Coraza module to work
        # see https://github.com/corazawaf/coraza-caddy
        order coraza_waf first
}

{$SERVER_NAME}

route {
        coraza_waf {
                load_owasp_crs
                directives `
                Include @coraza.conf-recommended
                Include @crs-setup.conf.example
                Include @owasp_crs/*.conf
                SecRuleEngine On
                `
        }

        root * /srv/app/public

        php_fastcgi unix//var/run/php/php-fpm.sock
        encode zstd gzip
        file_server
}

I've used caddy fmt --overwrite to correctly format the Caddyfile.

However, when I run caddy I get this error:

Error: adapting config using caddyfile: parsing caddyfile tokens for 'coraza_waf': Caddyfile:14 - Error during parsing: invalid key for filter directive: load_owasp_crs

However, if I comment out the load_owasp_crs directive, then caddy runs. Is this expected?

[Edit: after testing, the WAF is running, but I'm not sure how to check that the OWASP core rule set is running too?]

provision http.handlers.waf: invalid WAF config from string: failed to readfile: open path: invalid argument

here is Caddyfile:

/coraza # cat Caddyfile
{
	debug
	auto_https off
	order coraza_waf first
}

10.10.10.10:443 {
	tls internal

	coraza_waf {
		directives `
		Include /ruleset/coraza.conf
		Include /ruleset/sites/test/*.conf
		Include /ruleset/coreruleset/rules/*.conf
		`
	}
	reverse_proxy 10.10.10.10:4443 {
	}
}

config file exists:

/coraza # ls /ruleset/coraza.conf
/ruleset/coraza.conf

caddy doesn't see config:

/coraza # caddy reload
2023/04/26 08:01:04.459	INFO	using adjacent Caddyfile
Error: sending configuration to instance: caddy responded with error: HTTP 400: {"error":"loading config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'waf': provision http.handlers.waf: invalid WAF config from string: failed to readfile: open path: invalid argument"}

Path error

First of all I want to say thank you for the alternative to products like ModSecurity. This is very important for those who use open source. Before that, I had hardly ever met Go. That's why even simple errors can be difficult for me.

Version Go: 1.17
OS: Ubuntu 18.04

caddy build-info output:

go_version: go1.17.6
go_os:      linux
go_arch:    amd64
path:       caddy
main:       caddy (devel) 
dependencies:
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
github.com/alecthomas/chroma v0.9.2 h1:yU1sE2+TZbLIQPMk30SolL2Hn53SR/Pv750f7qZ/XMs=
github.com/antchfx/jsonquery v1.1.4 h1:+OlFO3QS9wjU0MKx9MgHm5f6o6hdd4e9mUTp0wTjxlM=
github.com/antchfx/xmlquery v1.3.6 h1:kaEVzH1mNo/2AJZrhZjAaAUTy2Nn2zxGfYYU8jWfXOo=
github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f h1:0cEys61Sr2hUBEXfNV8eyQP01oZuBgoMeHunebPirK8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/caddyserver/caddy/v2 v2.4.6 h1:HGkGICFGvyrodcqOOclHKfvJC0qTU7vny/7FhYp9hNw=
github.com/caddyserver/certmagic v0.15.2 h1:OMTakTsLM1ZfzMDjwvYprfUgFzpVPh3u87oxMPwmeBc=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8=
github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o=
github.com/dgraph-io/ristretto v0.0.4-0.20200906165740-41ebdbffecfd h1:KoJOtZf+6wpQaDTuOWGuo61GxcPBIfhwRxRTaTWGCTc=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac h1:opbrjaN/L8gg6Xh5D04Tem+8xVcz6ajZlGCs49mQgyg=
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/google/cel-go v0.7.3 h1:8v9BSN0avuGwrHFKNCjfiQ/CE6+D6sW+BDyOVoEeP6o=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/ip2location/ip2location-go/v9 v9.1.0 h1:DVlKxIcjA7CsA0cgzbidwe6eKzpbkS313LsH9ceutxI=
github.com/jptosso/aho-corasick v1.0.4 h1:4zLohlv0YrkXNLhNdRA0eTanzd1z8YFnDfZYg0fTm9g=
github.com/jptosso/coraza-caddy v1.1.0 h1:VR5P1VEiF3K5fvAjnZIpLpniW7eVmbAislI3G5ZfWNs=
github.com/jptosso/coraza-waf v1.1.0 h1:tItgbuhNXdigvwpRHzQkudaVrG9G9QNNFArajz5yFbQ=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
github.com/lucas-clemente/quic-go v0.23.0 h1:5vFnKtZ6nHDFsc/F3uuiF4T3y/AXaQdxjUqiVw26GZE=
github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mholt/acmez v1.0.1 h1:J7uquHOKEmo71UDnVApy1sSLA0oF/r+NtVrNzMKKA9I=
github.com/micromdm/scep/v2 v2.1.0 h1:2fS9Rla7qRR266hvUoEauBJ7J6FhgssEiq2OkSKXmaU=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8=
github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw=
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
github.com/pcktdmp/cef v0.2.0 h1:MgFUXCRqaXsITq83bN0+mmXVh4CGFgOeuyxNaT86Kj0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/samfoo/ansi v0.0.0-20160124022901-b6bd2ded7189 h1:CmSpbxmewNQbzqztaY0bke1qzHhyNyC29wYgh17Gxfo=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/smallstep/certificates v0.17.5-0.20211008195551-04fe3126bebf h1:T27FAcJuIadMwnt5uaYCxeNQceUoCkLHqWc0Y+PneHE=
github.com/smallstep/cli v0.17.6 h1:0npb8eQGDgEBPziYXb9tW4f4S5jt8aRRmEJvs97oh+Y=
github.com/smallstep/nosql v0.3.8 h1:1/EWUbbEdz9ai0g9Fd09VekVjtxp+5+gIHpV2PdwW3o=
github.com/smallstep/truststore v0.9.6 h1:vNzEJmaJL0XOZD8uouXLmYu4/aP1UQ/wHUopH3qKeYA=
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
github.com/yuin/goldmark v1.4.1 h1:/vn0k+RBvwlxEmP5E7SZMqNxPhfMVFEJiykr15/0XKM=
github.com/yuin/goldmark-highlighting v0.0.0-20210516132338-9216f9c5aa01 h1:0SJnXjE4jDClMW6grE0xpNhwpqbPwkBTn8zpVw5C0SI=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
go.step.sm/cli-utils v0.6.0 h1:sH4FxBcjmbxyilKXheSyJuKF/QjpojpiW90ERwUWOgQ=
go.step.sm/crypto v0.11.0 h1:VDpeVgEmqme/FK2w5QINxkOQ1FWOm/Wi2TwQXiacKr8=
go.step.sm/linkedca v0.5.0 h1:oZVRSpElM7lAL1XN2YkjdHwI/oIZ+1ULOnuqYPM6xjY=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 h1:3erb+vDS8lU1sxfDHF4/hhWyaXnhIaO+7RgL4fDZORA=
golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
google.golang.org/genproto v0.0.0-20210719143636-1d5a45f8e492 h1:7yQQsvnwjfEahbNNEKcBHv3mR+HnB1ctGY/z1JXzx8M=
google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

How I install Caddy + Coraza WAF

  1. I added systemd service and built Caddy using this command:
xcaddy build --with github.com/jptosso/coraza-caddy@latest=github.com/konstantin-921/coraza-caddy@latest

github.com/konstantin-921/coraza-caddy@latest - it is my fork with uncommented plugins github.com/jptosso/coraza-libinjection and github.com/coraza-pcre from caddy/main.go

  1. Downloaded CSR and put it in caddy dir (you can find paths in include section)

  2. Added following settings to Caddyfile:

{
	debug
	auto_https off
	log {
		output file /var/log/caddy-access.log
	}
	order coraza_waf first
}

example.domain.com {
	coraza_waf {
		directives `
		SecAction "id:1,pass,log"
		`
		include /etc/caddy/coraza.conf-recommended
		include /etc/caddy/coreruleset/crs-setup.conf.example
		include /etc/caddy/coreruleset/rules/*.conf
	}
	tls /etc/caddy/domain.crt /etc/caddy/domain.key
	log {
		output file /var/log/caddy-access.log
	}
	respond "Hello HTTPS from example.domain.com!"
}
  1. Enabled SecRuleEngine On

  2. Started Caddy like service systemctl start caddy

Problem

My problem is that I get this error when I add includes to Caddyfile:

caddy[12696]: {"level":"error","ts":1642752737.1271152,"msg":"cannot read configurations file","path":"/etc/caddy/coreruleset/rules/*.conf"}
caddy[13844]: run: loading initial config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'waf': provision http.handlers.waf: cannot load waf directives invalid profile path

In rules folder I have all files from this folder - https://github.com/coreruleset/coreruleset/tree/v3.4/dev/rules. All of the paths look right. I don't understand what's wrong.

Caddy can be started if I specify a specific file. For example, like this:

include /etc/caddy/crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf

But the Coraza itself apparently does not work because my requests with LFI vulnerabilities are freely handled by Caddy although they should be blocked by Coraza.

Build tag KO?

Hello,

I am trying to keep track of the version I use of coraza-caddy, but I have issue when calling it with the new release:
xcaddy build --with github.com/corazawaf/[email protected]

[...]
#0 1.031 go: added golang.org/x/term v0.5.0
#0 1.031 go: added golang.org/x/text v0.7.0
#0 1.031 go: added golang.org/x/tools v0.2.0
#0 1.031 go: added google.golang.org/protobuf v1.28.1
#0 1.034 2023/05/30 20:59:10 [INFO] exec (timeout=-2562047h47m16.854775808s): /usr/local/go/bin/go get -d -v github.com/corazawaf/coraza-caddy/[email protected] github.com/caddyserver/caddy/[email protected]
#0 11.08 go: github.com/corazawaf/[email protected]: invalid version: module contains a go.mod file, so module path must match major version ("github.com/corazawaf/coraza-caddy/v2")
#0 11.08 2023/05/30 20:59:20 [FATAL] exit status 1

When I specify the previous release, it is working fine:
xcaddy build --with github.com/corazawaf/[email protected]

Here is the Dockerfile I use:

# Set Caddy release tag
ARG CADDY_TAG="2.6-builder-alpine"

# Use official Caddy builder image
FROM caddy:"${CADDY_TAG}" as builder-caddy

# Build Caddy with Coraza
RUN --mount=type=cache,target=/go,id=caddy \
  xcaddy build --with github.com/corazawaf/[email protected]

Is it me doing something wrong or is there an issue with metadata somewhere?

Please note, when I try this way, I get the same error:
xcaddy build --with github.com/corazawaf/coraza-caddy/[email protected]

Coraza doesn't seem to read new rules on caddy reload

Hi,

I've ben playing with the coraza caddy module and discovered that if new rules are added under the CRS directory issuing systemctl reload caddy is not enough to update configuration. To make it work you need systemctl restart caddy.

Is this intended?

Thx!

Data race warning detected upon starting Caddy

Hi! Our servers build Caddy with Go's data race detector and I've observed the following data race detections upon each server restart when any request comes in: https://gist.github.com/r3g-5z/19a4710c2a061c3248d27de4dde5ddae (logs are too long)

At the moment I'm setting up Coraza so my CRS is all default except for allowlisting the protocols HTTP/3 and HTTP/3.0 (setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0').

This warning only occurs once each restart, but it is consistent.

We're building Caddy from the main branch instead of the latest tag, and running and building with Go 1.20 (go version go1.20 linux/amd64).

Logging into JSON

First of all, thank you very much for the project !

The context

I installed coraza-caddy and included coreruleset following the Readme. Everything seems to work as expected.

I am trying to create an alert reporter to monitor the rules without opening the logs.

My issue

Logs don't seem to be formattable to JSON when i look into caddy logs (even with caddy logs in JSON, the part about coraza is in a string message) :

{
    "level": "error",
    "ts": 1661861476.6985302,
    "logger": "http.handlers.waf",
    "msg": "[client \"[1]\"] Coraza: Warning. Invalid character in request (outside of very strict set) [file \"coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\"] [line \"0\"] [id \"920273\"] [rev \"\"] [msg \"Invalid character in request (outside of very strict set)\"] [data \"ARGS:search_block_form=<br>\"] [severity \"critical\"] [ver \"OWASP_CRS/4.0.0-rc1\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-protocol\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/210/272\"] [tag \"paranoia-level/4\"] [hostname \"\"] [uri \"/Error\"] [unique_id \"bjmFA0ZaJ6RSkQufYKo\"]\n[client \"[1]\"] Coraza: Warning. Invalid character in request (outside of very strict set) [file \"coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\"] [line \"0\"] [id \"920273\"] [rev \"\"] [msg \"Invalid character in request (outside of very strict set)\"] [data \"REQUEST_BODY=search_block_form=<br>&submit.x=0&submit.y=0&form_build_id=form-DzAhIjoslwnpJp3m245LBTcJRO9uNj6SPL3ImE-LvUI&form_id=search_block_form\"] [severity \"critical\"] [ver \"OWASP_CRS/4.0.0-rc1\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-protocol\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/210/272\"] [tag \"paranoia-level/4\"] [hostname \"\"] [uri \"/Error\"] [unique_id \"bjmFA0ZaJ6RSkQufYKo\"]\n"
}

I searched into coraza API and a bit into source code without finding any way to get the output formated to JSON.

Should I try to code a custom solution for myself, or is there a setting I missed ?
P.S. If the option is quite easy to add to the project, I could try to make a PR if you indicate me the way...

Coraza with Caddy error include Coreruleset/rules

Hello,
Coraza_load_module

I try to use Coraza over Caddy with the OWASP Core Rule Set.
When I include the rules I got the follow error:

Log:
Jan 17 22:30:21 lab caddy[8434]: Error: loading initial config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'waf': provision http.handlers.waf: failed to compile rule (error parsing regexp: invalid or unsupported Perl syntax: (?<): FILES_NAMES|FILES "@rx (?<!&(?:[aAoOuUyY]uml)|&(?:[aAeEiIoOuU]circ)|&(?:[eEiIoOuUyY]acute)|&(?:[aAeEiIoOuU]grave)|&(?:[cC]cedil)|&(?:[aAnNoO]tilde)|&(?:amp)|&(?:apos));|['"=]" "id:920120,phase:2,block,t:none,t:urlDecodeUni,msg:'Attempted multipart/form-data bypass',logdata:'%{MATCHED_VAR}',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-protocol',tag:'paranoia-level/1',tag:'OWASP_CRS',tag:'capec/1000/210/272',ver:'OWASP_CRS/3.3.4',severity:'CRITICAL',setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

Looking the error I find the file make the issue is "REQUEST-922-MULTIPART-ATTACK.conf", when I remote this file I can restart Caddy with coraza without problem, but i think remove this file from the repository is not the solutions.

Thanks for help about this case.
Carlos Herrera

Does the connector support caddy json config ?

Discussed in corazawaf/coraza#769

Originally posted by Barnoux April 11, 2023
Hello,
i saw that the connector can be configured with Caddyfile but does it support the json format ?
If so what is the syntax ?

i already tried the caddy adapt command but it didn't work for me. The web server launch with a default configuration

Regards,

BBA

The rule reported an error

Caddyfile

        coraza_waf {
                include /waf/coraza.conf
                include /waf/coreruleset4/crs-setup.conf.example
                include /waf/coreruleset4/rules/*.conf
        }

Start error

# ./caddy start
2022/10/10 04:36:31.694 INFO    using adjacent Caddyfile
2022/10/10 04:36:31.696 WARN    Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies    {"adapter": "caddyfile", "file": "Caddyfile", "line": 2}
2022/10/10 04:36:31.697 INFO    redirected default logger       {"from": "stderr", "to": "/data/test/access.log"}
Error: loading initial config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'waf': provision http.handlers.waf: failed to compile rule (error parsing regexp: invalid or unsupported Perl syntax: `(?<`): FILES_NAMES|FILES "@rx (?<!&(?:[aAoOuUyY]uml)|&(?:[aAeEiIoOuU]circ)|&(?:[eEiIoOuUyY]acute)|&(?:[aAeEiIoOuU]grave)|&(?:[cC]cedil)|&(?:[aAnNoO]tilde)|&(?:amp)|&(?:apos));|['\"=]" "id:920120,phase:2,block,t:none,t:urlDecodeUni,msg:'Attempted multipart/form-data bypass',logdata:'%{MATCHED_VAR}',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-protocol',tag:'paranoia-level/1',tag:'OWASP_CRS',tag:'capec/1000/210/272',ver:'OWASP_CRS/3.3.4',severity:'CRITICAL',setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
Error: caddy process exited with error: exit status 1

Can http3 be used with Coraza?

Caddy webserver support the http3 protocol. However it looks like it can not be used with Coraza.

To enable http3 both 443/tcp and 443/udp need to be opened in the firewall. But access to the site is then blocked by Coraza and I see these entries in the log:
Coraza: Access denied (phase 1). HTTP protocol version is not allowed by policy @owasp_crs/REQUEST-920-PROTOCOL-ENFORCEMENT.conf

When I close 443/udp in the firewall Caddy will serve http2 and then all is working as expected.

Coraza not logging logs and audit logs

Hi,
I am using coraza with caddy and trying to find the audit logs noted that it does not leave the audit log registers and when change the config SecAuditLog got a error:

If used a rute /var/log/audit/coraza_audit.log I got Permission deny
and If I used another rute in my case I try with /var/log/caddy/coraza_audit.log I got file don't found (if I create log file back permission deny)

All logs that i receive came from caddy log and not from the coraza

I try seting the config "SecDebugLog /var/log/coraza/coraza.log" with "SexDebugLogLevel 6" but not generate any file.
and if I using audit log "SecAuditLogDir /var/log/audit/audit_coraza.log", it's generate a permission error even with permission 777, only if using on /tmp/ folder not geting a error but it's not generate any file or log.

anyone knows how to fix the permission deny?

Spurious "failed to parse server name" messages

I'm getting the following line in my logs when I access my sites:

{"level":"warn","ts":1686448129.858539,"logger":"http.handlers.waf","msg":"failed to parse server name","tx_id":"_______________","error":"failed to parse server name from authority \"sub.example.com\", address sub.example.com: missing port in address"}

I've noticed that some sites work perfectly fine with this warning while other sites will just throw up a blank page with a 200 response code. (Edit: warning message not indicative of this problem)

Should I be worried about this warning? Is there a way to fix it?

Here is a part of my Caddyfile:

sub.example.com {
	reverse_proxy 127.0.0.1:1642

	coraza_waf {
		load_owasp_crs
		directives `
			Include @coraza.conf-recommended
			Include @crs-setup.conf.example
			Include @owasp_crs/*.conf
			SecRuleEngine On
		`
	}
}

Memory leak : body files are not deleted in SecTmpDir

I just noticed coraza is creating many files in directory specified in SecTmpDir and dont remove them afterward.

My config :

coraza_waf {
		directives `
			SecAction \
				"id:900000,\
				phase:1,\
				nolog,\
				pass,\
				t:none,\
				setvar:tx.blocking_paranoia_level={args.0}"
			SecAction \
				"id:900001,\
				phase:1,\
				nolog,\
				pass,\
				t:none,\
				setvar:tx.detection_paranoia_level={args.1}"
		`
		include coraza.conf
		include coreruleset/crs-setup.conf
		include coreruleset/rules/*.conf
	}

coraza.conf

# -- Rule engine initialization ----------------------------------------------

# Enable Coraza, attaching it to every transaction. Use detection
# only to start with, because that minimises the chances of post-installation
# disruption.
#
# SecRuleEngine DetectionOnly
SecRuleEngine On


# -- Request body handling ---------------------------------------------------

# Allow Coraza to access request bodies. If you don't, Coraza
# won't be able to see any POST parameters, which opens a large security
# hole for attackers to exploit.
#
SecRequestBodyAccess Off

# Enable XML request body parser.
# Initiate XML Processor in case of xml content-type
#
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
     "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"

# Enable JSON request body parser.
# Initiate JSON Processor in case of JSON content-type; change accordingly
# if your application does not use 'application/json'
#
SecRule REQUEST_HEADERS:Content-Type "application/json" \
     "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"

# Sample rule to enable JSON request body parser for more subtypes.
# Uncomment or adapt this rule if you want to engage the JSON
# Processor for "+json" subtypes
#
#SecRule REQUEST_HEADERS:Content-Type "^application/.+[+]json$" \
#     "id:'200006',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"

# Maximum request body size we will accept for buffering. If you support
# file uploads then the value given on the first line has to be as large
# as the largest file you are willing to accept. The second value refers
# to the size of data, with files excluded. You want to keep that value as
# low as practical.
#
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

# What to do if the request body size is above our configured limit.
# Keep in mind that this setting will automatically be set to ProcessPartial
# when SecRuleEngine is set to DetectionOnly mode in order to minimize
# disruptions when initially deploying Coraza.
#
SecRequestBodyLimitAction Reject

# Verify that we've correctly processed the request body.
# As a rule of thumb, when failing to process a request body
# you should reject the request (when deployed in blocking mode)
# or log a high-severity alert (when deployed in detection-only mode).
#
SecRule REQBODY_ERROR "!@eq 0" \
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"

# By default be strict with what we accept in the multipart/form-data
# request body. If the rule below proves to be too strict for your
# environment consider changing it to detection-only. You are encouraged
# _not_ to remove it altogether.
#
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:400, \
msg:'Multipart request body failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"

# Did we see anything that might be a boundary?
#
# Here is a short description about the Coraza Multipart parser: the
# parser returns with value 0, if all "boundary-like" line matches with
# the boundary string which given in MIME header. In any other cases it returns
# with different value, eg. 1 or 2.
#
# The RFC 1341 descript the multipart content-type and its syntax must contains
# only three mandatory lines (above the content):
# * Content-Type: multipart/mixed; boundary=BOUNDARY_STRING
# * --BOUNDARY_STRING
# * --BOUNDARY_STRING--
#
# First line indicates, that this is a multipart content, second shows that
# here starts a part of the multipart content, third shows the end of content.
#
# If there are any other lines, which starts with "--", then it should be
# another boundary id - or not.
#
# After 3.0.3, there are two kinds of types of boundary errors: strict and permissive.
#
# If multipart content contains the three necessary lines with correct order, but
# there are one or more lines with "--", then parser returns with value 2 (non-zero).
#
# If some of the necessary lines (usually the start or end) misses, or the order
# is wrong, then parser returns with value 1 (also a non-zero).
#
# You can choose, which one is what you need. The example below contains the
# 'strict' mode, which means if there are any lines with start of "--", then
# Coraza blocked the content. But the next, commented example contains
# the 'permissive' mode, then you check only if the necessary lines exists in
# correct order. Whit this, you can enable to upload PEM files (eg "----BEGIN.."),
# or other text files, which contains eg. HTTP headers.
#
# The difference is only the operator - in strict mode (first) the content blocked
# in case of any non-zero value. In permissive mode (second, commented) the
# content blocked only if the value is explicit 1. If it 0 or 2, the content will
# allowed.
#

#
# See #1747 and #1924 for further information on the possible values for
# MULTIPART_UNMATCHED_BOUNDARY.
#
SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
    "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"

# Some internal errors will set flags in TX and we will need to look for these.
# All of these are prefixed with "MSC_".  The following flags currently exist:
#
# COR_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded.
#
SecRule TX:/^COR_/ "!@streq 0" \
        "id:'200005',phase:2,t:none,deny,msg:'Coraza internal error flagged: %{MATCHED_VAR_NAME}'"


# -- Response body handling --------------------------------------------------

# Allow Coraza to access response bodies. 
# You should have this directive enabled in order to identify errors
# and data leakage issues.
# 
# Do keep in mind that enabling this directive does increases both
# memory consumption and response latency.
#
SecResponseBodyAccess Off

# Which response MIME types do you want to inspect? You should adjust the
# configuration below to catch documents but avoid static files
# (e.g., images and archives).
#
SecResponseBodyMimeType text/plain text/html text/xml

# Buffer response bodies of up to 512 KB in length.
SecResponseBodyLimit 524288

# What happens when we encounter a response body larger than the configured
# limit? By default, we process what we have and let the rest through.
# That's somewhat less secure, but does not break any legitimate pages.
#
SecResponseBodyLimitAction ProcessPartial


# -- Filesystem configuration ------------------------------------------------

# The location where Coraza stores temporary files (for example, when
# it needs to handle a file upload that is larger than the configured limit).
# 
# This default setting is chosen due to all systems have /tmp available however, 
# this is less than ideal. It is recommended that you specify a location that's private.
#
SecTmpDir /tmp/coraza/tmp

# The location where Coraza will keep its persistent data.  This default setting 
# is chosen due to all systems have /tmp available however, it
# too should be updated to a place that other users can't access.
#
SecDataDir /tmp/coraza/data


# -- File uploads handling configuration -------------------------------------

# The location where Coraza stores intercepted uploaded files. This
# location must be private to Coraza. You don't want other users on
# the server to access the files, do you?
#
#SecUploadDir /opt/coraza/var/upload/

# By default, only keep the files that were determined to be unusual
# in some way (by an external inspection script). For this to work you
# will also need at least one file inspection rule.
#
#SecUploadKeepFiles RelevantOnly

# Uploaded files are by default created with permissions that do not allow
# any other user to access them. You may need to relax that if you want to
# interface Coraza to an external program (e.g., an anti-virus).
#
#SecUploadFileMode 0600


# -- Debug log configuration -------------------------------------------------

# Default debug log path
# Debug levels:
# 1: fatal
# 2: panic
# 3: error
# 4: warn
# 5: info
# 6: debug
# Most logging has not been implemented because it will be replaced with
# advanced rule profiling options
#SecDebugLog /opt/coraza/var/log/debug.log
#SecDebugLogLevel 3


# -- Audit log configuration -------------------------------------------------

# Log the transactions that are marked by a rule, as well as those that
# trigger a server error (determined by a 5xx or 4xx, excluding 404,  
# level response status codes).
#
SecAuditEngine On
# SecAuditLog /var/log/caddy/waf.log

# Log everything we know about a transaction.
# SecAuditLogParts ABCFHZ

# Use a single file for logging. This is much easier to look at, but
# assumes that you will use the audit log only occasionally.
#
# SecAuditLogType Serial
SecAuditLogType concurrent 
SecAuditLogStorageDir /var/log/caddy/
SecAuditLogRelevantStatus "^(?:(5|4)(0|1)[0-9])$"


# -- Miscellaneous -----------------------------------------------------------

# Use the most commonly used application/x-www-form-urlencoded parameter
# separator. There's probably only one application somewhere that uses
# something else so don't expect to change this value.
#
SecArgumentSeparator &

# Settle on version 0 (zero) cookies, as that is what most applications
# use. Using an incorrect cookie version may open your installation to
# evasion attacks (against the rules that examine named cookies).
#
SecCookieFormat 0

We put it in prod yesterday and it growed at about 25 GiB in the night
I hope I misconfigured something...

Caddy handle_errors not working with v2

Hello,

Whilst working with the most recent version (v2) of this module, I observed that the handle_errors directive is no longer functional with the 403 code initiated by the WAF. However, in the v1.2.2 version of the module, this feature operates correctly.

My configuration (the commented parts are used in v2):

	# Error handling
	handle_errors {
		reverse_proxy http://localhost:5001 {
			respond "Hello"
		}
	}


        coraza_waf {
			# load_owasp_crs
			# directives `
			include /waf/coraza/coraza.conf-recommended
			include /waf/coreruleset/crs-setup.conf.example
			include /waf/coreruleset/rules/*.conf
			# `
        }

In version 1.2.2, the activation of a rule prompts the display of the "Hello" message. However, in version 2, the standard browser's 403 page is presented instead.

Thank you,
Simone

runtime error: slice bounds out of range

Description

Describe the issue that you're seeing.
caddy server container crashed with panic. hope this might help someone. great project thank you

cdn-in-a-box-caddy-1 | panic: runtime error: slice bounds out of range [862:0]
cdn-in-a-box-caddy-1 |
cdn-in-a-box-caddy-1 | goroutine 21235869 [running]:
cdn-in-a-box-caddy-1 | github.com/corazawaf/coraza/v3/internal/corazawaf.(*bodyBufferReader).Read(0xc047d6cd50, {0xc038774000?, 0x0?, 0x7fce60935688?})
cdn-in-a-box-caddy-1 | github.com/corazawaf/coraza/[email protected]/internal/corazawaf/body_buffer.go:98 +0x139
cdn-in-a-box-caddy-1 | io.discard.ReadFrom({}, {0x1f8f960, 0xc047d6cd50})
cdn-in-a-box-caddy-1 | io/io.go:611 +0x72
cdn-in-a-box-caddy-1 | io.copyBuffer({0x1f97800, 0x2ca05e0}, {0x1f8f960, 0xc047d6cd50}, {0xc05461a000, 0x8000, 0x8000})
cdn-in-a-box-caddy-1 | io/io.go:413 +0x14b
cdn-in-a-box-caddy-1 | io.(*multiReader).writeToWithBuffer(0xc051094c48, {0x1f97800, 0x2ca05e0}, {0xc05461a000, 0x8000, 0x8000})
cdn-in-a-box-caddy-1 | io/multi.go:54 +0x125
cdn-in-a-box-caddy-1 | io.(*multiReader).WriteTo(0x19bcd00?, {0x1f97800, 0x2ca05e0})
cdn-in-a-box-caddy-1 | io/multi.go:45 +0x56
cdn-in-a-box-caddy-1 | io.copyBuffer({0x1f97800, 0x2ca05e0}, {0x7fce601809b8, 0xc047d4bbf0}, {0x0, 0x0, 0x0})
cdn-in-a-box-caddy-1 | io/io.go:409 +0x16e
cdn-in-a-box-caddy-1 | io.Copy(...)
cdn-in-a-box-caddy-1 | io/io.go:386
cdn-in-a-box-caddy-1 | net/http.(*transferWriter).doBodyCopy(0xc02cddcdc0, {0x1f97800?, 0x2ca05e0?}, {0x7fce601809b8?, 0xc047d4bbf0?})
cdn-in-a-box-caddy-1 | net/http/transfer.go:412 +0x4d
cdn-in-a-box-caddy-1 | net/http.(*transferWriter).writeBody(0xc02cddcdc0, {0x1f8e160, 0xc0293ac640})
cdn-in-a-box-caddy-1 | net/http/transfer.go:375 +0x418
cdn-in-a-box-caddy-1 | net/http.(*Request).write(0xc069109700, {0x1f8e160, 0xc0293ac640}, 0x0, 0x0, 0x0)
cdn-in-a-box-caddy-1 | net/http/request.go:701 +0xb46
cdn-in-a-box-caddy-1 | net/http.(*persistConn).writeLoop(0xc0595f9b00)
cdn-in-a-box-caddy-1 | net/http/transport.go:2395 +0x174
cdn-in-a-box-caddy-1 | created by net/http.(*Transport).dialConn
cdn-in-a-box-caddy-1 | net/http/transport.go:1752 +0x1791

Steps to reproduce

Clear steps describing how to reproduce the issue. Please please please link to a demo project if possible, this makes your issue much easier to diagnose (seriously).
reverse proxy server being hammered by bots

Expected result

What should happen?

Actual result

What happened.

Customize how 403 pages display unique_id fields

To prevent interception, I need more user-unique_id fields to query the audit log. So I wanted to show the field unique_id up the 403 page, but I didn't know how to do that.

My configuration is for example below

:8080 {
        root * /data/test
        file_server
        ...
        handle_errors {
                @403 {
                        expression {http.error.status_code} == 403
                }
                root * /data/test
                rewrite @403 /403.html
                file_server
                import sec
        }
        coraza_waf {
                ....
        }
}

Broken redirection 301 changed to 200, resulting in white page

Hi,

Wanted to configure a Wordpress instance secured by CORAZA Waf with CRS, started with just empty config to check if the reverse proxy is working, and it wasnt... 😄

So, that's the config:

{
    admin off
    auto_https off
    order coraza_waf first
}


http://example.org:8081/ {
    coraza_waf {
        
    }

   reverse_proxy http://127.0.0.1:8080/
}

On the http://127.0.0.1:8080/ there is a plain Wordpress installation on it's own NGINX.

Scenarios:

  • I remove block coraza_waf -> it works
  • I disable Caddy at all and use NGINX, it works
  • I increase verbosity, then I get:
SecAction "id:1,pass,log"
SecAuditLog /dev/stdout
SecDebugLog /dev/stdout
SecDebugLogLevel 5
{"level":"warn","ts":1653157564.0115337,"msg":"Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
{"level":"warn","ts":1653157564.0118072,"logger":"admin","msg":"admin endpoint disabled"}
{"level":"warn","ts":1653157564.011933,"logger":"http","msg":"automatic HTTPS is completely disabled for server","server_name":"srv0"}
{"level":"warn","ts":1653157564.011956,"logger":"http","msg":"automatic HTTPS is completely disabled for server","server_name":"srv1"}
{"level":"warn","ts":1653157564.0119655,"logger":"http","msg":"automatic HTTPS is completely disabled for server","server_name":"srv2"}
{"level":"info","ts":1653157564.012178,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc00048acb0"}
{"level":"info","ts":1653157564.0125582,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/.local/share/caddy"}
{"level":"info","ts":1653157564.012748,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"info","ts":1653157564.0128853,"msg":"autosaved config (load with --resume flag)","file":"/.config/caddy/autosave.json"}
{"level":"info","ts":1653157564.0130568,"msg":"serving initial configuration"}
{"level":"error","ts":1653157584.9115057,"logger":"http.handlers.waf","msg":"[client \"10.42.0.0\"] Coraza: Warning.  [file \"\"] [line \"0\"] [id \"1\"] [rev \"\"] [msg \"\"] [data \"\"] [severity \"emergency\"] [ver \"\"] [maturity \"0\"] [accuracy \"0\"] [hostname \"\"] [uri \"/wp-admin/\"] [unique_id \"PLqC91DKwSNTMfG4QWr\"]"}
{"level":"debug","ts":1653157584.9111702,"caller":"[email protected]/waf.go:261","msg":"new transaction created","event":"NEW_TRANSACTION","txid":"PLqC91DKwSNTMfG4QWr"}
{"level":"debug","ts":1653157584.911321,"caller":"[email protected]/rulegroup.go:116","msg":"Evaluating phase","event":"EVALUATE_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":1}
{"level":"debug","ts":1653157584.911337,"caller":"[email protected]/rulegroup.go:173","msg":"Finished phase","event":"FINISH_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":1,"rules":0}
{"level":"debug","ts":1653157584.9113533,"caller":"[email protected]/rulegroup.go:116","msg":"Evaluating phase","event":"EVALUATE_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":2}
{"level":"debug","ts":1653157584.9113638,"caller":"[email protected]/rule.go:236","msg":"Evaluating rule","rule":1,"raw":"SecAction id:1,pass,log","tx":"PLqC91DKwSNTMfG4QWr","event":"EVALUATE_RULE","is_chain":false}
{"level":"debug","ts":1653157584.9113884,"caller":"[email protected]/rule.go:258","msg":"Forcing rule match","txid":"PLqC91DKwSNTMfG4QWr","rule":1,"event":"RULE_FORCE_MATCH"}
{"level":"debug","ts":1653157584.9114132,"caller":"[email protected]/rule.go:399","msg":"evaluating action","type":"non_disruptive","txid":"PLqC91DKwSNTMfG4QWr","rule":1,"action":"log"}
{"level":"debug","ts":1653157584.9114475,"caller":"[email protected]/rule.go:363","msg":"Detecting rule disruptive action","txid":"PLqC91DKwSNTMfG4QWr","rule":1}
{"level":"debug","ts":1653157584.911467,"caller":"[email protected]/rule.go:366","msg":"Evaluating action","type":"disruptive or flow","txid":"PLqC91DKwSNTMfG4QWr","rule":1,"action":"pass"}
{"level":"debug","ts":1653157584.9114861,"caller":"[email protected]/transaction.go:279","msg":"rule matched","txid":"PLqC91DKwSNTMfG4QWr","rule":1}
{"level":"debug","ts":1653157584.9115162,"caller":"[email protected]/rule.go:376","msg":"finished evaluating rule","txid":"PLqC91DKwSNTMfG4QWr","rule":1,"matched_values":0,"event":"FINISH_RULE","is_chain":false}
{"level":"debug","ts":1653157584.9115338,"caller":"[email protected]/rulegroup.go:173","msg":"Finished phase","event":"FINISH_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":2,"rules":1}
{"level":"debug","ts":1653157590.2650416,"caller":"[email protected]/rulegroup.go:116","msg":"Evaluating phase","event":"EVALUATE_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":3}
{"level":"debug","ts":1653157590.2651434,"caller":"[email protected]/rulegroup.go:173","msg":"Finished phase","event":"FINISH_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":3,"rules":0}
{"level":"debug","ts":1653157590.2655733,"caller":"[email protected]/rulegroup.go:116","msg":"Evaluating phase","event":"EVALUATE_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":5}
{"level":"debug","ts":1653157590.2656057,"caller":"[email protected]/rulegroup.go:173","msg":"Finished phase","event":"FINISH_PHASE","txid":"PLqC91DKwSNTMfG4QWr","phase":5,"rules":0}
{"level":"debug","ts":1653157590.2656202,"caller":"[email protected]/transaction.go:795","msg":"Transaction not marked for audit logging, AuditEngine is disabled","tx":"PLqC91DKwSNTMfG4QWr"}

Actual response

< HTTP/2 200 
< date: Sat, 21 May 2022 19:10:18 GMT
< content-type: text/html; charset=UTF-8
< location: https://.../wp-login.php?redirect_to=https%3A%2F%2F...%2Fwp-admin%2F&reauth=1
< cache-control: no-cache, must-revalidate, max-age=0
< expires: Wed, 11 Jan 1984 05:00:00 GMT
< x-redirect-by: WordPress
< strict-transport-security: max-age=15724800; includeSubDomains

Expected response (when coraza_waf block is disabled)

< HTTP/2 302 
< date: Sun, 22 May 2022 06:28:39 GMT
< content-type: text/html; charset=UTF-8
< location: https://.../wp-login.php?redirect_to=https%3A%2F%2F...%2Fwp-admin%2F&reauth=1
< cache-control: no-cache, must-revalidate, max-age=0
< expires: Wed, 11 Jan 1984 05:00:00 GMT
< x-redirect-by: WordPress
< strict-transport-security: max-age=15724800; includeSubDomains

Payload failing

It seems coraza is shrinking the payload, I should implement a system that sends a clean reader to Caddy.

It does not generate any error, except an HTTP 2 error.

curl 'https://somewp/wp-admin/options.php' \
  -H 'origin: https://somewp' \
  -H 'content-type: application/x-www-form-urlencoded' \
  --data-raw 'option_page=discussion&action=update&_wpnonce=...&_wp_http_referer=%2Fwp-admin%2Foptions-discussion.php%3Fsettings-updated%3Dtrue&default_pingback_flag=1&default_ping_status=open&default_comment_status=open&require_name_email=1&close_comments_days_old=14&show_comments_cookies_opt_in=1&thread_comments=1&thread_comments_depth=5&comments_per_page=50&default_comments_page=newest&comment_order=asc&comments_notify=1&moderation_notify=1&comment_moderation=1&comment_previously_approved=1&comment_max_links=2&moderation_keys=&disallowed_keys=&show_avatars=1&avatar_rating=G&avatar_default=monsterid&submit=Save+Changes' 

[Bug] CRS rule 920171 is not applied on chunked-encoded requests

Dear Coraza-Caddy maintainer,

it seems if CRS rule 920171 is not applied on chunked-encoded requests (i.e., requests using Transfer-Encoding: chunked). I used the following request to identify this behavior:

GET / HTTP/1.1
Host: localhost
Connection: close
Transfer-Encoding: chunked

1
A
0

Note: Keep in mind of CRLFs after each line

Issue

This request gets accepted by Coraza+Caddy as the screenshots below demostrate:

image

However, it is expected that a GET request with a message body is blocked by rule 920171.

Side Note

Sending this request to another CRS engine (e.g., ModSecurity) triggers the expected rejection:

image

Here ModSecurity's logs indicating the resposible rule:

image

Impact

This has no severe impact since it seems all other rules are still applied on the body as expected. Here a further request line was embedded into the body which triggers the respective rule:

image

Setup

Summarized I've used:

  • Coraza-Caddy plugin v1.2.2
  • Caddy v2.6.2
  • CRS v4.0.0-rc1 with default settings

Here is my Dockerfile I've used to build Caddy + Coraza:

# Caddy builder image is our base in order to compile the binary with Coraza support
FROM caddy:2.6.2-builder AS builder

# Build Caddy binary with Coraza plugin included
RUN xcaddy build \
    --with github.com/corazawaf/[email protected]

# Replace original caddy binary within our custom image with binary containing Coraza
FROM nick/caddy:2.6.2-no-expose
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

RUN mkdir -p /etc/caddy/crs/rules

# Reverse proxy to dummy backend
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]

nick/caddy:2.6.2-no-expose is a customized Dockerfile which removed Docker's EXPOSE statements and an error (see this issue for more information). Here is its source code:

FROM alpine:3.16

RUN apk add --no-cache ca-certificates mailcap

RUN set -eux; \
	mkdir -p \
		/config/caddy \
		/data/caddy \
		/etc/caddy \
		/usr/share/caddy \
	; \
	wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/8c5fc6fc265c5d8557f17a18b778c398a2c6f27b/config/Caddyfile"; \
	wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/8c5fc6fc265c5d8557f17a18b778c398a2c6f27b/welcome/index.html"

# https://github.com/caddyserver/caddy/releases
ENV CADDY_VERSION v2.6.2

RUN set -eux; \
	apkArch="$(apk --print-arch)"; \
	case "$apkArch" in \
		x86_64)  binArch='amd64'; checksum='ae18c0facae7c8ee872492a1ba63a4c7608915d6d9fe267aef4f869cf65ebd4b7f9ff57f609aff2bd52db98c761d877b574aea2c0c9ddc2ec53d0d5e174cb542' ;; \
		armhf)   binArch='armv6'; checksum='6de688e6514df67594635c79be51a3fe3b7b29254b36349955979571d0624dd9bb228abcb798e76fc64ec0e1c4884443c3fd5074a5b5124ee895d29d239bcf1c' ;; \
		armv7)   binArch='armv7'; checksum='ba2186fd97c2e3f8930ee04bf01774938fc3682365fe4be70d9326f2b2a430f337c617f2c385aaa3d4e6dccb7ba980990d26cdc395574e6a5172c4f74cd9391d' ;; \
		aarch64) binArch='arm64'; checksum='91b5d50cd5c0dd84bf7dfcc437880df0d39dc62af57574cea2b560000c5bf12ba415b8723c5cb091276a93b979249ff939d567fef3a2a6ed417f93af266effcc' ;; \
		ppc64el|ppc64le) binArch='ppc64le'; checksum='f8aa3a478a989217a5f4e6b58936d2a69ffb99f2b7625760451ecab6fdc6d2534f815b8414a2121d63cdbea4f92022cebaa8550f9e3a61681ec25893ebf11ee6' ;; \
		s390x)   binArch='s390x'; checksum='2c8f9b6b28194dcc14db98c0657f6a47f35dbfa6c0a45fc485b488ada7c5b77abb4f880d3763dac1699d1007ba8e0f622a075fc7f394a0f3898fb90883c00407' ;; \
		*) echo >&2 "error: unsupported architecture ($apkArch)"; exit 1 ;;\
	esac; \
	wget -O /tmp/caddy.tar.gz "https://github.com/caddyserver/caddy/releases/download/v2.6.2/caddy_2.6.2_linux_${binArch}.tar.gz"; \
	echo "$checksum  /tmp/caddy.tar.gz" | sha512sum -c; \
	tar x -z -f /tmp/caddy.tar.gz -C /usr/bin caddy; \
	rm -f /tmp/caddy.tar.gz; \
	chmod +x /usr/bin/caddy; \
	caddy version

# set up nsswitch.conf for Go's "netgo" implementation
# - https://github.com/docker-library/golang/blob/1eb096131592bcbc90aa3b97471811c798a93573/1.14/alpine3.12/Dockerfile#L9
RUN [ -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf

# See https://caddyserver.com/docs/conventions#file-locations for details
ENV XDG_CONFIG_HOME /config
ENV XDG_DATA_HOME /data

LABEL org.opencontainers.image.version=v2.6.2
LABEL org.opencontainers.image.title=Caddy
LABEL org.opencontainers.image.description="a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go"
LABEL org.opencontainers.image.url=https://caddyserver.com
LABEL org.opencontainers.image.documentation=https://caddyserver.com/docs
LABEL org.opencontainers.image.vendor="Light Code Labs"
LABEL org.opencontainers.image.licenses=Apache-2.0
LABEL org.opencontainers.image.source="https://github.com/caddyserver/caddy-docker"

# DON'T NEED THEM
#EXPOSE 80
#EXPOSE 443
#EXPOSE 443/udp
#EXPOSE 2019

WORKDIR /srv

CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]

Caddy configuration file:

# Global configuration block
{
	# This line says, in a chain of HTTP handlers execute coraza_waf block first
	order coraza_waf first
}

# Configuration block for site 0.0.0.0:80
:80 {
	# Configure Coraza WAF with CRS v4.0.0-rc1
	coraza_waf {
		include /etc/caddy/coraza.conf
		include /etc/caddy/crs/crs-setup.conf
		include /etc/caddy/crs/rules/*.conf
	}
}

Coraza configuration:

# -- Rule engine initialization ----------------------------------------------

# Enable Coraza, attaching it to every transaction. Use detection
# only to start with, because that minimises the chances of post-installation
# disruption.
#
SecRuleEngine On


# -- Request body handling ---------------------------------------------------

# Allow Coraza to access request bodies. If you don't, Coraza
# won't be able to see any POST parameters, which opens a large security
# hole for attackers to exploit.
#
SecRequestBodyAccess On

# Enable XML request body parser.
# Initiate XML Processor in case of xml content-type
#
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
     "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"

# Enable JSON request body parser.
# Initiate JSON Processor in case of JSON content-type; change accordingly
# if your application does not use 'application/json'
#
SecRule REQUEST_HEADERS:Content-Type "application/json" \
     "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"

# Sample rule to enable JSON request body parser for more subtypes.
# Uncomment or adapt this rule if you want to engage the JSON
# Processor for "+json" subtypes
#
#SecRule REQUEST_HEADERS:Content-Type "^application/.+[+]json$" \
#     "id:'200006',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"

# Maximum request body size we will accept for buffering. If you support
# file uploads then the value given on the first line has to be as large
# as the largest file you are willing to accept. The second value refers
# to the size of data, with files excluded. You want to keep that value as
# low as practical.
#
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

# What to do if the request body size is above our configured limit.
# Keep in mind that this setting will automatically be set to ProcessPartial
# when SecRuleEngine is set to DetectionOnly mode in order to minimize
# disruptions when initially deploying Coraza.
#
SecRequestBodyLimitAction Reject

# Verify that we've correctly processed the request body.
# As a rule of thumb, when failing to process a request body
# you should reject the request (when deployed in blocking mode)
# or log a high-severity alert (when deployed in detection-only mode).
#
SecRule REQBODY_ERROR "!@eq 0" \
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"

# By default be strict with what we accept in the multipart/form-data
# request body. If the rule below proves to be too strict for your
# environment consider changing it to detection-only. You are encouraged
# _not_ to remove it altogether.
#
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:400, \
msg:'Multipart request body failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"

# Did we see anything that might be a boundary?
#
# Here is a short description about the Coraza Multipart parser: the
# parser returns with value 0, if all "boundary-like" line matches with
# the boundary string which given in MIME header. In any other cases it returns
# with different value, eg. 1 or 2.
#
# The RFC 1341 descript the multipart content-type and its syntax must contains
# only three mandatory lines (above the content):
# * Content-Type: multipart/mixed; boundary=BOUNDARY_STRING
# * --BOUNDARY_STRING
# * --BOUNDARY_STRING--
#
# First line indicates, that this is a multipart content, second shows that
# here starts a part of the multipart content, third shows the end of content.
#
# If there are any other lines, which starts with "--", then it should be
# another boundary id - or not.
#
# After 3.0.3, there are two kinds of types of boundary errors: strict and permissive.
#
# If multipart content contains the three necessary lines with correct order, but
# there are one or more lines with "--", then parser returns with value 2 (non-zero).
#
# If some of the necessary lines (usually the start or end) misses, or the order
# is wrong, then parser returns with value 1 (also a non-zero).
#
# You can choose, which one is what you need. The example below contains the
# 'strict' mode, which means if there are any lines with start of "--", then
# Coraza blocked the content. But the next, commented example contains
# the 'permissive' mode, then you check only if the necessary lines exists in
# correct order. Whit this, you can enable to upload PEM files (eg "----BEGIN.."),
# or other text files, which contains eg. HTTP headers.
#
# The difference is only the operator - in strict mode (first) the content blocked
# in case of any non-zero value. In permissive mode (second, commented) the
# content blocked only if the value is explicit 1. If it 0 or 2, the content will
# allowed.
#

#
# See #1747 and #1924 for further information on the possible values for
# MULTIPART_UNMATCHED_BOUNDARY.
#
SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
    "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"

# Some internal errors will set flags in TX and we will need to look for these.
# All of these are prefixed with "MSC_".  The following flags currently exist:
#
# COR_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded.
#
SecRule TX:/^COR_/ "!@streq 0" \
        "id:'200005',phase:2,t:none,deny,msg:'Coraza internal error flagged: %{MATCHED_VAR_NAME}'"


# -- Response body handling --------------------------------------------------

# Allow Coraza to access response bodies.
# You should have this directive enabled in order to identify errors
# and data leakage issues.
#
# Do keep in mind that enabling this directive does increases both
# memory consumption and response latency.
#
SecResponseBodyAccess On

# Which response MIME types do you want to inspect? You should adjust the
# configuration below to catch documents but avoid static files
# (e.g., images and archives).
#
SecResponseBodyMimeType text/plain text/html text/xml

# Buffer response bodies of up to 512 KB in length.
SecResponseBodyLimit 524288

# What happens when we encounter a response body larger than the configured
# limit? By default, we process what we have and let the rest through.
# That's somewhat less secure, but does not break any legitimate pages.
#
SecResponseBodyLimitAction ProcessPartial


# -- Filesystem configuration ------------------------------------------------

# The location where Coraza stores temporary files (for example, when
# it needs to handle a file upload that is larger than the configured limit).
#
# This default setting is chosen due to all systems have /tmp available however,
# this is less than ideal. It is recommended that you specify a location that's private.
#
SecTmpDir /tmp/

# The location where Coraza will keep its persistent data.  This default setting
# is chosen due to all systems have /tmp available however, it
# too should be updated to a place that other users can't access.
#
SecDataDir /tmp/


# -- File uploads handling configuration -------------------------------------

# The location where Coraza stores intercepted uploaded files. This
# location must be private to Coraza. You don't want other users on
# the server to access the files, do you?
#
#SecUploadDir /opt/coraza/var/upload/

# By default, only keep the files that were determined to be unusual
# in some way (by an external inspection script). For this to work you
# will also need at least one file inspection rule.
#
#SecUploadKeepFiles RelevantOnly

# Uploaded files are by default created with permissions that do not allow
# any other user to access them. You may need to relax that if you want to
# interface Coraza to an external program (e.g., an anti-virus).
#
#SecUploadFileMode 0600


# -- Debug log configuration -------------------------------------------------

# Default debug log path
# Debug levels:
# 1: fatal
# 2: panic
# 3: error
# 4: warn
# 5: info
# 6: debug
# Most logging has not been implemented because it will be replaced with
# advanced rule profiling options
SecDebugLog /var/log/coraza/debug.log
SecDebugLogLevel 3


# -- Audit log configuration -------------------------------------------------

# Log the transactions that are marked by a rule, as well as those that
# trigger a server error (determined by a 5xx or 4xx, excluding 404,
# level response status codes).
#
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:(5|4)(0|1)[0-9])$"

# Log everything we know about a transaction.
SecAuditLogParts ABIJDEFHZ

# Use a single file for logging. This is much easier to look at, but
# assumes that you will use the audit log only occasionally.
#
SecAuditLogType Serial
SecAuditLog /var/log/modsec_audit.log


# -- Miscellaneous -----------------------------------------------------------

# Use the most commonly used application/x-www-form-urlencoded parameter
# separator. There's probably only one application somewhere that uses
# something else so don't expect to change this value.
#
SecArgumentSeparator &

# Settle on version 0 (zero) cookies, as that is what most applications
# use. Using an incorrect cookie version may open your installation to
# evasion attacks (against the rules that examine named cookies).
#
SecCookieFormat 0

If I'm missing something please let me know. Otherwise I'm glad if I can contribute to your project!

King regards
Nick

Prometheus metrics

The WAF level should expose Prometheus metrics the same way Caddy does, some useful base metrics would be:

  • Total number of rules loaded
  • Total number of times a request was blocked

Duplicate modsecurity fields's in caddy logs's

Hello,

At first thank a lot for you work for this project he is very nice.
I found that some field in the log from coraza are duplicated see the log bellow when i tested an SQL injection.

{"level":"error","ts":1668631193.1862295,"logger":"http.handlers.waf","msg":"[client \"192.168.1.1\"] Coraza: Warning. SQL Injection Attack: SQL Boolean-based attack detected [file \"/ruleset/coreruleset/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"0\"] [id \"942130\"] [rev \"\"] [msg \"SQL Injection Attack: SQL Boolean-based attack detected\"] [data \"Matched Data:  1=1 found within ARGS:q: '1 OR 1=1\\\"\"] [severity \"critical\"] [ver \"OWASP_CRS/4.0.0-rc1\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/152/248/66\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"] [hostname \"\"] [uri \"/?q=%271%20OR%201=1%22\"] [unique_id \"VLS1AeezUlAFnWQyFd2\"]\n[client \"192.168.1.1\"] Coraza: Warning. SQL Injection Attack: SQL Boolean-based attack detected [file \"/ruleset/coreruleset/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"0\"] [id \"942130\"] [rev \"\"] [msg \"\"] [data \"\"] [severity \"critical\"] [ver \"OWASP_CRS/4.0.0-rc1\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/152/248/66\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"] [hostname \"\"] [uri \"/?q=%271%20OR%201=1%22\"] [unique_id \"VLS1AeezUlAFnWQyFd2\"]\n"}

if you beautify it:

{"level":"error","ts":1668631193.1862295,"logger":"http.handlers.waf","msg":"[client \"192.168.1.1\"] Coraza: Warning. SQL Injection Attack: SQL Boolean-based attack detected [file \"/ruleset/coreruleset/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"]
[line \"0\"]
[id \"942130\"]
[rev \"\"]
[msg \"SQL Injection Attack: SQL Boolean-based attack detected\"]
[data \"Matched Data:  1=1 found within ARGS:q: '1 OR 1=1\\\"\"]
[severity \"critical\"]
[ver \"OWASP_CRS/4.0.0-rc1\"]
[maturity \"0\"]
[accuracy \"0\"]
[tag \"application-multi\"]
[tag \"language-multi\"]
[tag \"platform-multi\"]
[tag \"attack-sqli\"]
[tag \"OWASP_CRS\"]
[tag \"capec/1000/152/248/66\"]
[tag \"PCI/6.5.2\"]
[tag \"paranoia-level/2\"]
[hostname \"\"]
[uri \"/?q=%271%20OR%201=1%22\"] #After unique_id this is exatcly the same.
[unique_id \"VLS1AeezUlAFnWQyFd2\"]\n[client \"192.168.1.1\"] Coraza: Warning. SQL Injection Attack: SQL Boolean-based attack detected [file \"/ruleset/coreruleset/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"]
[line \"0\"]
[id \"942130\"]
[rev \"\"]
[msg \"\"]
[data \"\"]
[severity \"critical\"]
[ver \"OWASP_CRS/4.0.0-rc1\"]
[maturity \"0\"]
[accuracy \"0\"]
[tag \"application-multi\"]
[tag \"language-multi\"]
[tag \"platform-multi\"]
[tag \"attack-sqli\"]
[tag \"OWASP_CRS\"]
[tag \"capec/1000/152/248/66\"]
[tag \"PCI/6.5.2\"]
[tag \"paranoia-level/2\"]
[hostname \"\"]
[uri \"/?q=%271%20OR%201=1%22\"]
[unique_id \"VLS1AeezUlAFnWQyFd2\"]\n"}

We can see that there is duplication, is it me or ?

Regards,

BBA

Missing hostname in WAF logs

Hi everyone,

I am currently trying to implement Coraza into my Caddy setup, but for some reason the hostname of blocked requests does not get logged. As you can see in the log samples below, the hostname is recorded as [hostname ""]

2023/06/15 11:08:02.985 WARN    http.handlers.waf       [client "192.168.178.11"] Coraza: Access denied (phase 1). POST without Content-Length or Transfer-Encoding headers [file "@owasp_crs/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "1543"] [id "920180"] [rev ""] [msg "POST without Content-Length or Transfer-Encoding headers"] [data "0"] [severity "warning"] [ver "OWASP_CRS/4.0.0-rc1"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/210/272"] [hostname ""] [uri "/api/add"] [unique_id "iicqKuOYWuBJfVcM"]

2023/06/15 11:08:02.985 ERROR   http.handlers.waf       [client "192.168.178.11"] Coraza: Access denied (phase 2). XSS Attack Detected via libinjection [file "@owasp_crs/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "4432"] [id "941100"] [rev ""] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS:url: <script>"] [severity "critical"] [ver "OWASP_CRS/4.0.0-rc1"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname ""] [uri "/api/add"] [unique_id "iicqKuOYWuBJfVcM"]

2023/06/15 11:08:02.985 ERROR   http.handlers.waf       [client "192.168.178.11"] Coraza: Access denied (phase 2). XSS Filter - Category 1: Script Tag Vector [file "@owasp_crs/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "4451"] [id "941110"] [rev ""] [msg "XSS Filter - Category 1: Script Tag Vector"] [data "Matched Data: <script> found within ARGS:url: <script>"] [severity "critical"] [ver "OWASP_CRS/4.0.0-rc1"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname ""] [uri "/api/add"] [unique_id "iicqKuOYWuBJfVcM"]

According to #35 this should be fixed, so I am not sure if there is a possible misconfiguration at play also.

I've compiled Caddy 2.6.4 with xcaddy in several ways, with the most recent command seen as below. AFAIK these versions should contain the servername fixes.

xcaddy build --with github.com/corazawaf/coraza-caddy/@v2.0.0-rc.2 --with github.com/corazawaf/coraza/@v3.0.0

My current Caddyfile looks like this.
I am using the current rule files from coraza-coreruleset, haven't made any changes except additionaly allowing HTTP/3 & HTTP/3.0 versions in crs-setup.conf.

{
        debug
        http_port 1180
        https_port 11443
        admin off
        auto_https off
        order coraza_waf first
        servers {
                metrics
        }
}

(tls) {
        tls ./{args.0}_ecc/fullchain.cer ./{args.0}_ecc/{args.0}.key
        header {
                Strict-Transport-Security max-age=63072000;includeSubDomains;preload
                X-Content-Type-Options nosniff
                X-Frame-Options SAMEORIGIN
                X-Robots-Tag none
        }
}

(waf) {
        coraza_waf {
          #load_owasp_crs
          directives `
           Include @coraza.conf-recommended
           Include @crs-setup.conf.example
           Include @owasp_crs/*.conf
           SecRuleEngine On
          `
 }
}

memes.example.com {
        import tls example.com
        import waf
        reverse_proxy 10.0.0.109:5001
}

Would be happy about some hints. Thank you 😀

Websocket connections not working as soon as Coraza is active

Hello everyone,

as already announced in your Slack channel, I am currently facing issues with Websocket connections in conjunction with coraza-caddy.
These connections work fine if I set SecRuleEngine Off or remove the corresponding snippet from my subdomain config in caddy, but as soon as Coraza is in the play, these websocket connections do not seem to be handled correctly, while the rest of HTTP requests seems to be fine.
The websocket connections also won't work with SecRuleEngine DetectionOnly set, which makes me assume that this may be some internal Coraza handling problem, and not the OWASP rules, Coraza config etc.

Setup

Linux LXC Debian 11
Caddy 2.6.4 + coraza 3.0.0 + coraza-caddy 2.0.0-rc2 with xcaddy

build-info

go      go1.20.5
path    caddy
mod     caddy   (devel)
dep     filippo.io/edwards25519 v1.0.0  h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
dep     github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96      h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
dep     github.com/BurntSushi/toml      v1.2.1  h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
dep     github.com/Masterminds/goutils  v1.1.1  h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
dep     github.com/Masterminds/semver/v3        v3.2.0  h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
dep     github.com/Masterminds/sprig/v3 v3.2.3  h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
dep     github.com/alecthomas/chroma/v2 v2.5.0  h1:CQCdj1BiBV17sD4Bd32b/Bzuiq/EqoNTrnIhyQAZ+Rk=
dep     github.com/antlr/antlr4/runtime/Go/antlr        v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
dep     github.com/aryann/difflib       v0.0.0-20210328193216-ff5ff6dc229b      h1:uUXgbcPDK3KpW29o4iy7GtuappbWT0l5NaMo9H9pJDw=
dep     github.com/beorn7/perks v1.0.1  h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
dep     github.com/caddyserver/caddy/v2 v2.6.4  h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=
dep     github.com/caddyserver/certmagic        v0.17.2 h1:o30seC1T/dBqBCNNGNHWwj2i5/I/FMjBbTAhjADP3nE=
dep     github.com/cenkalti/backoff/v4  v4.1.2  h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
dep     github.com/cespare/xxhash       v1.1.0  h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
dep     github.com/cespare/xxhash/v2    v2.1.2  h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
dep     github.com/chzyer/readline      v0.0.0-20180603132655-2972be24d48e      h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
dep     github.com/corazawaf/coraza-caddy/v2    v2.0.0-rc.2     h1:HY101opLin5TVKvNlyRv25LQc4HVvdJ9cIiFMgc0UO8=
dep     github.com/corazawaf/coraza-coreruleset v0.0.0-20230405190458-b4d2a6f6bdfh1:EU5PEFuQ4PTzkz2YFoCQwI73gu8GW95txz3dMNGsseA=
dep     github.com/corazawaf/coraza/v3  v3.0.0  h1:GvTzxcgtfQ76LneYL19Nkb1/T+2E/s3BRAOEt6h2sY0=
dep     github.com/corazawaf/libinjection-go    v0.1.2  h1:oeiV9pc5rvJ+2oqOqXEAMJousPpGiup6f7Y3nZj5GoM=
dep     github.com/cpuguy83/go-md2man/v2        v2.0.2  h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
dep     github.com/dgraph-io/badger     v1.6.2  h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8=
dep     github.com/dgraph-io/badger/v2  v2.2007.4       h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o=
dep     github.com/dgraph-io/ristretto  v0.1.0  h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI=
dep     github.com/dgryski/go-farm      v0.0.0-20200201041132-a6ae2369ad13      h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
dep     github.com/dlclark/regexp2      v1.7.0  h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
dep     github.com/dustin/go-humanize   v1.0.1  h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
dep     github.com/felixge/httpsnoop    v1.0.3  h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
dep     github.com/fxamacker/cbor/v2    v2.4.0  h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
dep     github.com/go-chi/chi   v4.1.2+incompatible     h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
dep     github.com/go-kit/kit   v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
dep     github.com/go-logfmt/logfmt     v0.5.1  h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
dep     github.com/go-logr/logr v1.2.3  h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
dep     github.com/go-logr/stdr v1.2.2  h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
dep     github.com/go-sql-driver/mysql  v1.6.0  h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
dep     github.com/golang/glog  v1.0.0  h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
dep     github.com/golang/protobuf      v1.5.2  h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
dep     github.com/golang/snappy        v0.0.4  h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
dep     github.com/google/cel-go        v0.13.0 h1:z+8OBOcmh7IeKyqwT/6IlnMvy621fYUqnTVPEdegGlU=
dep     github.com/google/uuid  v1.3.0  h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
dep     github.com/grpc-ecosystem/grpc-gateway  v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
dep     github.com/huandu/xstrings      v1.3.3  h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
dep     github.com/imdario/mergo        v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
dep     github.com/jackc/chunkreader/v2 v2.0.1  h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
dep     github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
dep     github.com/jackc/pgio   v1.0.0  h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
dep     github.com/jackc/pgpassfile     v1.0.0  h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
dep     github.com/jackc/pgproto3/v2    v2.3.1  h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
dep     github.com/jackc/pgservicefile  v0.0.0-20200714003250-2b9c44734f2b      h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
dep     github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
dep     github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E=
dep     github.com/jcchavezs/mergefs    v0.0.0-20230405222254-20429875efdd      h1:wj0PapN9ZM27EnZqqtvVHUpRUWDHEK3/H7gkBFj1qyw=
dep     github.com/klauspost/compress   v1.15.15        h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
dep     github.com/klauspost/cpuid/v2   v2.2.3  h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
dep     github.com/libdns/libdns        v0.2.1  h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
dep     github.com/manifoldco/promptui  v0.9.0  h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
dep     github.com/mattn/go-colorable   v0.1.8  h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
dep     github.com/mattn/go-isatty      v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
dep     github.com/matttproud/golang_protobuf_extensions        v1.0.1  h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
dep     github.com/mgutz/ansi   v0.0.0-20200706080929-d51e80ef957d      h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
dep     github.com/mholt/acmez  v1.1.0  h1:IQ9CGHKOHokorxnffsqDvmmE30mDenO1lptYZ1AYkHY=
dep     github.com/micromdm/scep/v2     v2.1.0  h1:2fS9Rla7qRR266hvUoEauBJ7J6FhgssEiq2OkSKXmaU=
dep     github.com/miekg/dns    v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
dep     github.com/mitchellh/copystructure      v1.2.0  h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
dep     github.com/mitchellh/go-ps      v1.0.0  h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
dep     github.com/mitchellh/reflectwalk        v1.0.2  h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
dep     github.com/petar-dambovaliev/aho-corasick       v0.0.0-20211021192214-5ab2d9280aa9        h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8=
dep     github.com/pkg/errors   v0.9.1  h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
dep     github.com/prometheus/client_golang     v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
dep     github.com/prometheus/client_model      v0.3.0  h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
dep     github.com/prometheus/common    v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
dep     github.com/prometheus/procfs    v0.8.0  h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
dep     github.com/quic-go/qpack        v0.4.0  h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
dep     github.com/quic-go/qtls-go1-20  v0.1.0  h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
dep     github.com/quic-go/quic-go      v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
dep     github.com/rs/xid       v1.4.0  h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
dep     github.com/russross/blackfriday/v2      v2.1.0  h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
dep     github.com/shopspring/decimal   v1.2.0  h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
dep     github.com/shurcooL/sanitized_anchor_name       v1.0.0  h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
dep     github.com/sirupsen/logrus      v1.9.0  h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
dep     github.com/slackhq/nebula       v1.6.1  h1:/OCTR3abj0Sbf2nGoLUrdDXImrCv0ZVFpVPP5qa0DsM=
dep     github.com/smallstep/certificates       v0.23.2 h1:7KSx9WfZ3CILV0XlsTrl+PK58YE4CHSgqobB6+ieQWs=
dep     github.com/smallstep/nosql      v0.5.0  h1:1BPyHy8bha8qSaxgULGEdqhXpNFXimAfudnauFVqmxw=
dep     github.com/smallstep/truststore v0.12.1 h1:guLUKkc1UlsXeS3t6BuVMa4leOOpdiv02PCRTiy1WdY=
dep     github.com/spf13/cast   v1.4.1  h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
dep     github.com/spf13/cobra  v1.6.1  h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
dep     github.com/spf13/pflag  v1.0.5  h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
dep     github.com/stoewer/go-strcase   v1.2.0  h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
dep     github.com/tailscale/tscert     v0.0.0-20230124224810-c6dc1f4049b2      h1:TrgfmCXwtWyFw85UkRGXt9qZRzdzt3nWt2Rerdecn0w=
dep     github.com/tidwall/gjson        v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
dep     github.com/tidwall/match        v1.1.1  h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
dep     github.com/tidwall/pretty       v1.2.1  h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
dep     github.com/urfave/cli   v1.22.12        h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8=
dep     github.com/x448/float16 v0.8.4  h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
dep     github.com/yuin/goldmark        v1.5.4  h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
dep     github.com/yuin/goldmark-highlighting/v2        v2.0.0-20220924101305-151362477c87        h1:Py16JEzkSdKAtEFJjiaYLYBOWGXc1r/xHj/Q/5lA37k=
dep     go.etcd.io/bbolt        v1.3.6  h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
dep     go.mozilla.org/pkcs7    v0.0.0-20210826202110-33d05740a352      h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
dep     go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp   v0.39.0 h1:vFEBG7SieZJzvnRWQ81jxpuEqe6J8Ex+hgc9CqOTzHc=
dep     go.opentelemetry.io/otel        v1.13.0 h1:1ZAKnNQKwBBxFtww/GwxNUyTf0AxkZzrukO8MeXqe4Y=
dep     go.opentelemetry.io/otel/exporters/otlp/internal/retry  v1.4.0  h1:j7AwzDdAQBJjcqayAaYbvpYeZzII7cEe5qJTu+De6UY=
dep     go.opentelemetry.io/otel/exporters/otlp/otlptrace       v1.4.0  h1:lRpP10E8oTGVmY1nVXcwelCT1Z8ca41/l5ce7AqLAss=
dep     go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.0  h1:buSx4AMC/0Z232slPhicN/fU5KIlj0bMngct5pcZhkI=
dep     go.opentelemetry.io/otel/metric v0.36.0 h1:t0lgGI+L68QWt3QtOIlqM9gXoxqxWLhZ3R/e5oOAY0Q=
dep     go.opentelemetry.io/otel/sdk    v1.13.0 h1:BHib5g8MvdqS65yo2vV1s6Le42Hm6rrw08qU6yz5JaM=
dep     go.opentelemetry.io/otel/trace  v1.13.0 h1:CBgRZ6ntv+Amuj1jDsMhZtlAPT6gbyIRdaIzFhfBSdY=
dep     go.opentelemetry.io/proto/otlp  v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c=
dep     go.step.sm/cli-utils    v0.7.5  h1:jyp6X8k8mN1B0uWJydTid0C++8tQhm2kaaAdXKQQzdk=
dep     go.step.sm/crypto       v0.23.2 h1:XGmQH9Pkpxop47cjYlUhF10L5roPCbu1BCZXopbeW8I=
dep     go.step.sm/linkedca     v0.19.0 h1:xuagkR35wrJI2gnu6FAM+q3VmjwsHScvGcJsfZ0GdsI=
dep     go.uber.org/atomic      v1.9.0  h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
dep     go.uber.org/multierr    v1.8.0  h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
dep     go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
dep     golang.org/x/crypto     v0.5.0  h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
dep     golang.org/x/exp        v0.0.0-20221205204356-47842c84f3db      h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
dep     golang.org/x/net        v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
dep     golang.org/x/sync       v0.1.0  h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
dep     golang.org/x/sys        v0.8.0  h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
dep     golang.org/x/term       v0.8.0  h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
dep     golang.org/x/text       v0.9.0  h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
dep     google.golang.org/genproto      v0.0.0-20230202175211-008b39050e57      h1:vArvWooPH749rNHpBGgVl+U9B9dATjiEhJzcWGlovNs=
dep     google.golang.org/grpc  v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ=
dep     google.golang.org/protobuf      v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
dep     gopkg.in/natefinch/lumberjack.v2        v2.2.1  h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
dep     gopkg.in/square/go-jose.v2      v2.6.0  h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
dep     gopkg.in/yaml.v3        v3.0.1  h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
dep     rsc.io/binaryregexp     v0.2.0  h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=
build   -buildmode=exe
build   -compiler=gc
build   -trimpath=true
build   CGO_ENABLED=0
build   GOARCH=amd64
build   GOOS=linux
build   GOAMD64=v1

Reproduce

Please follow this example to reproduce the issue

  1. Run a instance of RustPad
docker run --rm -dp 3030:3030 ekzhang/rustpad
  1. Run your instance of caddy+Coraza with the following Caddyfile (adapt accordingly)
{
        debug
        auto_https off
        order coraza_waf first
}

(tls) {
        tls /etc/acme/{args.0}_ecc/fullchain.cer /etc/acme/{args.0}_ecc/{args.0}.key
}

(waf) {
        coraza_waf {
          directives `
            SecRuleEngine Off
          `
 }
}

pad.example.com {
        import tls example.com
        import waf
        reverse_proxy localhost:3030
}
  1. When visiting the app via Caddy, you should then see Rustpad Connecting to the server... and then You are connected (or check WS connection in your browsers network inspector) - everything works fine.

  2. In the Caddyfile, replace SecRuleEngine Off with SecRuleEngine DetectionOnly and reload Caddy.

  3. Now, Rustpad wont be able to establish a websocket connection :( DEBUG log output should provide something like:

2023/06/24 14:45:22.808 DEBUG   http.handlers.reverse_proxy     selected upstream{"dial": "10.0.0.110:3030", "total_upstreams": 1}
2023/06/24 14:45:22.809 DEBUG   http.handlers.reverse_proxy     upstream roundtri{"upstream": "10.0.0.110:3030", "duration": 0.000513863, "request": {"remote_ip": "192.168.178.11", "remote_port": "56254", "proto": "HTTP/1.1", "method": "GET", "host": "pad.example.com:11443", "uri": "/api/socket/MCxiai", "headers": {"Connection": ["Upgrade"], "Origin": ["https://pad.example.com:11443"], "Sec-Websocket-Version": ["13"], "Accept-Language": ["de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"], "Sec-Websocket-Extensions": ["permessage-deflate; client_max_window_bits"], "Sec-Websocket-Key": ["FCOBxo+tJXz+iewTbsv4tQ=="], "X-Forwarded-Proto": ["https"], "Upgrade": ["websocket"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"], "Accept-Encoding": ["gzip, deflate, br"], "X-Forwarded-Host": ["pad.example.com:11443"], "Cache-Control": ["no-cache"], "Pragma": ["no-cache"], "X-Forwarded-For": ["192.168.178.11"]}, "tls": {"resumed": true, "version": 772, "cipher_suite": 4865, "proto": "http/1.1", "server_name": "pad.example.com"}}, "headers": {"Connection": ["upgrade"], "Upgrade": ["websocket"], "Sec-Websocket-Accept": ["Aqzjvc/3P75wBozHmowR/c98QBI="], "Date": ["Sat, 24 Jun 2023 14:45:21 GMT"]}, "status": 101}
2023/06/24 14:45:22.809 DEBUG   http.handlers.reverse_proxy     upgrading connection      {"upstream": "10.0.0.110:3030", "duration": 0.000513863, "request": {"remote_ip": "192.168.178.11", "remote_port": "56254", "proto": "HTTP/1.1", "method": "GET", "host": "pad.example.com:11443", "uri": "/api/socket/MCxiai", "headers": {"Connection": ["Upgrade"], "Origin": ["https://pad.example.com:11443"], "Sec-Websocket-Version": ["13"], "Accept-Language": ["de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"], "Sec-Websocket-Extensions": ["permessage-deflate; client_max_window_bits"], "Sec-Websocket-Key": ["FCOBxo+tJXz+iewTbsv4tQ=="], "X-Forwarded-Proto": ["https"], "Upgrade": ["websocket"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"], "Accept-Encoding": ["gzip, deflate, br"], "X-Forwarded-Host": ["pad.example.com:11443"], "Cache-Control": ["no-cache"], "Pragma": ["no-cache"], "X-Forwarded-For": ["192.168.178.11"]}, "tls": {"resumed": true, "version": 772, "cipher_suite": 4865, "proto": "http/1.1", "server_name": "pad.example.com"}}}
2023/06/24 14:45:22.809 DEBUG   http.handlers.reverse_proxy     connection closed{"upstream": "10.0.0.110:3030", "duration": 0.000513863, "request": {"remote_ip": "192.168.178.11", "remote_port": "56254", "proto": "HTTP/1.1", "method": "GET", "host": "pad.example.com:11443", "uri": "/api/socket/MCxiai", "headers": {"Connection": ["Upgrade"], "Origin": ["https://pad.example.com:11443"], "Sec-Websocket-Version": ["13"], "Accept-Language": ["de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"], "Sec-Websocket-Extensions": ["permessage-deflate; client_max_window_bits"], "Sec-Websocket-Key": ["FCOBxo+tJXz+iewTbsv4tQ=="], "X-Forwarded-Proto": ["https"], "Upgrade": ["websocket"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"], "Accept-Encoding": ["gzip, deflate, br"], "X-Forwarded-Host": ["pad.example.com:11443"], "Cache-Control": ["no-cache"], "Pragma": ["no-cache"], "X-Forwarded-For": ["192.168.178.11"]}, "tls": {"resumed": true, "version": 772, "cipher_suite": 4865, "proto": "http/1.1", "server_name": "pad.example.com"}}, "duration": 0.000393468}
2023/06/24 14:45:22.809 DEBUG   http.stdlib     http: response.WriteHeader on hijacked connection from github.com/caddyserver/caddy/v2/modules/caddyhttp.(*responseRecorder).WriteHeader (responsewriter.go:191)

I hope this helps - would be a pity if I couldnt use Coraza with apps that need websockets :) Thanks in advance

Fails GotestWAF block check

When I attempt to test Coraza with GoTestWAF, the WAF block check fails and I am unable to perform a successful test.

Caddyfile:

{
        order coraza_waf first
}

http://fqdn:80 {
        coraza_waf {
                include ./coraza/coraza.conf-recommended
                include ./coreruleset/crs-setup.conf.example
                include ./coreruleset/rules/*.conf
        }
        reverse_proxy http://172.16.157.140:80
}

Error running GotestWAF:
ERRO[0000] caught error in main function error="WAF was not detected. Please use the '--blockStatusCodes' or '--blockRegex' flags. Use '--help' for additional info. Baseline attack status code: 200"
If I run with flag --skipWAFBlockCheck the test fails so it's clear that GotestWAF needs to be told what actual blocking looks like

According to GotestWAF documentation, I can use either of these arguments to detect the WAF blocking

  --blockRegex string       Regex to detect a blocking page with the same HTTP response status code as a not blocked request
  --blockStatusCodes ints   HTTP status code that WAF uses while blocking requests (default [403])

Please help me determine how I can best go about this to get a successful POC

Some services return a blank 200 page with Coraza enabled

Some services that I use through the reverse proxy feature on Caddy break when I enable Coraza. One example that I've run into is with Overseerr

Reproduction steps

  • Set up Overseerr
  • Reverse proxy to Overseerr with Caddy
  • Verify site works without Coraza enabled
  • Enable Coraza with Caddyfile configuration

Expected behavior

Site loads properly and redirects to /login endpoint

Actual behavior

Site returns a blank 200 page. Developer tools say that no response was returned from the server.

No logs are generated to indicate why the request has failed.

Access logs say that a 307 response code was returned, but browsers report a 200 response code (tested with Firefox and Edge).

Configuration used

Caddyfile:

{
	order coraza_waf first
}

*.example.com {
	# Comment out this entire block to make Overseerr load properly
	coraza_waf {
		load_owasp_crs
		directives `
			Include @coraza.conf-recommended
			Include @crs-setup.conf.example
			Include @owasp_crs/*.conf
			SecRuleEngine On
		`
	}

	@overseerr host overseerr.example.com
	handle @overseerr {
		reverse_proxy overseerr:5055
	}
}

Logs

Caddy stdout:

{"level":"warn","ts":1686497529.0466342,"logger":"http.handlers.waf","msg":"failed to parse server name","tx_id":"__________","error":"failed to parse server name from authority \"overseerr.example.com\", address overseerr.example.com: missing port in address"}

Caddy access.log:

{
  "level": "info",
  "ts": 1686498117.092308,
  "logger": "http.log.access.log1",
  "msg": "handled request",
  "request": {
    "remote_ip": "[redacted]",
    "remote_port": "18232",
    "proto": "HTTP/2.0",
    "method": "GET",
    "host": "overseerr.example.com",
    "uri": "/login",
    "headers": {
      "User-Agent": [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
      ],
// --snip--
    },
    "tls": {
      "resumed": false,
      "version": 772,
      "cipher_suite": 4865,
      "proto": "h2",
      "server_name": "overseerr.example.com"
    }
  },
  "user_id": "",
  "duration": 0.029880206,
  "size": 0,
  "status": 307,
  "resp_headers": {
    "Date": [
      "Sun, 11 Jun 2023 15:41:57 GMT"
    ],
    "Server": [
      "Caddy"
    ],
    "Alt-Svc": [
      "h3=\":443\"; ma=2592000"
    ],
    "X-Powered-By": [
      "Express"
    ],
    "Location": [
      "/"
    ]
  }
}

500 instead of 401 on unauthenticated requests

If coraza-caddy is enabled, Caddy responds with 500 to unauthenticated requests on paths that require basicauth.
Here's my stripped-down Caddyfile.

{
    order coraza_waf first
    log {
        level DEBUG
        output stdout
    }
}
(coraza) {
    coraza_waf {
        directives `
            Include /etc/caddy/coreruleset/coraza.conf
            Include /etc/caddy/coreruleset/crs-setup.conf
            Include /etc/caddy/coreruleset/rules/*.conf
            SecRuleEngine On
            SecDebugLog /dev/stdout
            SecDebugLogLevel 1
            # This rule blocks HTTP3, which Caddy 2.6+ supports just fine
            SecRuleRemoveById 920430
        `
    }
}

foo.example.com {
    import coraza
    reverse_proxy foo:80
    basicauth * {
        # not the actual credentials, just an example for github
        foouser $2a$14$EUkRdDpsoURnFJtZz3KhLuIIAirpmYdMYyetZI0uDR08ok3ZWp3I.
    }
}

With coraza-caddy, 500:

[
    {
        "level": "debug",
        "ts": 1688392576.8852417,
        "logger": "tls.handshake",
        "msg": "matched certificate in cache",
        "remote_ip": "1.2.3.4",
        "remote_port": "53457",
        "subjects": [
            "foo.example.com"
        ],
        "managed": true,
        "expiration": 1696157323,
        "hash": "b51151ea9e3641ce334c3091d7c3d9b8b657490dfb4137dd7075a612da4c69de"
    },
    {
        "level": "error",
        "ts": 1688392576.910175,
        "logger": "http.log.error",
        "msg": "{id=1dz2mdqaf} caddyauth.Authentication.ServeHTTP (caddyauth.go:88): HTTP 401: not authenticated",
        "request": {
            "remote_ip": "1.2.3.4",
            "remote_port": "53457",
            "proto": "HTTP/2.0",
            "method": "GET",
            "host": "foo.example.com",
            "uri": "/",
            "headers": {
                "User-Agent": [
                    "curl/8.2.0-DEV"
                ],
                "Accept": [
                    "*/*"
                ]
            },
            "tls": {
                "resumed": false,
                "version": 772,
                "cipher_suite": 4865,
                "proto": "h2",
                "server_name": "foo.example.com"
            }
        },
        "duration": 0.001088573,
        "status": 500,
        "err_id": "YyXFfIEbBmHhiWYd",
        "err_trace": ""
    }
]

Without coraza-caddy: 401, the expected behaviour:

[
    {
        "level": "debug",
        "ts": 1688393963.6893258,
        "logger": "tls.handshake",
        "msg": "matched certificate in cache",
        "remote_ip": "1.2.3.4",
        "remote_port": "52382",
        "subjects": [
            "foo.example.com"
        ],
        "managed": true,
        "expiration": 1696157323,
        "hash": "b51151ea9e3641ce334c3091d7c3d9b8b657490dfb4137dd7075a612da4c69de"
    },
    {
        "level": "debug",
        "ts": 1688393963.7223728,
        "logger": "http.log.error",
        "msg": "not authenticated",
        "request": {
            "remote_ip": "1.2.3.4",
            "remote_port": "52382",
            "proto": "HTTP/2.0",
            "method": "GET",
            "host": "foo.example.com",
            "uri": "/",
            "headers": {
                "User-Agent": [
                    "curl/8.2.0-DEV"
                ],
                "Accept": [
                    "*/*"
                ]
            },
            "tls": {
                "resumed": false,
                "version": 772,
                "cipher_suite": 4865,
                "proto": "h2",
                "server_name": "foo.example.com"
            }
        },
        "duration": 0.00003665,
        "status": 401,
        "err_id": "5jxu9w957",
        "err_trace": "caddyauth.Authentication.ServeHTTP (caddyauth.go:88)"
    }
]

I asked for assistance on the OWASP Slack and Matteo helpfully suggested these debugging tricks:

  • Running it with SecRuleEngine DetectionOnly
  • Running it with SecDebugLogLevel 3
  • Running it not including the CRS

These are very helpful suggestions. I can report the issue still occurrs even without the Include statements and in DetectionOnly mode, and no additional logging was produced on level 3.

Config error cannot run caddy with coraza waf

I built the source code as specified

xcaddy build --with github.com/corazawaf/coraza-caddy

however then I get the following incorrect configuration error

root@caddy:~/tk# ./caddy adapt --config /etc/caddy/Caddyfile
{"logging":{"logs":{"default":{"exclude":["http.log.access.log0"]},"log0":{"writer":{"filename":"/home/caddy/xxxx.com.log","output":"file"},"include":["http.log.access.log0"]}}},"apps":{"http":{"servers":{"srv0":{"listen":[":443"],"routes":[{"match":[{"host":["xxxx.com"]}],"handle":[{"handler":"subroute","routes":[{"handle":[{"directives":"","handler":"waf","include":["/etc/caddy/waf/config.conf","/etc/caddy/waf/coreruleset/crs-setup.conf.example","/etc/caddy/waf/coreruleset/rules/*.conf"]},{"handler":"vars","root":"/home/caddy/web"}]},{"handle":[{"handler":"static_response","headers":{"Location":["{http.request.orig_uri.path}/"]},"status_code":308}],"match":[{"file":{"try_files":["{http.request.uri.path}/index.php"]},"not":[{"path":["*/"]}]}]},{"handle":[{"handler":"rewrite","uri":"{http.matchers.file.relative}"}],"match":[{"file":{"split_path":[".php"],"try_files":["{http.request.uri.path}","{http.request.uri.path}/index.php","index.php"]}}]},{"handle":[{"handler":"reverse_proxy","transport":{"protocol":"fastcgi","split_path":[".php"]},"upstreams":[{"dial":"127.0.0.1:1111"}]}],"match":[{"path":["*.php"]}]},{"handle":[{"handler":"file_server","hide":["/etc/caddy/Caddyfile"]}]}]}],"terminal":true}],"logs":{"logger_names":{"xxxx.com":"log0"}}}}}}}
2022/11/10 15:41:05.388 WARN    caddyfile       Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies    {"file": "/etc/caddy/Caddyfile", "line": 2}

here is my config file

{
        order coraza_waf first
}

xxxxxxxxx.com {
        coraza_waf {
                include /etc/caddy/waf/config.conf
                include /etc/caddy/waf/coreruleset/crs-setup.conf.example
                include /etc/caddy/waf/coreruleset/rules/*.conf
        }
        root * /home/caddy/web
        php_fastcgi 127.0.0.1:1111
        file_server
        log {
                output file /home/caddy/xxxx.com.log
        }
}

version info I'm using

root@caddy:~/tk# ./caddy version
v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=

High memory usage with CRS

First, just want to say that I'm really excited about this project - it's great to have an alternative to Apache or nginx with ModSecurity!

I've built a distroless image that uses Caddy, Coraza and the Core Rule Set, based on the directions from your various repos. It took a little while to get things working correctly, but it is now - you can see it here: https://github.com/abstractvector/c3-waf

However, one thing I've noticed is that the memory consumption of the container is incredibly high when the CRS rules are loaded - jumping from ~10MB without the rules to ~200MB with the rules. The addition of these two lines is all it takes:

include /coraza/coreruleset/crs-setup.conf
include /coraza/coreruleset/rules/*.conf

Once the container is loaded (e.g. using ab), the memory usage climbs significantly again. Stress testing the image without the CRS rules loaded will cause the memory usage to rise to ~20MB, but if I add the CRS rules in then memory consumption climbs to over 900MB!

This is easily reproduced using your Dockerfile (https://github.com/jptosso/coraza-waf-docker/blob/master/Dockerfile) and just adding in the relevant crs-setup.conf and rules/*.conf files as per the directions in your README.

Any idea what can be done to reduce the memory consumption? It doesn't appear to drop once the load has been removed.

Double break line when writing error logs

Errors are printed with double break line using console log format.

2023/07/14 12:49:16.929 ERROR   http.handlers.waf       [client "xxxxx"] Coraza: Access denied (phase 1).  [file ""] [line "8164"] [id "123"] [rev ""] [msg ""] [data ""] [severity "emergency"] [ver ""] [maturity "0"] [accuracy "0"] [hostname ""] [uri "/test5"] [unique_id "lplsWtaxdPAZBEMV"]

2023/07/14 12:54:49.311 ERROR   http.handlers.waf       [client "xxxx"] Coraza: Access denied (phase 1).  [file ""] [line "8164"] [id "123"] [rev ""] [msg ""] [data ""] [severity "emergency"] [ver ""] [maturity "0"] [accuracy "0"] [hostname ""] [uri "/test5"] [unique_id "ipPVdICWZdSKCKnq"]

2023/07/14 12:56:30.860 ERROR   http.handlers.waf       [client "xxxx"] Coraza: Access denied (phase 1).  [file ""] [line "8164"] [id "123"] [rev ""] [msg ""] [data ""] [severity "emergency"] [ver ""] [maturity "0"] [accuracy "0"] [hostname ""] [uri "/test5"] [unique_id "HUDskOlODMNnKEqb"]

log error how to troubleshoot

Hi,

I am successfully using te coraza waf. However I see this log lines, and I have no idea where to start as it not clear what is producing the warning. Any pointers would be helpful to reduce log messages. thanks!

Nov 18 16:49:48 caddy1 caddy[36093]: {"level":"error","ts":1668790188.225632,"logger":"http.handlers.waf","msg":"[client \"x.y.z.a\"] Coraza: Warning.  [file \"\"] [line \"0\"] [id \"1\"] [rev \"\"] [msg \"\"] [data \"\"] [severity \"emergency\"] [ver \"\"] [maturity \"0\"] [accuracy \"0\"] [hostname \"\"] [uri \"/api/ds/query\"] [unique_id \"wkx6KPvYdSLDJ64qAEv\"]\n"}

How to whitelist rule Or ID log?

we run waf test but there was a problem with the whitelist rule they couldn't find any instructions on how to do this, in the logging section I also don't find information about the log it only has the following

{"level":"error","ts":1668137651.9967813,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"1.1.1.1","remote_port":"60290","proto":"HTTP/1.1","method":"GET","host":"caddy.manhtuong.net","uri":"/test5","headers":{"Connection":["close"],"Accept-Encoding":["identity"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/605.1.15"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","server_name":"caddy.manhtuong.net"}},"user_id":"","duration":0.001161757,"size":0,"status":403,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}

{"level":"error","ts":1668137271.2399333,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"1.1.1.1","remote_port":"58887","proto":"HTTP/2.0","method":"GET","host":"caddy.manhtuong.net","uri":"/a=%3Cscript%3Ealert(1)%3C/script%3E","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"],"Accept-Language":["vi"],"Sec-Ch-Ua":["\"Google Chrome\";v=\"107\", \"Chromium\";v=\"107\", \"Not=A?Brand\";v=\"24\""],"Sec-Ch-Ua-Mobile":["?0"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"],"Sec-Fetch-Mode":["navigate"],"Sec-Fetch-Dest":["document"],"Accept-Encoding":["gzip, deflate, br"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"caddy.manhtuong.net"}},"user_id":"","duration":0.007092084,"size":0,"status":403,"resp_headers":{"Alt-Svc":["h3=\":443\"; ma=2592000"],"Server":["Caddy"]}}

we have a problem if the rules mistakenly blocked a valid application then other than removing the rule we can't whitelist. it has no information about the blocked rule so tracking is really a bad thing

Unable to load PCRE rules

Coraza fails to load PCRE rules even with the coraza-pcre module loaded: loading module 'waf': provision http.handlers.waf: failed to compile rule (error parsing regexp: invalid or unsupported Perl syntax

System info

$ go version
go version go1.17.11 linux/amd64
$ uname -a
Linux altair 5.18.0-2-amd64 #1 SMP PREEMPT_DYNAMIC Debian 5.18.5-1 (2022-06-16) x86_64 GNU/Linux

To reproduce

Build caddy with coraza-caddy plugin:

git clone https://github.com/corazawaf/coraza-caddy

# Uncomment coraza-pcre import
sed -i '/.*coraza-pcre/s/\/\/ //g' coraza-caddy/caddy/main.go

xcaddy build --with github.com/corazawaf/coraza-caddy=./coraza-caddy

# Download CRS
curl -sL https://raw.githubusercontent.com/corazawaf/coraza/v2/master/coraza.conf-recommended -O
curl -sL https://github.com/coreruleset/coreruleset/archive/refs/tags/v3.3.2.tar.gz -O
tar -xvzf v3.3.2.tar.gz && rm v3.3.2.tar.gz
mv coreruleset-3.3.2 coreruleset

Create example Caddyfile:

{
    order coraza_waf first
}

localhost {
    coraza_waf {
        directives `
            SecAction "id:1,deny,log"
            SecRule REQUEST_URI "/test5" "id:2, deny, log, phase:1"
            SecRule REQUEST_URI "/test6" "id:4, deny, log, phase:3"
        `
        include coraza.conf-recommended
        include coreruleset/crs-setup.conf.example
        include coreruleset/rules/*.conf
    }
    respond "test"
}

Start caddy:

$ sudo ./caddy run -config Caddyfile
2022/07/05 01:23:01.020 INFO    using provided configuration    {"config_file": "Caddyfile", "config_adapter": ""}
2022/07/05 01:23:01.021 WARN    Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies    {"adapter": "caddyfile", "file": "Caddyfile", "line": 2}
2022/07/05 01:23:01.022 INFO    admin   admin endpoint started  {"address": "tcp/localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]}
2022/07/05 01:23:01.022 INFO    http    server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {"server_name": "srv0", "https_port": 443}
2022/07/05 01:23:01.022 INFO    http    enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2022/07/05 01:23:01.022 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc00037df80"}
2022/07/05 01:23:01.044 INFO    tls.cache.maintenance   stopped background certificate maintenance      {"cache": "0xc00037df80"}
run: loading initial config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 0: loading handler modules: position 0: loading module 'waf': provision http.handlers.waf: failed to compile rule (error parsing regexp: invalid or unsupported Perl syntax: `(?<`): FILES_NAMES|FILES "@rx (?<!&(?:[aAoOuUyY]uml)|&(?:[aAeEiIoOuU]circ)|&(?:[eEiIoOuUyY]acute)|&(?:[aAeEiIoOuU]grave)|&(?:[cC]cedil)|&(?:[aAnNoO]tilde)|&(?:amp)|&(?:apos));|['\"=]" "id:920120,phase:2,block,t:none,t:urlDecodeUni,msg:'Attempted multipart/form-data bypass',logdata:'%{MATCHED_VAR}',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-protocol',tag:'paranoia-level/1',tag:'OWASP_CRS',tag:'capec/1000/210/272',ver:'OWASP_CRS/3.3.2',severity:'CRITICAL',setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

High RAM Consumption when activating the WAF on multiple sites

Hello,

I'm encountering a problem with this module, specifically, the RAM usage keeps rising consistently whenever I incorporate a new Caddyfile configuration (or when I activate the WAF on an existing config).

My main configuration looks like this one:

{ Caddy global options... }
import *.caddy

In each Caddyfile, I manage a distinct site. I have approximately 200 Caddyfiles in total. Prior to installing the module, the loaded configuration utilized merely 1 GB of memory. However, once the module is installed and the WAF directive is enabled like this:

        coraza_waf {
			include /waf/coraza/coraza.conf-recommended
			include /waf/coreruleset/crs-setup.conf.example
			include /waf/coreruleset/rules/*.conf
			include /var/sites_waf/specific_site_configuration.conf
        }

I observe an increment of nearly 200 MB of RAM per site. Upon restarting the Caddy server, the RAM usage amplifies further and appears to remain unreleased. This does not occur when I deactivate the module and the WAF directive.

Do you have any idea on what is happening?

Thank you,
Simone

Coraza-caddy overuse RAM

Linux host Debian 11 5.10.0-15-amd64 #1 SMP Debian 5.10.120-1 (2022-06-09) x86_64 GNU/Linux
go version go1.18.3 linux/amd64
Caddy is built as per https://github.com/corazawaf/coraza-caddy#build-caddy-with-coraza-waf
Loaded OWASP ModSecurity Core Rule Set (CRS) 3.3.2 https://github.com/coreruleset/coreruleset/tree/v3.3.2/rules
Next rules list:

       include /etc/caddy/inclusions/coraza.conf-recommended
       include /etc/caddy/inclusions/crs-setup.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-901-INITIALIZATION.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-910-IP-REPUTATION.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-912-DOS-PROTECTION.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-913-SCANNER-DETECTION.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-921-PROTOCOL-ATTACK.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf
       include /etc/caddy/inclusions/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf
       include /etc/caddy/inclusions/coreruleset/rules/RESPONSE-950-DATA-LEAKAGES.conf
       include /etc/caddy/inclusions/coreruleset/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
       include /etc/caddy/inclusions/coreruleset/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
       include /etc/caddy/inclusions/coreruleset/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
       include /etc/caddy/inclusions/coreruleset/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
       include /etc/caddy/inclusions/coreruleset/rules/RESPONSE-980-CORRELATION.conf

If to run penetration test such as Vega and Wapti to a website hosted behind Caddy then it start to overuse memory and consumes RAM/SWAP total 40GB within 20 min.

See screenshots:
image

image

failed to compile rule

sudo caddy validate
2022/12/09 01:13:17.893 INFO using adjacent Caddyfile
2022/12/09 01:13:17.894 WARN Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies {"adapter": "caddyfile", "file": "Caddyfile", "line": 11}
2022/12/09 01:13:17.895 WARN http server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server {"server_name": "srv6", "http_port": 80}
2022/12/09 01:13:17.895 INFO tls.cache.maintenance started background certificate maintenance {"cache": "0xc0002fd500"}
2022/12/09 01:13:17.913 INFO tls.cache.maintenance stopped background certificate maintenance {"cache": "0xc0002fd500"}
Error: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'waf': provision http.handlers.waf: failed to compile rule (unknown variable): &MULTIPART_PART_HEADERS:charset "!@eq 0" "id:922100,phase:2,block,t:none,msg:'Multipart content type global charset definition is not allowed by policy',logdata:'Matched Data: %{ARGS.charset}',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-multipart-header',tag:'OWASP_CRS',tag:'capec/1000/255/153',tag:'paranoia-level/1',ver:'OWASP_CRS/4.0.0-rc1',severity:'CRITICAL',chain"


sudo caddy version
v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=


Caddyfile
{
order coraza_waf first
}
:80 {
# Set this path to your site's directory.
root * /usr/share/nginx/www

# Enable the static file server.
file_server

# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080

# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000

}

:60000 {
coraza_waf {
directives SecAction "id:1,pass,log"
include /home/ubuntu18/coreruleset/coraza.conf-recommended
include /home/ubuntu18/coreruleset/crs-setup.conf.example
include /home/ubuntu18/coreruleset/rules/*.conf
}
reverse_proxy 192.168.0.36:60000
}


fetch rules via git clone https://github.com/coreruleset/coreruleset.git

After remove REQUEST-922-MULTIPART-ATTACK.conf, All is ok

Using TLS with this plugin

Hello! Thank you for your plugin! Very awesome.

Is it available to first tls encrypt traffic, than pass it to Coraza? Your examples folder contains example with no TLS encryption, so i wonder is it possible? Or should i accept incomming traffic in one scope, than pass it to another port with waf?

`SecAuditEngine RelevantOnly` won't log

Hello again, thank you very much for your answer in #20 (I tried to find a way into the code by myself with your help but without success this morning).

So my issue today is about logs again, which is my main task those days.

The context

I've installed as in the Readme, Caddy and coraza-waf and it works.
I am trying to collect the logs about coraza.

The Issue

Coraza does not log into my file specified with SecAuditLog unless I set SecAuditEngine to On which logs every single request where I want only relevant with relevant.

In addition, changing the SecAuditLogParts does not affect the logs.

My config

Some of my Caddyfile

http://example.com {
	coraza_waf {
		include coraza.conf-recommended
		include coreruleset/crs-setup.conf.example
		include coreruleset/rules/*.conf
	}
	reverse_proxy {
		to some_ip
		trusted_proxies private_ranges 127.0.0.1
	}
}

Some of coraza.conf-recommended

# -- Rule engine initialization ----------------------------------------------

# Enable Coraza, attaching it to every transaction. Use detection
# only to start with, because that minimises the chances of post-installation
# disruption.
#
# SecRuleEngine DetectionOnly
SecRuleEngine On

# -- Audit log configuration -------------------------------------------------

# Log the transactions that are marked by a rule, as well as those that
# trigger a server error (determined by a 5xx or 4xx, excluding 404,  
# level response status codes).
#
SecAuditEngine On
SecAuditLogRelevantStatus "^(?:(5|4)(0|1)[0-9])$"

# Log everything we know about a transaction.
SecAuditLogParts AZ

# Use a single file for logging. This is much easier to look at, but
# assumes that you will use the audit log only occasionally.
#
SecAuditLogType Serial
# SecAuditLogType concurrent 
# SecAuditLogStorageDir /var/log/caddy/
SecAuditLog /var/log/caddy/waf.log

I tried to play with SecRuleEngine too.

Some of coreruleset/crs-setup.conf.example

# Default: Anomaly Scoring mode, log to error log, log to ModSecurity audit log
# - By default, offending requests are blocked with an error 403 response.
# - To change the disruptive action, see RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example
#   and review section 'Changing the Disruptive Action for Anomaly Mode'.
# - In Apache, you can use ErrorDocument to show a friendly error page or
#   perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html
#
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"



SecAction \
 "id:900000,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:tx.blocking_paranoia_level=1"

Modifying the paranoia works and block at lvl2 my XSS attempt but doesn't affect logging with SecAuditEngine (but it affects logging about errors in caddy logs

Using the coraza.conf-recommended configutarion causes dangerous requests to show a warning instead of returning 403

I've followed the README, and noticed that when using the 3 include statements in README causes dangerous request to show a warning in caddy's logs, but the request itself is executed as normal, without being blocked.
when using just the include caddypath/coreruleset/rules/*.conf - evereything is blocked, and a warning shows

ModSecurity Core Rule Set is deployed without configuration! Please copy the crs-setup.conf.example template to crs-setup.conf, and include the crs-setup.conf file in your webserver configuration before including the CRS rules. See the INSTALL file in the CRS directory for detailed instructions

So I've included the crs-setup.conf and everything seems to work as expected, Is there something I'm missing, or perhaps the README should be updated?

Coraza not act with rule on allow or pass when using SecDefultAction deny (implicit deny)

Hello,

I am using Coraza with caddy and loading de CRS rules on my CaddyFile and the crs-setup.conf is configure with "SecDefaultAction phase:1,log,auditlog,pass" in this case when I create my own rules on the directives in the caddyfile and try to block, this working fine.

But if I try to change the default action for Deny on the crs-setup.conf by "SecDefaultAction phase:1,log,auditlog,deby,status:403" then when I try to make my own rules for permit access this not work, always block website.

This case works for someone ? I try to block any request and permit only the specifit uri (with the OWASP proteccion at lease)

File upload : files over 120 kB returns 500 error

Hi, I found out files over 120 kB cant be uploaded when coraza is enabled, and it is not about a CRS rule file because I disabled them.

create the file with : dd if=/dev/zero of=file.pdf bs=10K count=13

caddy configuration

	coraza_waf {
			directives `
				SecAction \
					"id:900000,\
					phase:1,\
					nolog,\
					pass,\
					t:none,\
					setvar:tx.blocking_paranoia_level=1"
				SecAction \
					"id:900001,\
					phase:1,\
					nolog,\
					pass,\
					t:none,\
					setvar:tx.detection_paranoia_level=1"
			`
		include coraza.conf
		include coreruleset/crs-setup.conf
	}

coraza.conf

I tried uping SecRequestBodyLimit and setting SecRequestBodyAccess but this has no effect

SecRuleEngine On

SecRequestBodyAccess Off

SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
     "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"

SecRule REQUEST_HEADERS:Content-Type "application/json" \
     "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"

SecRequestBodyLimit 131072000000

SecRule REQBODY_ERROR "!@eq 0" \
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"

SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:400, \
msg:'Multipart request body failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"

SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
    "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"

SecRule TX:/^COR_/ "!@streq 0" \
        "id:'200005',phase:2,t:none,deny,msg:'Coraza internal error flagged: %{MATCHED_VAR_NAME}'"

SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/coraza/tmp
SecDataDir /tmp/coraza/data
SecAuditEngine On
SecAuditLogType concurrent 
SecAuditLogStorageDir /var/log/caddy/
SecAuditLogRelevantStatus "^(?:(5|4)(0|1)[0-9])$"
SecArgumentSeparator &
SecCookieFormat 0
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"

SecAction \
"id:900220,\
 phase:1,\
 nolog,\
 pass,\
 t:none,\
 setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/x-amf| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json| |application/octet-stream| |application/csp-report| |application/xss-auditor-report| |text/plain| |application/x-www-form-urlencoded;| |multipart/form-data;| |multipart/related;| |text/xml;| |application/xml;| |application/soap+xml;| |application/x-amf;| |application/json;| |application/cloudevents+json;| |application/cloudevents-batch+json;| |application/octet-stream;| |application/csp-report;| |application/xss-auditor-report;| |text/plain|'"

SecCollectionTimeout 600

SecAction \
    "id:900990,\
    phase:1,\
    nolog,\
    pass,\
    t:none,\
    setvar:tx.crs_setup_version=400"

caddy logs

I get this error when triggering the 500 error (/tmp/coraza/tmp is SecTmpDir) :

http.log.error  open /tmp/coraza/tmp/body2809431227: no such file or directory  {"request": {"remote_ip": "::1", "remote_port": "46222", "proto": "HTTP/1.1", "method": "POST", "host": "[redacted]", "uri": "/fr/imce", "headers": {"Te": ["trailers"], "X-Forwarded-For": ["[redacted]"], "Content-Type": ["multipart/form-data; boundary=---------------------------755505775042860173259666447"], "Origin": ["https://www.bookbeo.com"], "Referer": ["[redacted]/imce"], "X-Forwarded-Proto": ["https"], "X-Requested-With": ["XMLHttpRequest"], "User-Agent": ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0"], "Cookie": [], "Sec-Fetch-Site": ["same-origin"], "X-Forwarded-Host": ["[redacted]"], "X-Request-Id": ["g5hzRLV8qFTs3jo9ZoxVB"], "Accept": ["application/json, text/javascript, */*; q=0.01"], "Sec-Fetch-Mode": ["cors"], "Accept-Language": ["fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3"], "Sec-Fetch-Dest": ["empty"], "Content-Length": ["133737"], "Accept-Encoding": ["gzip, deflate"]}}, "duration": 0.323760727}

Stability for usage in production

I am wondering if this is ready for real world usage. I know that a very hard question to answer of course, but maybe you have an option and more knowledge on this than me.

It’s not listed here: https://coraza.io/connectors/ so it’s also why I am asking if this is ready for devs to use it.

i use and appreciate Caddy and think an Application firewall for Caddy is a massive boost to the adoption and future of Caddy.

Thank you in advance ..

Requesting release of a new version

Please release a new version of this module. It currently uses https://github.com/corazawaf/coraza commit id, 8b909c7fc
This commit in that repo was released on January 17, Last release in this repo was on January 19.

This commit in corazawaf/coraza has a bug because of which it crashes on some inputs.

May 24 21:01:12 delbgp caddy[798842]: panic: runtime error: slice bounds out of range [177:0]
May 24 21:01:12 delbgp caddy[798842]: goroutine 52252 [running]:
May 24 21:01:12 delbgp caddy[798842]: github.com/corazawaf/coraza/v3/internal/corazawaf.(*bodyBufferReader).Read(0xc000f7c6f0, {0xc00044a000?, 0xa6?, 0x41786d?})
May 24 21:01:12 delbgp caddy[798842]:         github.com/corazawaf/coraza/[email protected]/internal/corazawaf/body_buffer.go:98 +0x139
May 24 21:01:12 delbgp caddy[798842]: io.discard.ReadFrom({}, {0x260ada0, 0xc000f7c6f0})
May 24 21:01:12 delbgp caddy[798842]:         io/io.go:651 +0x72
May 24 21:01:12 delbgp caddy[798842]: io.copyBuffer({0x26139a0, 0x36c5ae0}, {0x260ada0, 0xc000f7c6f0}, {0xc0008c0000, 0x8000, 0x8000})
May 24 21:01:12 delbgp caddy[798842]:         io/io.go:413 +0x14b
May 24 21:01:12 delbgp caddy[798842]: io.(*multiReader).writeToWithBuffer(0xc000c3e1f8, {0x26139a0, 0x36c5ae0}, {0xc0008c0000, 0x8000, 0x8000})
May 24 21:01:12 delbgp caddy[798842]:         io/multi.go:54 +0xe5
May 24 21:01:12 delbgp caddy[798842]: io.(*multiReader).WriteTo(0x1fa9120?, {0x26139a0, 0x36c5ae0})
May 24 21:01:12 delbgp caddy[798842]:         io/multi.go:45 +0x56
May 24 21:01:12 delbgp caddy[798842]: io.copyBuffer({0x26139a0, 0x36c5ae0}, {0x7fb28b212b38, 0xc0011151d0}, {0x0, 0x0, 0x0})
May 24 21:01:12 delbgp caddy[798842]:         io/io.go:409 +0x16e
May 24 21:01:12 delbgp caddy[798842]: io.Copy(...)
May 24 21:01:12 delbgp caddy[798842]:         io/io.go:386
May 24 21:01:12 delbgp caddy[798842]: net/http.(*transferWriter).doBodyCopy(0xc0007ee140, {0x26139a0?, 0x36c5ae0?}, {0x7fb28b212b38?, 0xc0011151d0?})
May 24 21:01:12 delbgp caddy[798842]:         net/http/transfer.go:412 +0x4d
May 24 21:01:12 delbgp caddy[798842]: net/http.(*transferWriter).writeBody(0xc0007ee140, {0x26094a0, 0xc00067de00})
May 24 21:01:12 delbgp caddy[798842]:         net/http/transfer.go:375 +0x428
May 24 21:01:12 delbgp caddy[798842]: net/http.(*Request).write(0xc001087a00, {0x26094a0, 0xc00067de00}, 0x0, 0x0, 0x0)
May 24 21:01:12 delbgp caddy[798842]:         net/http/request.go:705 +0xb46
May 24 21:01:12 delbgp caddy[798842]: net/http.(*persistConn).writeLoop(0xc0006399e0)
May 24 21:01:12 delbgp caddy[798842]:         net/http/transport.go:2413 +0x171
May 24 21:01:12 delbgp caddy[798842]: created by net/http.(*Transport).dialConn
May 24 21:01:12 delbgp caddy[798842]:         net/http/transport.go:1766 +0x173d
May 24 21:01:12 delbgp systemd[1]: caddy.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
May 24 21:01:12 delbgp systemd[1]: caddy.service: Failed with result 'exit-code'.
May 24 21:01:12 delbgp systemd[1]: caddy.service: Consumed 6.991s CPU time.

This read method in that commit and the most recent commit look almost the same. I tried running fuzzers on the new code and the old code for a few minutes and couldn't find a valid input that will break this code and I'll try running fuzzer overnight again.

For now, Please consider releasing a new version of this module which uses an updated version of corazawaf/coraza. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.