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