読者です 読者をやめる 読者になる 読者になる

/home/cympfh/

数式を $$ で囲んで書いてますが面倒くさいので、いちいち、はてな書式にしたりしません

SECCON 2015 - Web 100

プロコン

SECCON 2015 - Web 100

URL http://entryform.pwn.seccon.jp/register.cgi だけが渡される. メールと名前だけの入力欄があるフォーム. http://entryform.pwn.seccon.jp/ にアクセスすると、 /SECRETS register.cgi_bak の存在が確認できて、 特に register.cgi_bak では register.cgiソースコードらしきものがテキストとして読める.

中を見ると Perl で、 大事そうなとこだけ引用すると、

if($q->param("mail") ne '' && $q->param("name") ne '') {
  open(SH, "|/usr/sbin/sendmail -bm '".$q->param("mail")."'");
  print SH "From: keigo.yamazaki\@seccon.jp\nTo: ".$q->param("mail")."\nSubject: from SECCON Entry Form\n\nWe received your entry.\n";
  close(SH);

Perl 知らないけどたぶん、 "/usr/sbin/sendmail -bm '".$q->param("mail")."'" という文字列を bash に投げるのだと思われる. というわけで、mail に ' ; echo Hi ; ' みたいな文字列を渡すことで OSコマンドインジェクションができる.

あと、

  open(LOG, ">>log"); ### <-- FLAG HERE ###
  flock(LOG, 2);

とあるので、作業ディレクトリ直下の log というファイルを覗いてみれば良いらしい.

肝心の sendmail が正しく動いてなかったり、 ファイルを新しく作ることが許可されてなかったりするので、 直接ファイルの中身を我々に見る手立てが無い. というわけでブラインドする.

tailed さんが自動化スクリプトを書いてくれたのでそれを使った. 賢いことに、 n文字目が何であるか? の命題 (真なら即座に結果が返って来て、さもなくば sleep 10 する) と、その逆の命題を同時に投げ、 先に返って来た命題が正しいと判定することでさっさとできる.

base64 に変換してからその判定に掛けるように変更して、ls の結果がわかるようになる

chars.each {|c|
  check("test $(ls -a . | base64 -w0 | cut -b #{i}) = #{c}")
}

で、 SECRETS/backdoor123.php なるファイルの存在を確認した. ブラウザでこれにアクセスして、エスパーして cat ../log したらできた (直接さっきのスクリプトで cat してもよかったのでは).