Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange behaviour if modsecurity off|on set on server and location levels. #292

Open
remort opened this issue Nov 25, 2022 · 2 comments
Open

Comments

@remort
Copy link

remort commented Nov 25, 2022

Let's look the example nginx config:

server {
    modsecurity on;
    error_log /var/log/nginx/error.log info;

    location /a {
        error_log /var/log/nginx/a.log info;
        modsecurity on;
        include lua_code_with_proxy_pass_to_python_web_server;
        proxy_pass 1.0.0.1;
    }

    location /b {
        error_log /var/log/nginx/b.log info;
        modsecurity off;
        include lua_code_with_proxy_pass_to_python_web_server;
        proxy_pass 1.0.0.1;
    }

   location /send-to-python-server {
       proxy_pass 1.0.0.2:8080;
   }
}

Issue is reproducible only when modsecurity is On on the server block and Off on one of the locations inside the server block.

Location /a works fine, as expected:

  • If I send malicious request on /a - modsec blocks request. Writes an event to modsec_audit log and a.log (the log-file set to location modsec triggered in). Client gets 403 response from nginx/modsec. Expected behavior.
  • If I send legitimate request on /a - It goes through modsec, no events are logged, no blocks are performed and request goes through lua_code, then goes to python service, then goes to proxy_pass and client receives the html response from the website. This is an expected behavior.

Location /b behavior seems to be broken in case of malicious request:

  • If I send malicious request on /b - modsec blocks request on the server level. No logs in modsec_audit and b.log but in server-level error.log (the server-level log file since modsec is being triggered on server level, not on the location level). Request is not being blocked since modsecurity is disabled for this certain location. BUT, handling of the request according to location statements stops here. Request goes to proxy pass, client receives HTML page of the website. I expect request to be handled by lua code and sent to python web-server. Request doesn't go lua code at all. In other words request handling by location code is being interrupted on server-level modsecurity, then it goes to proxy_pass. All intermediary location code is skipped. It doesn't happen if no modsecurity On set on server-level, since no hierarhical modsecurity structure is presented.
  • If I send legitimate request on /b - It goes through modsec, no events are logged, no blocks are performed and request goes through lua_code, then goes to python service, then to proxy_pass and client receives the html response from the website. Exactly as with /a location. Expected behavior.

Lua code in lua_code_with_proxy_pass_to_python_web_server is somewhat like:

location / {
  rewrite_by_lua_block {
    local python_server_res = ngx.location.capture(
          "/send-to-python-server",
          { method = ngx.HTTP_POST, always_forward_body = true }
    )
    ngx.var.result = python_server_res.header["Result"]
    if ngx.var.result then
        ngx.exit(ngx.HTTP_FORBIDDEN)
    else
        ngx.exit(ngx.HTTP_OK)
    end
  }
}

Yes: location / inside locations /a and /b. It works fine. This code is not reachable if modsecurity is on on the server block and off on the location block in case of malicious request.

So, as for me, during the buggy case, modsecurirty triggers on server level. Writes an event to server-level log file. Affects end of request handling somehow. Doesn't block the request since modsec is off on the corresponding location, then request goes to proxy_pass of the location. No intermediary lua code is being executed. Some strange hierarchical logic in modsec seems to fire up here. I need the request being send furtherto python service to block it there, which doesn't happen. Changing rewrite_by_lua_block to content_by_lua_block doesn't matter.

If we have no modsecurity directive on server block (or modsecurity off) - any request (legitimate or malicious) is being handled by lua code with any state of modsecurity directive on the location (either on or off) on any location. Everything works as expected.

@martinhsv
Copy link
Contributor

Hello @remort ,

Thanks for the detailed report.

I seem to recall an earlier report of some inheritance issues between blocks, that may have been resolved by my predecessor in an experimental branch. I'll have a look and see if I can find it.

@remort
Copy link
Author

remort commented Dec 20, 2022

Hello, @martinhsv. Any updates on the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants