ライブCTF

2019-11-24 東京大学駒場祭 TSG出展企画「TSG LIVE! 4」

気軽にコメントしてね♫ 

@hakatashi

Hidden Page

ジャンル: Reversing

難易度: easy (100pts)

作問者: @hakatashi

「隠しページ」を探す問題

実は、通常の操作をするだけではたどり着けないページ
「フラグ」が記されている

→ プログラムの中身を解析して「フラグ」の場所を探す

リバースエンジニアリング

Webの「リバースエンジニアリング」は
通常不可能

クライアント

サーバー

プログラムはサーバーにあるので
入手不可能。解析もできない

プログラム実行

実行結果を返す

返されたデータを表示

しかし、この問題では
SPAという技術が用いられている

クライアント

サーバー

手元でプログラムが実行される
→リバースエンジニアリング可能!

プログラムを返す

プログラム実行

何も実行しない

中身を見てみる

  • SPAは便利だけどプログラムがユーザーにバレる
  • 通常は問題にはならないが、
    URLなどに隠したいデータがある場合には不向き
  • ちゃんと理解して使おう

Is the order a flag?

ジャンル: Web

難易度: easy (100pts)

作問者: @hakatashi

「行えない操作」の検証ロジック

クライアント

サーバー

「残高が足りない」などにより
「行えない操作」は、まずクライアントで検証される

データ検証

OKならサーバーに問い合わせ

操作を実行

「行えない操作」の検証ロジック

悪いクライアント

サーバー

クライアントでの検証だけでは不十分。

悪いクライアントによりハックすることができる

データ検証をスキップ

NGだけどサーバーに問い合わせ

操作を実行

デモ

適切な検証ロジック

クライアント

サーバー

悪意あるユーザーからのリクエストを
ブロックするには、操作を二重に検証する必要がある

データ検証

OKならサーバーに問い合わせ

操作を実行

データ検証

OKなら

  • サーバーでのバリデーション不備は、
    あまりに地味なのでCTFではほぼ出題されないが
    「現実に最も発生しやすい脆弱性」のひとつ
  • 初歩的な話なので意識して実装をしよう

Stegano Voltex

ジャンル: Stego

難易度: medium (200pts)

作問者: @hakatashi

音声ファイルが与えられる

使用楽曲: “One Day” by Tune Down!, licensed under CC BY 3.0 - https://soundcloud.com/electronicotaku/one-day

某音ゲーを
題材にした (?)
問題

ぶっちゃけゲームは
あまり関係ない

余談ですが、最近TSG内で
音ゲー界隈が盛り上がってる

Slackの#sig-rhythm-gameチャンネルで
わいわいしています

怪しいのはこのGateエフェクトの部分

なんか聞き心地悪い気がしませんか?

プツプツの長さに長いのと短いのがある

モールス信号

エフェクトがかかるのは4回。
それぞれをモールス信号として読むと

-    ・・・    --・    -・-・    -    ・・-・    -・--・
---    -・    ・-・・    -・--    -・・・・-    ・・-・
---    ・-・    -・・・・-    --・    ---    ・-・    ・・
・-・・    ・-・・    ・-    --・・    -・--・-

となる。

復号すると

TSGCTF(ONLY-FOR-GORILLAZ)

Furuikeya

ジャンル: Misc

難易度: medium (200pts)

作問者: @bitmath

SlackのChatBotとして
問題が与えられる

const {RTMClient, WebClient} = require('@slack/client');
const rtm = new RTMClient(process.env.SLACK_TOKEN);
const slack = new WebClient(process.env.SLACK_TOKEN);
const postFlag = require('./postFlag');

const pond = {
    'その辺で売ってる普通の斧': (channel) => {slack.chat.postMessage({channel, text:'普通の斧がありましたよ!'})},
    'ギラギラと輝く白銀色の斧': (channel) => {slack.chat.postMessage({channel, text:'銀の斧がありましたよ!'})},
    'ピカピカに光る黄金色の斧': (channel) => {slack.chat.postMessage({channel, text:'金の斧がありましたよ!'})},
    'f': (channel) => {postFlag(slack, {channel})},
}

rtm.on('message', async (message) => {
    if (!message.channel.startsWith('D')) {
        // not available in public channels
        return;
    }
    const match = message.text.match(/^(?<obj>.+)が池に落ちちゃった$/);
    if (match) {
        await slack.chat.postMessage({channel: message.channel, text:':statue_of_liberty:「あらあら,かわいそうに。わたしが探してあげましょう。」'});
        for (kind of ['その辺で売ってる普通の', 'ギラギラと輝く白銀色の', 'ピカピカに光る黄金色の']) {
            const text = [
                ':statue_of_liberty:「どのようなものかわからないけれど,試しに',
                kind,
                match.groups.obj,
                'を探してみますわ。どこかにあればいいのだけれど。」'
            ];
            const reply = await slack.chat.postMessage({channel: message.channel, text:text.join('')});

            const obj = reply.message.text.slice(text[0].length, -text[3].length);
            if (pond[obj]) {
                pond[obj](message.channel);
            } else {
                slack.chat.postMessage({channel: message.channel, text:':statue_of_liberty:「見つからなかったわ……ごめんなさい。」'});
            }
        }
    }
});

rtm.start();

「f」を探させられると
フラグが手に入る

とても長い文を投げた時の
Slack API の仕様を利用します

通常、Slackでは非常に長い文章を投げることができない

しかし、APIから投稿すると、自動で短い文章に
分割されて投稿される → 文章としては別のものに

KillKirby4Free

ジャンル: Pwn

難易度: hard (300pts)

作問者: @smallkirby

Anti-Quantum

ジャンル: Crypto

難易度: hard (300pts)

作問者: @hakatashi

最近

  • 量子コンピューターがどうとかで
    RSA暗号が話題ですね
  • RSA暗号は現在実用的に用いられている
    暗号の中では最も基礎的なもの
  • 破られた時のダメージもでかい
  • この問題もそんな「RSAを破る」趣旨の
    問題です

priv.json.encを
開いてみましょう

暗号化後なのに怪しいビットパターンが

AES暗号の不適切な利用が原因

  • AESのECBモードは、同じ平文を
    同じ暗号文に変換してしまう
  • つまり、もとのpriv.jsonにも同じような
    繰り返しパターンが現れているはず

数式で表現してみる

priv.jsonを手元で生成したりして
実験すると、pおよびqが以下の形を

していることがわかる

\begin{aligned} p&=a\mathrm{X}+c\\q&=b\mathrm{X}+d \end{aligned}

ただし

\mathrm{X}=1000\cdots0001000\cdots0001000\cdots

のような定数

この状態で\(N\)を計算する。

\begin{aligned} N&=\left(a\mathrm{X}+c\right)\left(b\mathrm{X}+d\right)\\&=ab\mathrm{X}^{2}+\left(ad+bc\right)\mathrm{X}+cd \end{aligned}
\begin{cases} A=ab\\ B=ad+bc\\ C=cd \end{cases}

\(\mathrm{X}\gg a,b,c,d\)なので、
\(N\)を\(\mathrm{X}\)進表示することで
直ちに以下の係数を得る。

\begin{cases} A=ab\\ B=ad+bc\\ C=cd \end{cases}

これらを連立させることで、式

\left(bc\right)^{2}-B\left(bc\right)+AC=0

を得る。これを\(bc\)の2次方程式として解くと\(bc\)が得られるので、

\begin{aligned} A+B-bc&=a\left(b+d\right)\\bc+C&=c\left(b+d\right) \end{aligned}

を計算する。

\begin{aligned} A+B-bc&=a\left(b+d\right)\\bc+C&=c\left(b+d\right) \end{aligned}

ところで\(p\)は

p=a\mathrm{X}+c

であり、RSA暗号の要件からこれは素数。
つまり\(a\)と\(c\)は互いに素であるので、

\operatorname{GCD}\left(a\left(b+d\right),c\left(b+d\right)\right)=b+d

が成り立つ。GCDは拡張ユークリッドの互除法を用いて高速に求まるので\(b+d\)が求まり、
これと上式から\(a,c\)も直ちに求まる。

いま\(a,b,c,d\)の全てが求まったので\(p,q\)を復元できる。

よってRSA暗号の秘密鍵が求まりこれにより問題が解ける。

⋯⋯ともかく、デモをお見せします

  • RSA暗号は広く使われているぶん、
    さまざまな攻撃手法が研究されている
  • いまは適切に利用すれば安全とされているが、
    今後の計算能力の向上などにより安全性が
    崩壊する可能性も考えられる
  • 新しい暗号への乗り換えも検討しよう

おしまい

TSG LIVE! 4「ライブCTF」解説スライド

By Koki Takahashi

TSG LIVE! 4「ライブCTF」解説スライド

  • 1,474