Hi!

According to the documentation

  req.cook_cnt([<name>]) : integer
  Returns an integer value representing the number of occurrences of the cookie
  <name> in the request, or all cookies if <name> is not specified.

it should be possible to do something like this to reject a request if it 
contains more than <n> cookies total. I do not know the cookie names in 
advance. I am trying to reject malicious requests with hundreds or thousands of 
cookies, trying to exhaust memory in my backend servers. Tomcat has a maximum 
number of cookies per request setting, but I’d like to reject these before they 
even get to the backends.

I thought this would work (for n=2):

        frontend fe-test
                bind 0.0.0.0:8070
                http-request deny deny_status 400 if { req.cook_cnt() gt 2 }
                http-request auth realm tomcat
                default_backend be-test


However, it does not work. The count is always 0, hence the ACL always passes 
and I get a 401 response from the next ACL in line.

root@tomcat:~# curl -v -b 'C1=v1; C1=v2; C1=v3' tomcat:8070
* Rebuilt URL to: tomcat:8070/
* Hostname was NOT found in DNS cache
*   Trying 127.0.1.1...
* Connected to tomcat (127.0.1.1) port 8070 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: tomcat:8070
> Accept: */*
> Cookie: C1=v1; C1=v2; C1=v3
>
* HTTP 1.0, assume close after body
< HTTP/1.0 401 Unauthorized
< Cache-Control: no-cache
< Connection: close
< Content-Type: text/html
< WWW-Authenticate: Basic realm="tomcat"
<
<html><body><h1>401 Unauthorized</h1>
You need a valid user and password to access this content.
</body></html>
* Closing connection 0


When I change the ACL to include a cookie name, it works:

        http-request deny deny_status 400 if { req.cook_cnt("C1") gt 2 }

root@tomcat:~# curl -v -b 'C1=v1; C1=v2; C1=v3' tomcat:8070
* Rebuilt URL to: tomcat:8070/
* Hostname was NOT found in DNS cache
*   Trying 127.0.1.1...
* Connected to tomcat (127.0.1.1) port 8070 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: tomcat:8070
> Accept: */*
> Cookie: C1=v1; C1=v2; C1=v3
>
* HTTP 1.0, assume close after body
< HTTP/1.0 400 Bad request
< Cache-Control: no-cache
< Connection: close
< Content-Type: text/html
<
<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>
* Closing connection 0



I tried to figure out what the code does, to see if I am doing something wrong 
and found this in proto_http.c:

------------------------------------------------------------------------------
/* Iterate over all cookies present in a request to count how many occurrences
 * match the name in args and args->data.str.len. If <multi> is non-null, then
 * multiple cookies may be parsed on the same line. The returned sample is of
 * type UINT. Accepts exactly 1 argument of type string.
 */
static int
smp_fetch_cookie_cnt(const struct arg *args, struct sample *smp, const char 
*kw, void *private)
{
        struct http_txn *txn;
        struct hdr_idx *idx;
        struct hdr_ctx ctx;
        const struct http_msg *msg;
        const char *hdr_name;
        int hdr_name_len;
        int cnt;
        char *val_beg, *val_end;
        char *sol;

        if (!args || args->type != ARGT_STR)
                return 0;
------------------------------------------------------------------------------

So without being very C-savvy, this appears to exit early when there is no 
parameter of type string passed in.

I hope someone can shed some light on this. :)

Thanks in advance,
Daniel


-- 
Daniel Schneller
Principal Cloud Engineer
 
CenterDevice GmbH                  | Hochstraße 11
                                   | 42697 Solingen
tel: +49 1754155711                | Deutschland
daniel.schnel...@centerdevice.de   | www.centerdevice.de

Geschäftsführung: Dr. Patrick Peschlow, Dr. Lukas Pustina,
Michael Rosbach, Handelsregister-Nr.: HRB 18655,
HR-Gericht: Bonn, USt-IdNr.: DE-815299431



Reply via email to