Skip to content

modsecurity + auth_request hang #163

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

Closed
chaoyun opened this issue Jul 31, 2019 · 20 comments
Closed

modsecurity + auth_request hang #163

chaoyun opened this issue Jul 31, 2019 · 20 comments
Assignees
Labels
no-issue-activity nostale The label to apply when an issue is exempt from being marked stale question

Comments

@chaoyun
Copy link

chaoyun commented Jul 31, 2019

hi, Experts:
I meet some issue why enable modSecurity plus with auth_request + http/2.

If a request with POST data, it will hang there. But "GET" method works well.

There's a similar issue discussed in the kubernetes/ingress-nginx#1932
Disable modSecurity, it can work. Disable auth_request, it can also work. Using http1.1 can work too. Only the combination of "modSecurity"+"auth_request"+http1.1 cannot work.
Do you have any test for this case?

@chaoyun
Copy link
Author

chaoyun commented Aug 1, 2019

@defanator Hi, I see you fixed this issue #131. But with my latest test, seems it doesn't work. In your testcase, I see you use http/2, right?

@defanator
Copy link
Collaborator

@chaoyun in connector tests we are using both HTTP/1 and HTTP/2 where applicable. I believe there were some TODO-marked tests specifically for HTTP/2, and auth_request can be one of those. I need to refresh my memory about that topic.

@chaoyun
Copy link
Author

chaoyun commented Aug 8, 2019

@defanator Thanks for the reply. Waiting for your update. I checked the log in the modSecurity, seems it parsed the request, and there's no further log in both modSecurity and nginx. I don't know where it hung.

@zimmerle
Copy link
Contributor

@chaoyun, @defanator

Is this still an issue?

@defanator
Copy link
Collaborator

@zimmerle last time I checked there was an issue with HTTP/2. I'll try to pick some time to refresh this one.

@zimmerle
Copy link
Contributor

Thank you @defanator. Warming up a release. Checking on what could be closed.

@dcherniv
Copy link

@defanator @zimmerle just got bit by this one too. Specifically kibana is completely broken with modsecurity + oauth proxy, which is a common combination people use

@github-actions
Copy link

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

@dcherniv
Copy link

/reopen

@victorhora victorhora added nostale The label to apply when an issue is exempt from being marked stale and removed stale labels Apr 7, 2020
@victorhora
Copy link
Contributor

The "nostale" tag has been set for this one and it's now reopened. We'll get to it when possible. Thank you.

@victorhora victorhora reopened this Apr 7, 2020
@PaulCharlton
Copy link

PaulCharlton commented Jun 27, 2020

see also:
kubernetes/ingress-nginx#5723
owasp-modsecurity/ModSecurity#2341

definitive workaround:
add use-http2: false to the Nginx listen block or k8s Nginx-ingress ConfigMap

At this point, we can write a unit test that sets conditions: (1) "POST + non-empty body", (2) side-car sub request Auth, (3) modsecurity enabled, (4) force HTTP2 + TLS session. iterate until the unit test works.

I imagine that since modsecurity is inspecting the request body, even when modsecurity SecRulesEngine Off, and that it is somehow interfering with the state of the HTTP2 protocol handler. I traced it down to a single byte in the payload, which is the blank line between the headers and the body. It appears to be consumed by modsecurity, but not consumed when modsecurity is off. For some reason as yet unknown to me, this impacts the sub-request to the Auth, but does not impact the upstream server request body.

@PaulCharlton
Copy link

@victorhora @zimmerle with the information above, this should be relatively easy to track down

@PaulCharlton
Copy link

PaulCharlton commented Jun 28, 2020

this code looks really suspicious, and there are no unit tests configured with http2.
the phrase r->main->count--; can be invoked twice and there is no explanation for why it is Nginx version dependent.

src/ngx_http_modsecurity_pre_access.c

        r->request_body_in_single_buf = 1;
        r->request_body_in_persistent_file = 1;

        rc = ngx_http_read_client_request_body(r,
            ngx_http_modsecurity_request_read);
        if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
#if (nginx_version < 1002006) ||                                             \
    (nginx_version >= 1003000 && nginx_version < 1003009)
            r->main->count--;
#endif

            return rc;
        }

and

void
ngx_http_modsecurity_request_read(ngx_http_request_t *r)
{
    ngx_http_modsecurity_ctx_t *ctx;

    ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);

#if defined(nginx_version) && nginx_version >= 8011
    r->main->count--;
#endif

    if (ctx->waiting_more_body)
    {
        ctx->waiting_more_body = 0;
        r->write_event_handler = ngx_http_core_run_phases;
        ngx_http_core_run_phases(r);
    }
}

the most important thing is that no internal NGINX state should be changed as a result of modsecurity reading the request body. It is possible that Nginx should be giving modules a copy of the request buffers rather than the original request buffers, however, this module should have some sanity checking that "Nginx_state_before_processing==nginx_state_after_processing"

@github-actions
Copy link

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

@mtorromeo
Copy link

mtorromeo commented Jan 11, 2021

This is still an issue. The nostale label does not seem to work...

/reopen

@mtorromeo
Copy link

I noticed that in tests/modsecurity-request-body-h2.t there are already 4 tests that are specifically for this exact issue but are contained in a TODO block.

I removed the TODO and after running the tests with different versions of nginx I found out that the tests are failing with the stable release 1.18.0 but are passing with mainline nginx 1.19.6

@mtorromeo
Copy link

I just finished bisecting the nginx repository to find the exact commit that made the tests pass and this is it: nginx/nginx@6c89d75

I am not sure if a workaround is possible.

@defanator
Copy link
Collaborator

@mtorromeo thanks for digging into this! I have marked those tests as TODO and was going to specify the exact version where the issue has been resolved. Hopefully to find some time this week for that.

@mtorromeo
Copy link

I was hoping to find an easy fix and it's a bit disappointing to find out that it's actually a bug of nginx itself and that such a critical issue was not even backported to stable but what can you do...

defanator added a commit that referenced this issue Jan 14, 2021
See the following issue for details:
#163
@defanator
Copy link
Collaborator

@mtorromeo adjusted TODO versioning here: 3f016fc

(there's another couple of passing TODOs related to alerts in error log; I'll handle those separately)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-issue-activity nostale The label to apply when an issue is exempt from being marked stale question
Projects
None yet
Development

No branches or pull requests

7 participants