DEF CON CTF Qualifier 2018 - Easy Pisy
問題文
There, I've said it… http://5a7f02d0.quals2018.oooverflow.io Files: samples.tgz
writeup
sign.phpとexecute.phpの2種類のphpがある。
phpのソースコードはlinkより参照可能。
sign.php
アップロードしたPDF内に書かれた文字列が"ECHO "で始まる場合に、
PDFと秘密鍵をopenssl_sign関数に渡して署名を生成する。
"EXECUTE "で始まる場合は、Go awayと怒られる。execute.php
アップロードしたPDF、画面入力した署名文字列および公開鍵をopenssl_verify関数に渡して照合する。
照合OKの場合、アップロードしたPDF内に書かれた文字列が"ECHO "で始まる場合に、文字列を出力。
"EXECUTE "で始まる場合に、文字列のコマンドを実行。
<?php include 'common.php'; if ($_SERVER['REQUEST_METHOD'] === 'GET') { print highlight_string(file_get_contents("sign.php"), TRUE); exit(0); } $keys = get_keys(); $privkey = $keys[0]; $pubkey = $keys[1]; if ($privkey === FALSE || $pubkey === FALSE) { die("Could not load keys. Contact admin.<br/>"); } $file_info = $_FILES['userfile']; check_uploaded_file($file_info); $text = pdf_to_text($file_info['tmp_name']); print "Extracted text: \"$text\"<br/>"; $execute_query = "EXECUTE "; $echo_query = "ECHO "; if (substr($text, 0, strlen($execute_query)) === $execute_query) { print "I don't sign EXECUTE commands. Go away.<br/>"; } else if (substr($text, 0, strlen($echo_query)) === $echo_query) { print "I'm OK with ECHO commands. Here is the signature: <br/>"; $data = file_get_contents($file_info['tmp_name']); openssl_sign($data, $signature, $privkey); print bin2hex($signature); } else { print "I can't recognize the command type. Go away.<br/>"; }
<?php include 'common.php'; if ($_SERVER['REQUEST_METHOD'] === 'GET') { print highlight_string(file_get_contents("execute.php"), TRUE); exit(0); } $keys = get_keys(); $privkey = $keys[0]; $pubkey = $keys[1]; $file_info = $_FILES['userfile']; check_uploaded_file($file_info); $data = file_get_contents($file_info['tmp_name']); $signature = hex2bin($_POST['signature']); if (openssl_verify($data, $signature, $pubkey)) { print 'Signature is OK.<br/>'; } else { die('Bad signature.'); } $text = pdf_to_text($file_info['tmp_name']); print "Text: \"$text\"<br/>"; $execute_query = "EXECUTE "; $echo_query = "ECHO "; if (substr($text, 0, strlen($execute_query)) === $execute_query) { $payload = substr($text, strlen($execute_query)); print "About to execute: \"$payload\".<br/>"; $out = shell_exec($payload); print "Output: $out"; } else if (substr($text, 0, strlen($echo_query)) === $echo_query) { $payload = substr($text, strlen($echo_query)); print "About to echo: \"$payload\".<br/>"; echo $payload; } else { print "I can't recognize the command type. Go away.<br/>"; } ?>
添付されていたsampleのPDFにlsコマンドを実行するPDFと署名があるので、アップロードをかけてみる。
Signature is OK. Executing 'convert -depth 8 /tmp/phprLCQq1.pdf /tmp/phprLCQq1.ppm' Executing 'ocrad /tmp/phprLCQq1.ppm' Text: "EXECUTE ls" About to execute: "ls". Output: common.php execute.php flag index.nginx-debian.html index.php private_key.pem public_key.pem sign.php
flagファイルがある。これをcatできれば勝ち。 ただ、秘密鍵も公開鍵も取得できない。
openssl_sign関数のI/Fを確認。
PHP: openssl_sign - Manual
第4引数を指定しないと、OPENSSL_ALGO_SHA1となるようだ。
SHA1衝突が使えそうだ。
github.com
このスクリプトで、任意の2つの画像からSHA1が同じファイルを生成できる。
以下の文字列を書いた画像を作成する。
- ECHO cat flag
- EXECUTE cat flag
スクリプト実行すると、echo-collision.pdfとexecute-collision.pdfができた。
ctfuser@kali:sha1-collider-master$ python collider.py echo.jpg execute.jpg Image size: (380, 100) Successfully Generated Collision PDF !!!
ctfuser@kali:sha1-collider-master$ sha1sum echo-collision.pdf 35b03ecc67af9e8032f9c85e4ed10e0421b2a512 echo-collision.pdf ctfuser@kali:sha1-collider-master$ sha1sum execute-collision.pdf 35b03ecc67af9e8032f9c85e4ed10e0421b2a512 execute-collision.pdf
echo-collision.pdfをsign.phpにアップロードする。
Executing 'convert -depth 8 /tmp/php3Qt02x.pdf /tmp/php3Qt02x.ppm' Executing 'ocrad /tmp/php3Qt02x.ppm' Extracted text: "ECHO cat flag" I'm OK with ECHO commands. Here is the signature: 2a33067ffc44d04293adde3d16e7f1b7c813c808576e224406b5e648232f90d79c33fea1a9888140c5c8c7f9ccf1b5d87fcf09df8ff48b20bc7c6cb91667885075bbaac3d20594ef3d357e1ee9e1ede9f00809d91bbf6961e80b2ef890f581c14e815a1b8cd0b56c50afb87f4422b1a029bbbbc9636c055bcf6ae018c1bddb053bf89e779290973451cb7333e019a1ee344d1ebf2d5c6a30ea19ea7db0982b71f980eecc36dbb813eed1874272ac4eebb754b78dd364b10d4b3ea46836d86d870092023f6b430e6a3531317f5c09d5f591daaf6197942cc2d8c0a428081b455902d0028b7a203cd627b9e7209ed9e3a81c1bc1a2cbaf3ae1140a527c56429936
execute-collision.pdfをexecute.phpにアップロードする。署名文字列は上記を使用。
Signature is OK. Executing 'convert -depth 8 /tmp/phpbZ3uXB.pdf /tmp/phpbZ3uXB.ppm' Executing 'ocrad /tmp/phpbZ3uXB.ppm' Text: "EXECUTE cat flag" About to execute: "cat flag". Output: OOO{phP_4lw4y5_d3l1v3r5_3h7_b35T_fl4g5}