Hi list, I'm playing with SPOE and modsecurity contrib from HAProxy 1.8.9. I've
a couple of doubts and issues that I'll describe just below my config and some
loggings:
===== haproxy.conf
listen my-front
log 127.0.0.1:514 format rfc5424 local0
timeout client 5s
timeout connect 5s
timeout server 5s
mode http
bind :8080
log-format "The txn.modsec.code is: %[var(txn.modsec.code)]"
filter spoe engine modsecurity config /tmp/haproxy/spoe-modsecurity.conf
tcp-request content reject if { var(txn.modsec.code) -m int gt 0 }
server local 192.168.95.102:8000
backend spoe-modsecurity
mode tcp
timeout connect 5s
timeout server 3m
server iprep1 127.0.0.1:12345
-----
===== spoe-modsecurity.conf
[modsecurity]
spoe-agent modsecurity-agent
messages check-request
option var-prefix modsec
timeout hello 100ms
timeout idle 30s
timeout processing 1s
use-backend spoe-modsecurity
spoe-message check-request
args unique-id method path query req.ver req.hdrs_bin req.body_size req.body
event on-frontend-http-request
-----
modsecurity SPOA is logging whenever I make a request to HAProxy so apparently
it's working as expected:
=====log 1 -- curl -I localhost:8080?ref=abc
1526747591.637257 [01] Process SPOE Message 'check-request'
1526747591.638333 [01] Encode Agent ACK frame
1526747591.638867 [01] STREAM-ID=0 - FRAME-ID=1
1526747591.638887 [01] Add action : set variable code=4294967195
-----
=====log 2 -- curl -I 127.0.0.1:8080?ref=abc
1526741757.670146 [01] Process SPOE Message 'check-request'
1526741757.671956 [00] [client 127.0.0.1] ModSecurity: Warning. Pattern match
"^[\\d.:]+$" at REQUEST_HEADERS:Host. [file
"/owasp-modsecurity-crs-3.0.2/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"]
[line "810"] [id "920350"] [rev "2"] [msg "Host header is a numeric IP
address"] [data "127.0.0.1:8080"] [severity "WARNING"] [ver "OWASP_CRS/3.0.0"]
[maturity "9"] [accuracy "9"] [tag "application-multi"] [tag "language-multi"]
[tag "platform-multi"] [tag "attack-protocol"] [tag
"OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag
"OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [hostname "8ae61a5f0c2e"] [uri
"http://127.0.0.1:8080/"] [unique_id ""]
1526741757.672306 [01] Encode Agent ACK frame
1526741757.672333 [01] STREAM-ID=12 - FRAME-ID=1
1526741757.672351 [01] Add action : set variable code=4294967195
-----
=====log 3 -- curl -I 127.0.0.1:8080?ref=/../etc/passwd
1526741728.786700 [00] [client 127.0.0.1] ModSecurity: Warning. Matched phrase
"etc/passwd" at ARGS:ref. [file
"/owasp-modsecurity-crs-3.0.2/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"]
[line "448"] [id "932160"] [rev "1"] [msg "Remote Command Execution: Unix Shell
Code Found"] [data "Matched Data: etc/passwd found within ARGS:ref:
/etc/passwd"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"]
[accuracy "8"] [tag "application-multi"] [tag "language-shell"] [tag
"platform-unix"] [tag "attack-rce"] [tag
"OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION"] [tag "WASCTC/WASC-31"] [tag
"OWASP_TOP_10/A1"] [tag "PCI/6.5.2"] [hostname "8ae61a5f0c2e"] [uri
"http://127.0.0.1:8080/"] [unique_id ""]
...
1526741728.787814 [01] Add action : set variable code=4294967195
-----
Running modsecurity with: -d -n 1 -f /tmp/haproxy/modsec.conf
My environment is a `haproxy:alpine` container with all the stuff needed to
compile both modsecurity and it's SPOA contrib. The doc used was
`haproxy-1.8.9/contrib/modsecurity/README`.
Now a couple of doubts:
* If I `curl -v 127.0.0.1:12345` I can see a connection being opened on
modsecurity and `curl` waits for something it could understand. If I ctrl+C
`curl`, modsecurity starts an endless loop and use almost 100% of one CPU. I'm
aware modsecurity SPOA speaks SPOP instead of HTTP, but perhaps something could
be improved since this could also happen eg on a network failure.
* The `set variable code=` on logs has always the same value `4294967195`
despite what modsecurity found.
* A `log-format "%[var(txn.modsec.code)]"` logs always the same value `-101`
despite what modsecurity found.
* Perhaps a specific HAProxy doubt here: `tcp-request content reject` never
rejects a request even changing `gt` to `lt` or `eq`. Changing the acl to
`!{...}` the connection is always rejected despite of the operator.
~jm