⭐️Use After Free

返したはずのメモリを、まだ自分のものだと思って使うバグ(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 のある言語は言語の仕組みで防ぐ

参考: https://cwe.mitre.org/data/definitions/416.html