概要

学内で一部の生徒(主にサークル外部)向けに非常に簡単なPwnについての講義を実施しました.

内容としては,扱う脆弱性は初歩的なスタックオーバーフローに留め,バイナリを読んだことが無い人や,C言語でのプログラミング,Linux上での操作に慣れていないくらいの人を対象としたレベル感です.

最近,CTFにおけるPwnの分野はインフレーションが激しいように感じられます. セキュリティに興味を持ち,CTFに参加しようと思っても「Easy,Babyと書かれた問題すら解けない」と挫折してしまう様な人もいるでしょう(実際,自分も最初はそうでした).

そういった,どこから手を付けたらいいのかわからないレベル感の人に向けて,段階的に必要な知識を教えつつ,自分で調べ,手を動かして理解して欲しいという思いで資料を作成しました.

Pwnに限らず,わからない事を自分で調べ,理解する楽しみに気付いてもらいたいですね.

資料

資料の内容にあまり自信が無い点,学内での講義である点などから,公開範囲を限定したいと考えました.

しかし,PDFでの配布や,学内のシステムを使った配信では,修正やアップデートが面倒でした.

かといって,今回の講義の為だけにサーバーを用意するのも面倒だった為,これら全ての課題を程よく解決する方法として,

GitHub pagesでの配信を行いました.

GitHub pagesでは,静的なサイトの配信しか行なえませんが,Password-protection-for-static-pagesを参考に,簡単なページへのアクセス制限を施しました.

これにより,資料についてはトップページのURLと各回のパスフレーズを共有するだけで済みました. さらに,当然GitHubを使っている為,資料の修正やアップデート,追加についても一切苦労する事はありませんでした.

また,全体を通してVM + blowserの2画面の操作を必要とする為,ディスプレイ1枚の半分で表示しやすいようなレイアウトにしました.

環境

環境構築は初心者がつまずきやすい大きな点の一つです.

今回は,ホストOSの差異を吸収するためにVMを用いました. 必要なツールをインストールしたVagrantのboxを配布し,受講者はvagrant upするだけで必要な環境,ツールが全て整います.

各ツールの簡単な使用方法もページで説明してあります.

さらに,配布VMに入っている物と異なる,「普段自分が使っているツール群を用いたい」といった層の為に,問題は全てGitHub上で公開し,どこでも扱えるようにしました.

一つ反省点として,私が最近ハマっているという軽率な理由でfedora32をベースにした結果,runcがデフォルトでcgroup v2に対応してないので少し手を加えないとdockerが動かなかったりと,受講者に負担を掛けてしまいました. この場を使って謝罪したいと思います.

問題

問題(コード類)の管理も非常に迷った点の一つです. 資料と同様,修正や追加を考えるとgit管理したい一方, クオリティが低い問題,資料をpublicな場所に置きたくないというプライドから,VMに認証情報を置いてprivateリポジトリで扱う事も一度は考えました. 流石にそれはマズいだろうと,GitLab等のホスティングも考えましたが,手間を考えた結果普通にpublicなリポジトリに置いています.

内容

section 1

概要で述べた通り,今回は完全な初心者を対象としているため,まずはバイナリ(ELF)をどうやって(何を使って)読むのか説明しました. コンパイラによってhello world!と出力するソースコードからELFファイルが生成される事を確認し,それは他のテキストファイル等とは異なり,catbatではうまく読めない事,readelfを用いるとELFというフォーマットを解釈できる事,objdumpによって人間に読みやすいアセンブリ形式で読める事を解説しました. このセクションでは,Pwn以前に,実行ファイルを実行せずして挙動を理解する事を目標としているので,どちらかと言うとRevの解説に近いような資料となっています.

アセンブリについては,全ての命令を事細かく説明する事はせず,簡易的な解説に留めるようにしました. また,この(hello worldを読む)時点では,スタックフレームについての説明も省き,スタックというデータ構造とx86_64に於けるスタックとは何かを解説するだけに留めました.

このセクションを通して,受講者は

について大まかに理解する事ができます.

section 2

hello worldとよりも少しだけ複雑なバイナリの解析を通して,スタックフレームの理解を行い,自力でバイナリを読みます.

#include <stdio.h>

int inc(int a) {
    return a + 1;
}

int main() {
    int val;
    scanf("%d", &val);
    int ans = inc(val);
    printf("%d + 1 = %d\n", val, ans);
}

このセクションでは,資料での解説はスタックフレームとローカル変数,一部の命令,キーワードの簡単な説明に留め,残りの解読を受講者が自力で行うようになっています.

受講者はこのセクションを通して,

について理解し,実践を通して知識を身につける事ができます.

section 3

ここでは実際に非常に簡単なPwnの問題に取り組んでもらいました.

Pwnというジャンルの概要や,今回の目標設定について説明し,あとは実際に手を動かしてもらう形となっています.

以下のソースコードを-fno-stack-protector -no-pieでコンパイルしたバイナリが攻略対象です.

#include <stdio.h>
#include <stdlib.h>

void win() {
    system("sh");
}

int main() {
    int zero = 0;
    char name[30];
    printf("What's your name?\n>");
    scanf("%s", name);
    if (zero != 0) {
        win();
    }
    printf("hello %s!\n", name);
}

課題

先程のsectionでは物足りない受講者の為に課題を用意しました. サーバを用意するのが面倒なので,受講者がdocker-composeをローカルで動かす事で,問題が立ち上がります.

ncを使ってローカルホストへ接続を行い,攻略してもらいます.

また,せっかくなのでGitHubの使い方も学んでもらおうと思い,課題のWriteupをPRの形式で提出してもらうようにしました. 一部の意欲的な受講者はここまでやってくれたので嬉しかったです.

CTFのインフレについて

これは決して悪い事ではなく,セキュリティ業界全体のレベルが向上し続けていると考える事もできると思っています.