セキュリティ・キャンプ2025 ネクスト 応募課題晒し
はじめに
セキュリティ・キャンプ2025 ネクストに参加することになりました。
普段はあまり自分のことを発信しないのですが、応募課題を通じて、これまで取り組んできたことや、今後やりたいことをうまく言語化できたので、公開することにしました。
あなたに関する問い
あなたは今までどのようなことをやってきましたか.どのようなことができて,どのようなことが得意で,どのようなことに自信がありますか.
どのようなものを作りましたか.どのような情報を発信してきましたか.
どのようにしてそうしたことをやってきましたか.なぜ,そのようなことをやってきましたか.やってきてどう思いましたか.
参加できた場合,セキュリティ・キャンプ ネクストにどのようなことを期待し,どのようなことをやってみたいですか.
私は低レイヤ技術に興味があり、抽象化の階層を一つ一つ掘り下げながら、コンピュータの仕組みを学んできました。私を突き動かしているのは「仕組みを知りたい」という知的好奇心です。以下に、これまで作ってきたものの一部を紹介します:
- コンパイラの仕組みに興味が湧き、Cコンパイラを自作しました。この経験を通じて、コンパイラの内部構造やC言語の仕様を深く理解できました。Cでは型を確定させるためにトークンを前後に行き来しながら読む必要があり、実装には苦労しました。また、compound literalやcomma operatorといった言語機能は、実装を通して初めてその存在を知ることができました。
- WebAssembly(Wasm)を使えば、再コンパイルなしでバイナリをどこでも安全に実行できると聞き、興味を持ちました。そこで、書籍を参考に簡単なWasmランタイムを作成しました。しかし、参考にした書籍ではフィボナッチ数列を計算するのに必要な命令しかサポートされておらず、また実装を簡素にするため、私が最も知りたかった検証ステージについては省略されていました。そこで、自分でWasmの仕様書を読みながらランタイムをフルスクラッチで作り、公式のテストスイートを全て通しました。詳細はブログ記事[1]を参照してください。開発の過程で仕様にいくつかバグを見つけたため、報告して修正を行いました。この経験を通じて分かったことは、「Wasmの安全性はそこまで強固なものではない」ということです。例えばstoreやloadといったメモリアクセス命令の実行時には範囲外アクセスのチェックが行われますが、このチェックはページ単位です。仕様では1ページは64Kバイトであり、かなり荒いチェックになります。また、Wasmの線形メモリにはstack canaryやASLRといった、一般的なセキュリティ機構が存在しません。さらに、現状のWasmにはi32やf32といったプリミティブな型しかなく、配列や構造体を型として表現することができません。ポインタもi32として扱われます。実行前に型検査が行われますが、これが原因でそこまで強い制限にはなっていません。この経験を通じて、Wasmの仕組みを深く理解することができました。
- 大学の課題で「Javaでソケット通信を使うプログラムを自由に作る」という課題が与えられたため、9Pサーバーを実装しました。9Pは、Plan9という分散OSでネットワーク透過なファイルシステムを構築するために開発されたプロトコルです。WSLとWindows間のファイル共有にも使用されており、以前からその仕組みが気になっていたため、この機会に実装に挑戦しました。9Pは、TcreateやTopenのように、Unixのファイル操作に対応するメッセージを持ち、シンプルで分かりやすいプロトコルでした。
- ハイパーバイザーの仕組みに興味が湧き、Linuxカーネルが動作する程度のハイパーバイザーを自作しました。cpuid命令の実行やMSRの読み書きによるVM-Exitに一つずつ対応していき、最終的に/initが動作したときはとても嬉しかったです。開発を通じて、ハイパーバイザーの仕組みを深く理解できたと同時に、ゲストであるLinuxカーネルの仕組みも知ることができました。
私は「作って学ぶ」ことを大切にしています。実際に手を動かすことで、単に本を読んだり、使い方を学んだりするよりもはるかに深い理解が得られるからです。仕組みを理解することでできることの幅が広がり、問題解決の選択肢も格段に増えると実感しています。
例えば、私はSecHack365で、WasmOS[2]という、Wasmバイナリをカーネル空間で実行するマイクロカーネルを開発しました。マイクロカーネルの課題の一つにコンテキストスイッチのオーバーヘッドがあります。そこで、Wasmを用いてアプリケーションをカーネル空間で実行すれば、安全性を損なうことなく、この課題を解決できるのではないかと考えたのが出発点でした。こうしたアイデアを思いつけたのは、OSカーネルやWasmの仕組みを深く理解していたからこそだと思っています。
私がバイナリセキュリティに興味を持ったのも、攻撃手法が仕組みの深い理解をもたらしてくれるからでした。たとえば、古典的なスタックオーバーフロー攻撃やGOT overwrite攻撃を理解するには、関数呼び出しの仕組みや共有ライブラリ関数の呼び出しの仕組みを知る必要があります。私は「作って学ぶ」のと同時に、「壊して学ぶ」ことも大事にしています。壊すことが、ときに仕組みの本質的な理解につながるからです。
セキュリティ・キャンプ全国大会 2022(専門A)、2023(専門C)に参加し、Car Hacking、Linuxカーネルに対する攻撃手法、デジタル・フォレンジック、脅威モデリングなど、専門的な内容について講義を受けました。この経験を通じて、セキュリティ分野の幅広さを実感しました。特に印象に残っているのは、「トリアージ技術を活用したバグ・脆弱性情報の分類および解析の自動化」に関する講義です。この講義では、Fuzzingによってソフトウェアのバグを発見し、それをトリアージするという体験をしました。趣味レベルの開発では「見つけたバグはすべて修正する」ことが当たり前であったため、「バグに優先順位をつける」という考え方自体が私にとって新鮮でした。実際の現場では、ソースコードの規模が大きく、すべてのバグを発見・修正するのは非現実的であるため、バグに優先順位をつけて対処したり、脅威分析に基づいて危険性の高い箇所を重点的に調査したりする必要があります。セキュリティ・キャンプの講義は、CTFなどでは得られにくい「現実のセキュリティ」に対する理解を深める貴重な機会となりました。
また、GCC 2025 Taiwanにも参加し、世界中の学生とともに専門的な講義を受けました。グループワークでは「量子コンピューティングとセキュリティ」をテーマに開発に取り組みました。最終日までに成果物を完成させる必要があり、チームメンバーと夜遅くまで作業したのは、今では良い思い出です。私は基本的に一人で作業することが多く、技術一本な性格です。しかし、このグループワークは、一人では完成させることができなかったと感じています。GCCを通じて技術面で成長できただけでなく、コミュニケーションやチームワークの重要性を身をもって学ぶことができました。さらに、英語に対する苦手意識も薄れ、日本のコミュニティ内にとどまることの「もったいなさ」を実感しました。今後は、よりグローバルに活躍できる技術者を目指していきたいと考えています。
昨年の夏にはFlatt Securityのインターンに参加しました。Webアプリケーションに対する攻撃手法を学び、診断をし、レポートを作成するという内容でした。レポートを書く際は、開発者の立場に立ち、actionableな対策を提案することを心がけるようにアドバイスされ、脆弱性は修正されてこそ意味があるということ、良いセキュリティエンジニアになるためには良い開発者である必要があることを学びました。
セキュリティについて学ぶ過程で、私は「ある種類のバグが存在しないことを厳密に保証できないか」と考えるようになりました。診断でバグが見つからなかったとしても、それが安全であることを意味するわけではありませんし、見つかったバグを修正したとしても、それで十分とは言い切れません。セキュリティの本質的な課題は、「どこまでやれば安全と言えるのか」という問いに対して、明確な答えが存在しないことにあります。
このような背景から、私はプログラム検証(広くは形式手法とも呼ばれます)に興味を持ちました。プログラム検証は、ある種のバグが無いことを数学的に保証するための理論です。理論を学ぶ際も「作って学ぶ」という姿勢は変わりません。例えば、並行プログラムの正しさを検証するためのモデル検査という手法があり、発展的なアルゴリズムとしてsymbolic model checkingが知られています。私はこの理論を学んだ後、実際に簡単なsymbolic model checkerを自作し[3]、デッカーのアルゴリズムや食事する哲学者問題といった、簡単なプログラムの検証を行いました。さらに、この内容をKernel/VM探検隊@東京 No17で発表しました。
プログラム検証はバグのないソフトウェアを作るための方法論ですが、現実はそう甘くありません。私は現在TIER IVでアルバイトをしており、カーネルやミドルウェアの開発に携わっています。TIER IVでは形式手法が取り入れられており、モデル検査や定理証明支援系を用いてソフトウェアが検証されています。しかし、現実のソフトウェアを検証しようとすると、状態空間爆発や検証器の機能不足といった困難に直面します。この経験から私は、当初思い描いてた形で形式手法が現実に応用可能であるとは考えなくなりました。形式手法は銀の弾丸ではなく、適用範囲には限りがあり、また労力もかかります。
しかし、それでも理論は役に立ちます。例えばRustプログラミング言語は、所有権を用いることで、コンパイルが成功するならば、(unsafeが"正しく"使われているという仮定のもとで)メモリバグやdata raceが無いことを保証します。Rustの型システムが本当にこれを保証するかは興味のある問いですが、RustBeltの研究[4]によって、理論的には肯定的な結果が示されています。現実の深刻なバグのほとんどがメモリバグに起因することを考えれば、Rustはバイナリセキュリティを根本から変える可能性を秘めています。
私は現在、卒業研究としてIncorrectness Separation Logicの研究をしています。これはtriple <P>C<Q>についての論理体系です。Pはpresumpion、 Cはプログラム、Qはresultです。tripleの直感的な意味は、「Qを満たす状態は、Pを満たす状態からCを実行することで到達可能」というものです。Qとして「バグがある(エラーが発生する)」という性質を考えれば、<P>C<Q>は「バグはPを満たす入力から到達可能」という意味になります。このため、Incorrectness Separation Logicはバグ発見の理論的基礎であり、応用としては例えばMetaが開発している静的解析器Inferが挙げられます。バグ発見に理論を応用することの利点は健全性を保証できる点です。理論に基づくことで、false positiveがない(健全な)バグ発見器を作ることができます。
理論をセキュリティに応用することには困難がありますが、根本的な解決策となる可能性も秘めています。プログラムの動作原理を深く理解しており、特にバイナリセキュリティに関する知見を持ち、理論にも触れていることが私の強みです。私はソフトウェアエンジニアとして、セキュリティエンジニアとして、そしてプログラミング言語理論の研究者として、理論と現実を行き来しながら、現実的かつ根本的な解決策を模索できる「エンジニア」になりたいと考えています。
私は、取り組む問題が難しければ難しいほど燃える性格です。これまで、数多くの「分からない」との出会いが私のやる気を引き出し、成長の原動力となってきました。しかし、専門性を深めるにつれ、そうした「分からない」との出会いは徐々に減っていきます。また、自分の専門領域に注力するあまり、他の分野に触れる機会も少なくなりがちです。
セキュリティ・キャンプ ネクストの講義は基盤技術に焦点が当てられており、私にとっても新鮮な話題が多いです。キャンプを通じて、多くの「分からない」と出会い、自分をさらに成長させたいと考えています。また、講義が既存技術の仕組みを解説するだけにとどまらず、「その先に何を作るのか」を見せてくれる、そんな刺激的な内容であることを期待しています。
課題への姿勢に関する問い
自身で何らかの技術的な疑問を設定し,その疑問を解決しようと取り組み,その過程を示すことで,自身の技術力や課題に取り組むやりかたを説明してください.
(疑問の例:実行ファイルはどのような構造になっているのだろう? pingコマンドを実行すると何が起きるんだろう? オンラインゲームはどうやって通信対戦を実現しているのだろう? といったようなことです)
設定する疑問は何でも構いませんし,解決しなくても構いません.
解決できたかどうかではなく,いかに課題に取り組むかという点を評価します.
GCC 2025 Taiwanの「Modern Kernel Exploitation」という講義を受けた際に、「Cross-Cache Attack」という攻撃手法を知りました。これはUAF(Use After Free)を利用して、victim objectが存在するslabを本来とは異なるcacheのslabとして再利用させる手法です。
UAFが可能な場合、典型的な攻撃の流れは以下の通りです:
- victim objectをfree
- target object(権限昇格に便利な構造体のこと。例えば関数ポインタや権限情報へのポインタを持つ構造体)を確保
- UAFを用いて2で確保した構造体を改ざんし、権限昇格
しかし、最近のLinuxカーネルではvictim objectとtarget objectが異なるcacheに配置されることが多く、上の手順が通用しないケースが増えています。Cross-Cache Attackはこの制約を回避するための手法で、victim objectが存在するslabを、target objectが割り当てられるcacheのslabとして再利用させることで、異なるcache間のUAFを可能にします。この手法はDirtyCredやDirty PageTableなど、他のモダンな攻撃手法の基礎となっています。
GCCの講義では、時間の都合上、簡単な説明とデモのみが行われたため、概要は理解できたものの、詳細までは追いきれませんでした。そこで、講義終了後に関連するCVEのwriteup記事[5]を参考に勉強を進めましたが、それでも腑に落ちない部分が多く、自分で簡単なPoC(Proof of Concept)を作成することにしました。私はまず、脆弱なカーネルドライバを自作し、それに対してCross-Cache Attackを用いて権限昇格を行うPoCを実装しました。攻撃コードを作成・デバッグする過程で、手法の仕組みや前提条件について深く理解することができました。同様に、Dirty PageTableやPageJack[6]など、他のモダンな攻撃手法についても学習を進め、それぞれPoCを作成して検証を行いました。
新しい攻撃手法を学ぶ際、私は簡単なPoCを作成して理解を深めるようにしています。CTFの問題や実際の脆弱性(CVE)を題材に学ぶことも可能ですが、これらには非本質的な複雑性が含まれていることが多く、攻撃手法そのものを学ぶには適していないと感じています。実際、私がCVEやCTFのwriteup記事を読んで勉強していたときも、本質的な部分だけを切り出して理解するのに苦労しました。攻撃手法そのものに焦点を当てた記事はほとんど見かけなかったため、自分で学んだ内容を整理し、ブログ記事[7]として公開しました。記事では、私が作成したPoCを使って攻撃手法をハンズオン形式で学ぶことができます。非本質的な複雑性を排除し、攻撃のメカニズムに集中できる内容となっており、学習コンテンツとして有用であると自負しています。また、この記事を英語で執筆したことで海外からのアクセスも多く、日本国内よりも海外ユーザーの方が多い状況です。
さらに、先日開催された TsukuCTF 2025[8] では、Cross-Cache AttackとPageJack をテーマにした問題を作問しました。CTFの作問は初めてでしたが、これをきっかけに Linuxカーネルに対するモダンな攻撃手法に興味を持ち、学ぼうとする人が増えてほしいという思いで取り組みました。writeup記事[9] には、前述したブログ記事へのリンクを掲載しています。
CTFの作問やブログ記事の執筆を通して多くのことを学び、自分自身も大きく成長できたと感じています。今後も、学んだことを積極的に発信し、コミュニティに還元していきたいと考えています。
興味ある分野に関する問い
セキュリティ・キャンプ ネクストの講義の一覧を見て,その中から興味のある講義を選び,その講義で扱うテーマに対して自分が考えること,興味,疑問,課題,自分なりの考察などを説明してください.
その分野について知識があるかどうかではなく,いかに興味や疑問を持ち,課題を考え,自分なりに調べて考察するかといった点を評価します.
「TCP/IPプロトコルスタック自作入門」
上で紹介したWasmOSを作った際は、プロトコルスタックをフルスクラッチで作ることはせず、既存のものに多少手を加えて、bindとlistenを実装した程度でした。この講義でプロトコルスタックをゼロから自分で作ることで、より一層理解を深めたいと考えています。余裕があればxv6だけでなく自作OSにも移植したいと考えています。
「C++ の進化とライブラリ設計」
前述のとおり、理論上はバグのないソフトウェアを作ることは可能です。しかし、現実のソフトウェア開発においては、そのようなアプローチはあまり用いられていません。既存の多くのソフトウェアはCやC++で書かれており、多くのバグを抱えています。これらをRustで書き直したり、形式手法を用いて厳密に検証することは、現実的には非常に困難です。私が「バグの非存在を証明するための理論」ではなく、「バグを発見するための理論」の研究に興味を持ったのも、こうした背景によるものです。
本講義では、C++の機能を活用し、安全でないコードをできるだけ書きにくくする手法が扱われるとのことですが、私はこのような機能に、安全性に課題のある言語を用いながらも、できる限り安全なソフトウェアを実現しようとする開発者の創意工夫が表れると考えています。そこには理想と現実の間でのトレードオフが存在し、それを乗り越えるためのエンジニアリングがあります。これらの機能について学ぶことで、将来、理論を現実に応用する際のヒントを得たいと考えています。
「低レベルMN-Coreプログラミング」
私は過去にRISC-V CPUを自作した経験があるため、CPUの基本的な構造や仕組みについては理解しています。しかし、汎用CPUはさまざまなプログラムを動かすことを前提として設計されており、「大多数にとってそこそこ最適」なアーキテクチャになるよう工夫されています。一方、本講義で扱われるMN-Coreは、深層学習向けの計算を念頭に開発されたアクセラレータであり、その命令セットや設計には、深層学習特有の計算特性を生かした最適化が施されていると考えられます。また、ソフトウェアとハードウェアが協調することで可能になる最適化についても取り上げられるのではないかと期待しています。
私はこれまで主にソフトウェア開発に注力してきたため、ハードウェアに関しては知識が浅いです。MN-Coreのプログラミングを通じて、その設計思想や最適化手法について学ぶことで、ハードウェアを含めたより広い視野から問題解決に取り組める力を身につけたいと考えています。
おわりに
強くなります。
-
Ralf Jung, Jacques-Henri Jourdan, Robbert Krebbers, and Derek Dreyer. 2017. RustBelt: securing the foundations of the Rust programming language. Proc. ACM Program. Lang. 2, POPL, Article 66 (January 2018), 34 pages. https://doi.org/10.1145/3158154 ↩︎
-
Awarau and pql. 2022. CVE-2022-29582. https://ruia-ruia.github.io/2022/08/05/CVE-2022-29582-io-uring/#crossing-the-cache-boundary ↩︎
-
Zhiyun Qian, Jiayi Hu, Jinmeng Zhou, Qi Tang and Wenbo Shen. 2024. PageJack: A Powerful Exploit Technique With Page-Level UAF. https://i.blackhat.com/BH-US-24/Presentations/US24-Qian-PageJack-A-Powerful-Exploit-Technique-With-Page-Level-UAF-Thursday.pdf ↩︎
-
r1ru. 2025. Linux Kernel Exploitation. https://r1ru.github.io/categories/linux-kernel-exploitation/ ↩︎
-
r1ru. 2025. TsukuCTF 2025 Writeups. https://r1ru.github.io/posts/7/ ↩︎
Discussion