HeaderLogo
← Blog一覧に戻る

2026.04.15   [ TECH ]

Agent T PHP脆弱性

Agent T PHP脆弱性

TryHackMeの課題をやったのでウォークスルー

今回は簡単な課題Agent-Tとかいうやつをやった。

先日、Kaliの仮想環境も整えたことだし、早速VPNに接続してサービスに接続する。

うーん変わったところはないな・・・・・。

SQLIも通用しないし、開発者ツールで見ても変なところはない。

怪しいところがないか、Dirbもしてみよう・・・・・・。

これも怪しいディレクトリはないな。

PHP 8.1.0-devの脆弱性

もう少し深いところまで見てみよう。

Nmapで探すと、

ポート80に関して PHP server 5.5 PHP ver 8.1.0-dev

であることがわかった。調べてみたところ、

PHP 8.1.0-devの脆弱性は、一般的なバグではなく、PHPのソースコードのリポジトリが攻撃され、悪意のあるコード(バックドア)が直接埋め込まれたという衝撃的な事件が背景にあるらしい。

2021年3月28日、PHPの公式Gitリポジトリ(git.php.net)が何者かによって不正アクセスを受け、2つの悪意あるコミットが直接流し込まれたみたいだね。

当時のメンテナーである Nikita Popov 氏が、サーバーが侵害されたこと、そして自前でのGitインフラ運用をやめてGitHubへ移行することを発表した歴史的な投稿を発見した。↓当時のPHPニュースの記事

悪意あるコードの現物: GitHubのミラーに残っている修正履歴

  • これを見ると、犯人が 「Fix typo(タイポを修正)」というもっともらしい理由でバックドアを隠そうとしたことがわかる。

3月28日(日)、PHPのGitコードリポジトリに2つの悪意のあるコミットがプッシュされ、PHPの生みの親であるラスムス・ラードルフ氏と、メンテナーであるニキータ・ポポフ氏の名前で署名されていた。

悪意のあるコミットにおいて、攻撃者は些細なタイプミスの修正を装い、「タイプミスを修正」という謎めいた変更を上流に公開した。

追加された行370を見ると、 zend_eval_stringこの関数が呼び出されると、実際には、このハイジャックされたバージョンの PHP を実行している Web サイト上で簡単にリモート コード実行 (RCE) を取得するためのバックドアがコード内に仕掛けられます。この行は、文字列が「zerodium」で始まる場合、useragent HTTP ヘッダー内から PHP コードを実行します。

犯人の巧妙な手口

この事件が「恐ろしい」と言われる理由は、犯人が単にコードを盗んだのではなく、「なりすまし」を行っていた点にある。

  • 開発者の名前を偽装: 犯人は、PHPの生みの親である Rasmus Lerdorf 氏や、主要開発者の Nikita Popov 氏の名前でコミットを行った。一見すると「信頼できる開発者がちょっとした修正をしただけ」に見えるように偽装したのだ!
  • 合言葉は「Zerodium」: バックドアのコード内には zerodium という文字列が含まれていた。Zerodium社は脆弱性を買い取る有名な企業らしいが、これを含めたのは犯人の悪ふざけ(あるいは陽動作戦)だと考えられている。

このバックドアが混入されたのは、当時開発中だった最新バージョンである 8.1.0-dev

幸いなことに、コミットから数時間以内にコードレビューによって発見され、正式リリース版(安定版)のPHPにこのコードが載ることはなかったらしい。

しかし、開発者や一部のテスト環境、そして TryHackMe のような学習サイトのターゲットとして「8.1.0-dev」をインストールしていたサーバーは、このバックドアの影響を受けてしまったようだ。

攻撃

RCE(リモートコード実行)が成立する流れ

通常、Webサーバーは受け取ったHTTPヘッダー(User-Agentなど)を単なる「文字列」として扱う。しかし、このバックドアが入ったPHP 8.1.0-devは違う。

  1. 罠の起動: リクエストに User-Agentt ヘッダーが含まれていると、PHP内部で犯人が仕込んだ if 文が「お、合言葉が来たぞ」と反応。
  2. 中身の取り出し: ヘッダー内の zerodium という文字より後ろの部分を抜き出し。
  3. 禁断の関数 zend_eval_string: 抜き出した文字列を zend_eval_string 関数に放り込む。
    • この関数は、**「受け取った文字列を、そのままPHPコードとして実行せよ」**という強力な命令だ。
  4. RCE成立: system('id'); と送れば、サーバー上でそのコマンドが実行され、結果が画面に返ってくるという仕組みだ。

やってみよう

curlでヘッダーにAgenttをいれてコマンドを実行したら確かに、HTMLより上の部分にgid と groupsの情報が表示された。。ひえっ。

毎回Headerを送るのは面倒なのでExploitDBを漁っていると有効なExploitCodeを発見した。

Pythonコードが書いてある。

こちらを拝借。

Exploit.pyって名前でいいや。

起動するとURLを入力を促されて。

コマンドを入力できるようだった。以下で検索!

find / -name *flag* 2>/dev/null

フラグあった。

まとめ

今回はRCEまでわずか1手でめちゃくちゃ簡単な例だったが、歴史をみると世間ではいろんなことがおきているなぁ・・・

配信元がハックされるとおしまいだもんな。これはいよいよマトリックスのような世界になってきたぞ・・・!