返したはずのメモリを、まだ自分のものだと思って使うバグ(UAF)。
メモリをロッカーにたとえる。登場するのは PHP の中のプログラム 2 つ(人ではない)。
- 進捗係(p): アップロードの進捗を管理する PHP 内部の処理
- 受信係(q): 届いたリクエストのデータを置く PHP 内部の処理
- 攻撃者: 外からリクエストを送るだけ。メモリには直接触れない
① 進捗係が 7 番を借り、「7 番」とメモする 7 番: [進捗データ]
② 進捗係が 7 番を返す。メモは消し忘れる 7 番: [空き]
③ 受信係が空いた 7 番を借り、届いたデータを入れる
7 番: [攻撃者が送ったデータ]
④ 進捗係がメモを見て 7 番を開け、中身を進捗データだと思って使う
なぜ危ないか: 同じ中身でも、どの係が読むかで扱いが変わる。
進捗係のメモは決まった書式になっている。攻撃者はその書式に合わせてデータを作る。
進捗係のメモの書式 攻撃者が送ったデータ
1 行目: 受信済みバイト数 AAAA ← 何でもいい(埋め草)
2 行目: 次に呼ぶ処理の場所 0x7f123456 ← 狙いはここ
受信係にとってはただの文字列なので、置くだけで無害
進捗係は 2 行目を「次に呼ぶ処理の場所」と信じて、そこへジャンプする
0x7f123456 にコマンドを実行する処理を置いておけば(または既存の関数を指せば)、好きなコマンドが動く = 乗っ取り
実際は防御(番地のランダム化など)を回避する手順も要る。php2shell の具体的な手順は非公開
攻撃者は本来「データ」しか送れない。進捗係に読ませることで「どこを実行するか」まで決められる(RCE)
C / C++ で起きる。Rust や GC のある言語は言語の仕組みで防ぐ