MOPB-39-2007:PHP str_replace() Memory Allocation Integer Overflow Vulnerability

(Last Updated On: 2018年8月16日)

Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。

■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser

■PoCまたは攻撃コード
MOPB-39-2007.phpの予定

■リファレンス
なし

■サマリ
str_replace()関数が1文字を長い文字列で置換するように呼び出され、その1文字が置換対象の文字列に非常に多く含まれている場合、バッファのサイズが計算される際に整数オーバーフローが発生します。小さすぎるバッファはオーバーフローを引き起こします。

■影響するバージョン
PHP 4.4.5未満、PHP 5.2.1未満

■詳細情報
str_replace()関数が呼ばれる場合、置換対象の文字列の長さによって2つの別の経路でコードを実行します。1文字の検索文字列はより効率的に処理するために別の関数で処理されます。しかし、より効率的なコードは整数オーバーフロー脆弱性を含んでいます。

Z_STRLEN_P(result) = len + (char_count * (to_len – 1));
Z_STRVAL_P(result) = target = emalloc(Z_STRLEN_P(result) + 1);
Z_TYPE_P(result) = IS_STRING;

例えば、char_countとto_len両方が65537以上の場合、32ビットのカウンタがオーバーフローするのは明らかです。このため、emalloc()によって十分なメモリが割り当てられません。置換が行われる際にバッファーオーバーフローを引き起こします。攻撃を成功させるには目的のバッファは、オーバーフローで上書きできコピーがクラッシュを起こす前に終了するよう、置換対象の文字列の前に配置されなければなりません。

■PoC、攻撃コードまたは再現手順
この脆弱性をテストするには以下のコードを実行してください。

<?php

str_replace(“A”, str_repeat(“B”, 65535), str_repeat(“A”, 65538));

?>

このPoCはPHPをクラッシュさせるだけです。この脆弱性を利用したコード実行攻撃は将来このサイトい追加されます。後ほど確かめてください。

■備考
解説した問題はPHP 4.4.5, PHP 5.2.1で修正されました。しかし、PHP 4.4.5, PHP 5.2.1より前のセキュリティフィックスは壊れており、同じ個所でオフバイワンオーバーフローに脆弱でした。置換文字を別の文字に置き換える場所で発生します。

新しくリリースされたPHP 4.4.6はオフバイワン脆弱性が修正されていますが、PHP 5.2.1には修正がありません。

投稿者: yohgaki