fix: record real response status for IIS audit log F part - #3613
fix: record real response status for IIS audit log F part#3613A13501350 wants to merge 5 commits into
Conversation
The IIS connector never copied the HTTP response status into the request_rec, so r->status stayed 0 and the audit log rendered the F part as a bogus 'HTTP/1.1 500 Internal Server Error' (ap_get_status_line(0)) for every transaction. Set r->status and r->status_line from the raw HTTP_RESPONSE in OnSendResponse so the logging hook and relevant-status checks use the real response code.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hi @A13501350, thanks for the fix (and the report too) - could you add some tests to the CI to check this expected behavior? (Not just for this case, but I assume this is important in the future, so if anyone makes some changes, we should be sure the behavior is the same...) |
The IIS connector never copies the response status into the request_rec; r->status is only set in OnSendResponse. A request superseded by an internal redirect (e.g. the IIS default document rewrite of "/" to "/iisstart.htm") never reaches OnSendResponse, so its r->status stays 0 and the audit log F part would record a bogus HTTP/1.1 500 Internal Server Error (ap_get_status_line(0)). Skip audit logging for such transactions unless they were actually intercepted. A blocked request always reaches OnSendResponse with r->status set (403), so it is unaffected.
|
I can add tests for this. That said, the current workflow is mainly set up to verify that the build compiles and runs. It would be cleaner to test in a dedicated action. Regarding the SonarCloud Quality Gate failure, I'd prefer to keep the original code structure, so I am unable to refactor those lines to meet the maintainability rating. |
Feel free to add a test case, based on Linux tests. (But the regression tests there use Apache, so probably that won't be good to you. This part probably more useful for first time.) |
Replace the go-ftw cloud-mode run with file-based audit logging and a config-driven smoke suite. - iis/tests/ftw.yaml: go-ftw config. include selects a representative subset of rule families (913/920/930/941); testoverride.ignore lists tests that cannot pass on IIS/HTTP.SYS (behavior differences, not module faults). - iis/tests/crs-900005.conf: CRS regression-suite config (rule 900005), appended to crs-setup.conf before the rule files. - iis/tests/audit-logging.conf: file-based audit log + go-ftw marker. - iis/tests/web.config: IIS reverse proxy to the albedo backend. - workflow: download CRS, assemble config, deploy web.config, run go-ftw, upload the audit log as an artifact.
| @@ -0,0 +1,13 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <configuration> | |||
| <system.webServer> | |||
There was a problem hiding this comment.
web.config exists solely for the CI test environment and never serves real traffic, so I'd consider this ignorable.
2c6e8c3 to
166ed5e
Compare
|
|
For this specific case I've already added a test. Regarding a full regression suite, since IIS/HTTP.SYS behaves differently from Apache like you said, running the complete CRS suite is quite painful. I only cherry-pick a few tests in CI. |
There was a problem hiding this comment.
Like I said before, legacy code is usually not convenient to refactor.




Summary
Fixes the IIS connector so the audit log's F part records the real HTTP response status instead of a bogus
500 Internal Server Error.Problem
In the IIS connector,
r->statuswas never populated from the actual HTTP response.request_recisapr_pcalloc'd, sor->statusstayed0. When the logging hook builds the F part it callsap_get_status_line(r->status); forr->status == 0the standaloneap_index_of_response()maps any value< 100toLEVEL_500, so every transaction loggedHTTP/1.1 500 Internal Server Errorregardless of the true response code.There was a second, related source of bogus
500records: the IIS default-document rewrite (e.g.GET /internally redirected to/iisstart.htm) supersedes the original request before it ever reachesOnSendResponse, so itsr->statusstays0andhook_log_transactionwrote a phantom500record for it.Fix
CMyHttpModule::OnSendResponse(iis/mymodule.cpp), transfer the raw response status intor->status(and buildr->status_linefrom the reason phrase) before the rest of the response handling:hook_log_transaction(apache2/mod_security2.c, underVERSION_IIS), skip audit logging for transactions that never received a response status and were not intercepted. In the IIS connectorr->statusis only ever set byOnSendResponse, sor->status == 0 && !msr->was_intercepteduniquely identifies requests superseded by an internal redirect:A blocked request always reaches
OnSendResponsewithr->statusset (e.g.403), so intercepted transactions are unaffected.Verification
Verified against a local IIS default site with OWASP CRS (and in the module's Windows CI, which enables the audit log and asserts the F-part status lines):
GET /now logsHTTP/1.1 200 OK(single record; the phantom500records for the internal redirect are gone)SQLi/XSS) logsHTTP/1.1 403 ModSecurity ActionCloses #3612