
FreeFloat FTP Server 1.0 におけるバッファオーバーフロー。単一の安全でないハンドラがいかにして異なるコマンド間で複数のCVEエントリを生成し得るかを示しています。
FreeFloat FTP Server 1.0におけるバッファオーバーフロー。単一の安全でないハンドラが、異なるコマンドにわたって複数のCVEエントリを生成する様子を示しています。
このリポジトリは、メモリ破損の悪用(メモリ破壊エクスプロイト)を教える際に使用している教材の一部です(通常業務に加えて、さまざまなサイバーセキュリティコースで講師を務め、次世代のリバースエンジニアを育成しています)。
CVE-2025-5548 は、脆弱性研究がアクセス可能なスキルであり、長年の経験を持つシニア研究者だけのものではないことを学生に示したいときに使用するケースです。FreeFloat FTP Server 1.0 は小さなレガシーWindowsアプリケーションで、セットアップも実行もクラッシュも簡単です。オーバーフローは標準的なFTPコマンドを通じて引き起こされ、エクスプロイトの経路はクリーンなバニラEIP上書きであり、ファジングから動作するシェルまでの全プロセスを1回のセッションで完了できます。
このケースは、私のトーク 「The Path That Leads to Your First CVE」 にも直接関連しています。このトークでは、初心者にとって脆弱性研究への最も現実的な入り口の一つは、古いソフトウェアを分析し、その内部動作を理解し、まさにこのクラスの脆弱性を生み出す欠落した長さチェックを探すことだと説明しています。FreeFloat は、実際のバグを見つけて文書化するのに何年もの経験は必要なく、好奇心、デバッガ、そして系統的なアプローチが必要であることを示すために使用する例の一つです。
このケースが教育に特に効果的なのは、CVEがどのように割り当てられるかというより広範な教訓に結びつく点です。FreeFloat の同じ安全でない入力ハンドラが、USER、PASS、NOOPなど複数の異なるFTPコマンドにわたってオーバーフローを引き起こし、それぞれが独立して報告され、独自のCVEエントリを受け取りました。このバイナリのCVEリストを見て数十のエントリを目にした学生は、CVEの数は脆弱性の数と同じではなく、根本原因を理解することが症状をカタログ化するよりも価値があることをすぐに学びます。
学生がこのようなケースを通じてプロセスを理解したら、次に何が来るかの実際の例を示します。バッファオーバーフローとメモリ破損の練習を2週間行った後、彼らが見つけられる種類の脆弱性は既に実際のソフトウェアに存在しています。次のリポジトリは、学習パスの初期に見つけるのに十分アクセスしやすいもの、例えば CVE-2025-70330 において、発見、分析、文書化、CVEリクエストの完全なサイクルを学生に示すために私が発見した脆弱性を文書化したものです。
このリポジトリはより大きなコレクションの一部です。幅広いテクニック、脆弱性タイプ、ターゲットアーキテクチャにわたってエクスプロイトを練習したい場合は、Binary-Exploitation リポジトリをご覧ください。そこでは、これらすべての資料が、さらに多くのCVE、方法論、エクスプロイト演習とともに整理・管理されています。
この脆弱性は、非常に古いWindows FTPサーバーであるFreeFloat FTP Server 1.0に影響を与えます。これは最新のセキュリティ慣行なしに書かれました。2025年、研究者がこの同じバイナリに影響を与える多くのCVEを報告しました。
例としては以下のものがあります:
各CVEは異なるFTPコマンドを参照していますが、プログラムをリバースすると、その多くが同じ脆弱なコードパスに到達することが明らかになります。
これにより、このケースはバッファオーバーフローの例としてだけでなく、以下のことを示す実証としても興味深いものとなっています:
バイナリをリバースすると、すべてのFTPコマンドが同じディスパッチャ関数によって処理されていることが観察できます。コマンド文字列はセッション構造体内に格納され、いくつかのコマンドハンドラは、受信データの長さをチェックせずに、strcpy、strcat、memcpyなどの安全でない関数を使用してユーザー入力を固定サイズのバッファにコピーします。
このため、CVEの説明が特定のコマンドのみに言及している場合でも、異なるコマンドがスタックを上書きする可能性があります。
例えば、次のようにしてクラッシュを引き起こすことができます:
NOOP AAAAA...
USER AAAAA...
PASS AAAAA...
HOST AAAAA...
ANYTHING AAAAA...
唯一の違いは、リターンアドレスを上書きするのに必要なバイト数です。これは、このソフトウェアについて報告された多くのCVEが同じ根本原因を共有していることを意味します。
FreeFloat FTP ServerはTCPポート21を介して受信したコマンドを処理し、コマンド文字列を内部のセッション構造体に保存します。その後、コマンドハンドラは適切な長さ検証を行わずに、ユーザー制御のデータをローカルスタックバッファにコピーします。
バイナリをリバースすると、いくつかのコマンドハンドラが固定サイズのバッファと安全でないコピー操作を使用していることが観察できます。脆弱なロジックの簡略化されたバージョンは次のようになります:
char buffer[256];
strcpy(buffer, user_input);
宛先バッファは固定サイズであり、入力長がチェックされていないため、長い文字列を送信すると、コピー操作がバッファの末尾を超えて書き込むことになります。
さらにデータが書き込まれると、スタックレイアウトが破損し、最終的には保存されたリターンアドレスが上書きされます。
関数が戻ると、実行はユーザー制御の値にジャンプし、クラッシュが発生します。デバッガの下では、これは命令ポインタが攻撃者制御のデータで上書きされることとして確認できます。
クラッシュは、有効なFTPコマンドの後に長い文字列を送信することで再現できます。Pythonを使用した例:
import socket
ip = "127.0.0.1"
port = 21
payload = b"A" * 500
s = socket.socket()
s.connect((ip, port))
s.recv(1024)
s.send(b"USER anonymous\r\n")
s.recv(1024)
s.send(b"PASS anonymous\r\n")
s.recv(1024)
s.send(b"NOOP " + payload + b"\r\n")
s.close()
デバッガ上で実行すると、クラッシュは次のように表示されます:
EIP = 41414141
これにより、ユーザー制御のデータがリターンアドレスを上書きしていることが確認されます。
このリポジトリの目的は、クラッシュを示すだけでなく、エクスプロイト開発で一般的に使用される同じ方法論を用いて、脆弱性を悪用する全プロセスをステップバイステップで実演することです。
メインのREADMEを簡潔に保つため、詳細なエクスプロイトノート、スクリプト、デバッガの手順は、このリポジトリの Vulnerability 📂 フォルダ内に配置されています。
そこでは、ファジング、オフセットの発見、悪い文字の分析、ガジェットの検索、シェルコードの実行など、このCVEを悪用するために使用される完全なワークフローを見つけることができます。