目次
高度な PHP アプリケーション脆弱性監査技術
はじめに
従来のコード監査テクノロジー。
アプリケーション コード監査に関連するその他の要素
辞書を展開してください
変数自体のキー
变量覆盖
遍历初始化变量
parse_str()变量覆盖漏洞
import_request_variables()变量覆盖漏洞
PHP5 Globals
magic_quotes_gpc与代码安全
什么是magic_quotes_gpc
哪些地方没有魔术引号的保护
变量的编码与解码
二次攻击
魔术引号带来的新的安全问题
变量key与魔术引号
代码注射
PHP中可能导致代码注射的函数
ホームページ バックエンド開発 PHPチュートリアル 高度な PHP アプリケーションの脆弱性レビュー手法

高度な PHP アプリケーションの脆弱性レビュー手法

Jun 13, 2016 pm 12:02 PM
include php rand SEED srand

高度な PHP アプリケーション脆弱性監査技術

高度な PHP アプリケーション脆弱性監査技術

?

  • 高度な PHP アプリケーション脆弱性監査技術
    • はじめに
    • 従来のコード監査テクノロジー
    • PHP バージョンとアプリケーション コード監査
    • その他の要素とアプリケーション コード監査
    • 辞書を展開してください
      • 変数自体のキー
      • 変数カバレッジ
        • 初期化変数のトラバース
        • parse_str() 変数カバレッジの脆弱性
        • import_request_variables () 変数カバレッジの脆弱性
        • PHP5 グローバル
      • magic_quotes_gpc とコード セキュリティ
        • magic_quotes_gpc とは
        • マジック クオートからの保護がない場合
        • 変数のエンコードとデコード
        • 2 回目の攻撃
        • マジック クオートによってもたらされる新たなセキュリティ問題
        • 変数キーとマジック クォーテーション マーク
      • コードインジェクション
        • コードインジェクションを引き起こす可能性のある PHP の関数
        • 変数関数と二重引用符
      • PHP 自体の関数の脆弱性と欠陥
        • PHP 関数のオーバーフローの脆弱性
        • PHP 関数のその他の脆弱性
        • session_destroy() ファイル削除の脆弱性
        • ランダム関数
      • 特殊文字
        • 切り捨て
          • 切り捨てを含む
          • データの切り捨て
          • ファイル操作の特殊文字
    • 新しい辞書をさらに探す方法
    • デモ
    • あとがき
    • 付録

?

はじめに

PHP は広く使用されているスクリプト言語であり、特に Web 開発に適しています。クロスプラットフォームで、習得が簡単で強力です。統計によると、Yahoo、Sina、163、sohu などの大規模ポータルを含む、世界中の Web サイトの 34% 以上に PHP アプリケーションが含まれています。また、Discuz、phpwind、phpbb、vbb、wordpress、boblog など、多くのよく知られた Web アプリケーション システム (bbs、ブログ、wiki、cms など) は PHP を使用して開発されています。 Web セキュリティのアップグレードがホットスポットになるにつれ、PHP アプリケーションのコード セキュリティの問題が徐々に注目されるようになり、この分野に投資するセキュリティ担当者が増えており、公開されるアプリケーション コードの脆弱性も増えています。このような状況に対応して、多くのアプリケーション担当者はコード監査を実施するためにセキュリティ部門を設立したり、セキュリティ担当者を雇用したりしているため、多くの自動化された商用コード監査ツールが登場しています。つまり、大企業の製品安全率は大幅に向上し、明らかな抜け穴は基本的になくなり、誰もが知っている監査技術は役に立たないという状況が生じているのです。私たちは、専門家によって n 回スキャンされた多くのツールやコードに直面しています。多くのセキュリティ担当者は少し悲観的で、一部の公式セキュリティ担当者も自分のコードに非常に自信を持っていますが、「絶対的なものはない」ということを忘れないでください。セキュリティ」に基づいて、新しい脆弱性を悪用する新しい方法を見つける必要があります。この記事では、従来とは異なる技術的な経験をいくつか紹介します。

さらに、この記事の脆弱性の多くはインターネット上の専門家や友人の共有に由来していることを指摘しておきます。ここで彼らに感謝しなければなりません:)

従来のコード監査テクノロジー。

WEB アプリケーションの脆弱性探索は、基本的に変数と関数の 2 つの要素を中心に展開します。つまり、脆弱性を悪用するには、送信した悪意のあるコードが n 回の変数変換を通じて変数に渡され、最終的に実行のためにターゲット関数に渡される必要があります。 「すべての入力は有害です。」この文は変数の入力のみを強調しています。多くのプログラマは、「入力」を単に gpc[$_GET,$_POST,$_COOKIE] ですが、変数は転送プロセス中に n 回多くの変更を受けました。その結果、多くのフィルターは単なる「張り子の虎」になってしまいます。コードの安全性を別の言葉で説明しましょう。「関数に入るすべての変数は有害です」。

現在、最も一般的に使用されている PHP コード監査テクノロジは、主にセキュリティの脆弱性につながる可能性のある危険な関数を探す静的分析です。一般的に使用されている検索ツール (grep、findstr など)。また、多くの自動ツールでは、これらの関数の検索に正規表現が使用されます。以下に挙げる辞書など、よく使われる関数をいくつか挙げておきます(今回は省略)。ただし、基本的に既存の辞書の抜け穴を見つけるのは難しいため、辞書を拡張する必要があります。これらの辞書もこの記事の主な焦点です。

その他の方法には、PHP ソース コードを変更して変数フローを分析する方法や、危険な関数をフックしてアプリケーション コードを監査する方法などがありますが、これらも上記の辞書に依存します。

PHP のバージョンとアプリケーション コードの監査

これまでのところ、PHP には php4、php5、php6 の 3 つの主要なバージョンがあり、使用率はおおよそ次のとおりです。

?

?

PHP には自動アップグレード メカニズムがないため、現在の PHP バージョンが共存しており、パッチが適用されていない多くの既存の脆弱性にもつながります。これらの脆弱な機能は、当社の WEB アプリケーション コード監査の焦点でもあり、当社の辞書の重要な情報源でもあります。

アプリケーション コード監査に関連するその他の要素

多くのコード監査人は、コードを取得した後にそのコードを調べるだけであり、コードのセキュリティは他の多くの要素と関連していることを無視しています。上記のような要素が挙げられます。 PHP のバージョンに関して、より重要なのは、オペレーティング システムのタイプ (主に 2 つの主要陣営が勝利/*nix)、WEB サーバー ソフトウェア (主に 2 つのタイプ) です。 iis/apache) などの要因。これは、システムや Web サーバーが異なれば、セキュリティ機能や特性も異なるためです。これについては、以下の一部で説明します。

したがって、企業の WEB アプリケーション コードを監査するときは、企業が使用しているシステム、WEB サーバー ソフトウェア、PHP のバージョン、その他の情報を把握する必要があります。

辞書を展開してください

以下では、いくつかの非伝統的な PHP アプリケーション コード監査に対するいくつかの脆弱性の種類と悪用テクニックを詳細に紹介します。

変数自体のキー

変数の送信というと、GET/POST/COOKIEなどで送信された変数の値しか見ていない人が多いですが忘れています。一部のプログラムでは、変数が処理のために関数に抽出されるときに、変数自体のキーも含まれます。

<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//key.php?aaaa'aaa=1&bb'b=2 </span><span class="pln"></span><span style="color: #880000;" class="com">//print_R($_GET); </span><span class="pln">?</span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET AS $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $key</span><span style="color: #666600;" class="pun">.</span><span style="color: #008800;" class="str">"\n"</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
ログイン後にコピー

上記のコードでは、変数自体のキーを抽出して表示します。上記のコードの場合、URL:

<span class="pln">key</span><span style="color: #666600;" class="pun">.</span><span class="pln">php</span><span style="color: #666600;" class="pun">?<</span><span class="pln">script</span><span style="color: #666600;" class="pun">></span><span class="pln">alert</span><span style="color: #666600;" class="pun">(</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">);</</span><span class="pln">script</span><span style="color: #666600;" class="pun">>=</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">&</span><span class="pln">bbb</span><span style="color: #666600;" class="pun">=</span><span style="color: #006666;" class="lit">2</span>
ログイン後にコピー

を送信すると、 xss の脆弱性。このキーが include() や SQL クエリなどの関数に送信された場合はどうなるでしょうか? :)

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:通读代码

?

变量覆盖

很多的漏洞查找者都知道extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指定函数可以导致变量覆盖,但是还有很多其他情况导致变量覆盖的如:

遍历初始化变量

请看如下代码:

<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//var.php?a=fuck</span><span class="pln">$a</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'hi'</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $$key </span><span style="color: #666600;" class="pun">=</span><span class="pln"> $value</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $a</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
ログイン後にコピー

很多的WEB应用都使用上面的方式(注意循环不一定是foreach),如Discuz!4.1的WAP部分的代码:

<span class="pln">$chs </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">''</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_POST </span><span style="color: #666600;" class="pun">&&</span><span class="pln"> $charset </span><span style="color: #666600;" class="pun">!=</span><span style="color: #008800;" class="str">'utf-8'</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $chs </span><span style="color: #666600;" class="pun">=</span><span style="color: #000088;" class="kwd">new</span><span style="color: #660066;" class="typ">Chinese</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'UTF-8'</span><span style="color: #666600;" class="pun">,</span><span class="pln"> $charset</span><span style="color: #666600;" class="pun">);</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_POST </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? ? ? ? ? $$key </span><span style="color: #666600;" class="pun">=</span><span class="pln"> $chs</span><span style="color: #666600;" class="pun">-></span><span style="color: #660066;" class="typ">Convert</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">);</span><span class="pln">? ? ? ? </span><span style="color: #666600;" class="pun">}</span><span class="pln">? ? ? ? unset</span><span style="color: #666600;" class="pun">(</span><span class="pln">$chs</span><span style="color: #666600;" class="pun">);</span>
ログイン後にコピー

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:通读代码

?

parse_str()变量覆盖漏洞

<span style="color: #880000;" class="com">//var.php?var=new</span><span class="pln">$var </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'init'</span><span style="color: #666600;" class="pun">;</span><span class="pln"> ? ? ? ? ? ? ? ? ? ? parse_str</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_SERVER</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'QUERY_STRING'</span><span style="color: #666600;" class="pun">]);</span><span class="pln"> </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $var</span><span style="color: #666600;" class="pun">;</span>
ログイン後にコピー

该函数一样可以覆盖数组变量,上面的代码是通过$_SERVER['QUERY_STRING']来提取变量的,对于指定了变量名的我们可以通过注射“=”来实现覆盖其他的变量:

<span style="color: #880000;" class="com">//var.php?var=1&a[1]=var1%3d222</span><span class="pln">$var1 </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'init'</span><span style="color: #666600;" class="pun">;</span><span class="pln">parse_str</span><span style="color: #666600;" class="pun">(</span><span class="pln">$a</span><span style="color: #666600;" class="pun">[</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'var'</span><span style="color: #666600;" class="pun">]]);</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $var1</span><span style="color: #666600;" class="pun">;</span>
ログイン後にコピー

上面的代码通过提交$var来实现对$var1的覆盖。

?

漏洞审计策略(parse_str)
PHP版本要求:无
系统要求:无
审计策略:查找字符parse_str

?

?

漏洞审计策略(mb_parse_str)
PHP版本要求:php4<4.4.7 php5<5.2.2
系统要求:无
审计策略:查找字符mb_parse_str

?

import_request_variables()变量覆盖漏洞

<span style="color: #880000;" class="com">//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1</span><span class="pln">echo </span><span style="color: #008800;" class="str">'GLOBALS '</span><span style="color: #666600;" class="pun">.(</span><span style="color: #000088;" class="kwd">int</span><span style="color: #666600;" class="pun">)</span><span class="pln">ini_get</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">"register_globals"</span><span style="color: #666600;" class="pun">).</span><span style="color: #008800;" class="str">"n"</span><span style="color: #666600;" class="pun">;</span><span class="pln">import_request_variables</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'GPC'</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_SERVER</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'REMOTE_ADDR'</span><span style="color: #666600;" class="pun">]</span><span style="color: #666600;" class="pun">!=</span><span style="color: #008800;" class="str">'10.1.1.1'</span><span style="color: #666600;" class="pun">)</span><span style="color: #000088;" class="kwd">die</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'Go away!'</span><span style="color: #666600;" class="pun">);</span><span class="pln">echo </span><span style="color: #008800;" class="str">'Hello admin!'</span><span style="color: #666600;" class="pun">;</span>
ログイン後にコピー

?

漏洞审计策略(import_request_variables)
PHP版本要求:php4<4.4.1 php5<5.2.2
系统要求:无
审计策略:查找字符import_request_variables

?

PHP5 Globals

从严格意义上来说这个不可以算是PHP的漏洞,只能算是一个特性,测试代码:

<span style="color: #666600;" class="pun"><?</span><span class="pln"></span><span style="color: #880000;" class="com">// register_globals =ON</span><span class="pln"></span><span style="color: #880000;" class="com">//foo.php?GLOBALS[foobar]=HELLO</span><span class="pln">php echo $foobar</span><span style="color: #666600;" class="pun">;</span><span class="pln"> </span><span style="color: #666600;" class="pun">?></span>
ログイン後にコピー

但是很多的程序没有考虑到这点,请看如下代码:

<span style="color: #880000;" class="com">//为了安全取消全局变量</span><span class="pln"></span><span style="color: #880000;" class="com">//var.php?GLOBALS[a]=aaaa&b=111</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">ini_get</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'register_globals'</span><span style="color: #666600;" class="pun">))</span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_REQUEST </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $k</span><span style="color: #666600;" class="pun">=></span><span class="pln">$v</span><span style="color: #666600;" class="pun">)</span><span class="pln"> unset</span><span style="color: #666600;" class="pun">(</span><span class="pln">$</span><span style="color: #666600;" class="pun">{</span><span class="pln">$k</span><span style="color: #666600;" class="pun">});</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $a</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $_GET</span><span style="color: #666600;" class="pun">[</span><span class="pln">b</span><span style="color: #666600;" class="pun">];</span>
ログイン後にコピー

如果熟悉WEB2.0的攻击的同学,很容易想到上面的代码我们可以利用这个特性进行crsf攻击。

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:通读代码

?

magic_quotes_gpc与代码安全

?

什么是magic_quotes_gpc

当打开时,所有的 '(单引号),"(双引号),\(反斜线)和 NULL 字符都会被自动加上一个反斜线进行转义。还有很多函数有类似的作用 如:addslashes()、mysql_escape_string()、mysql_real_escape_string()等,另外还有parse_str()后的变量也受magic_quotes_gpc的影响。目前大多数的主机都打开了这个选项,并且很多程序员也注意使用上面那些函数去过滤变量,这看上去很安全。很多漏洞查找者或者工具遇到些函数过滤后的变量直接就放弃,但是就在他们放弃的同时也放过很多致命的安全漏洞。 :)

哪些地方没有魔术引号的保护

1) $_SERVER变量

PHP5的$_SERVER变量缺少magic_quotes_gpc的保护,导致近年来X-Forwarded-For的漏洞猛暴,所以很多程序员考虑过滤X-Forwarded-For,但是其他的变量呢?

?

漏洞审计策略($_SERVER变量)
PHP版本要求:无
系统要求:无
审计策略:查找字符_SERVER

?

2) getenv()得到的变量(使用类似$_SERVER变量)

?

漏洞审计策略(getenv())
PHP版本要求:无
系统要求:无
审计策略:查找字符getenv

?

3) $HTTP_RAW_POST_DATA与PHP输入、输出流

主要应用与soap/xmlrpc/webpublish功能里,请看如下代码:

<span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span style="color: #666600;" class="pun">!</span><span class="pln">isset</span><span style="color: #666600;" class="pun">(</span><span class="pln"> $HTTP_RAW_POST_DATA </span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $HTTP_RAW_POST_DATA </span><span style="color: #666600;" class="pun">=</span><span class="pln"> file_get_contents</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'php://input'</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln"> isset</span><span style="color: #666600;" class="pun">(</span><span class="pln">$HTTP_RAW_POST_DATA</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">)</span><span class="pln">? ? ? ? $HTTP_RAW_POST_DATA </span><span style="color: #666600;" class="pun">=</span><span class="pln"> trim</span><span style="color: #666600;" class="pun">(</span><span class="pln">$HTTP_RAW_POST_DATA</span><span style="color: #666600;" class="pun">);</span>
ログイン後にコピー

?

漏洞审计策略(数据流)
PHP版本要求:无
系统要求:无
审计策略:查找字符HTTP_RAW_POST_DATA或者php://input

?

4) 数据库操作容易忘记'的地方如:in()/limit/order by/group by

如Discuz!<5.0的pm.php:

<span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">is_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgtobuddys</span><span style="color: #666600;" class="pun">))</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $msgto </span><span style="color: #666600;" class="pun">=</span><span class="pln"> array_merge</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgtobuddys</span><span style="color: #666600;" class="pun">,</span><span class="pln"> array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgtoid</span><span style="color: #666600;" class="pun">));</span><span class="pln">? ? ? ? ? ? ? ? </span><span style="color: #666600;" class="pun">......</span><span class="pln"></span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgto </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $uid</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $uids </span><span style="color: #666600;" class="pun">.=</span><span class="pln"> $comma</span><span style="color: #666600;" class="pun">.</span><span class="pln">$uid</span><span style="color: #666600;" class="pun">;</span><span class="pln">? ? ? ? $comma </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">','</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">......</span><span class="pln">$query </span><span style="color: #666600;" class="pun">=</span><span class="pln"> $db</span><span style="color: #666600;" class="pun">-></span><span class="pln">query</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">"SELECT m.username, mf.ignorepm FROM {$tablepre}members m? ? ? ? LEFT JOIN {$tablepre}memberfields mf USING(uid)? ? ? ? WHERE m.uid IN ($uids)"</span><span style="color: #666600;" class="pun">);</span>
ログイン後にコピー

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:查找数据库操作字符(select,update,insert等等)

?

变量的编码与解码

一个WEB程序很多功能的实现都需要变量的编码解码,而且就在这一转一解的传递过程中就悄悄的绕过你的过滤的安全防线。

这个类型的主要函数有:

1) stripslashes() 这个其实就是一个decode-addslashes()

2) 其他字符串转换函数:

?

base64_decode对使用 MIME base64 编码的数据进行解码
base64_encode使用 MIME base64 对数据进行编码
rawurldecode对已编码的 URL 字符串进行解码
rawurlencode按照 RFC 1738 对 URL 进行编码
urldecode解码已编码的 URL 字符串
urlencode编码 URL 字符串
......

?

另外一个 unserialize/serialize

3) 字符集函数(GKB,UTF7/8...)如iconv()/mb_convert_encoding()等

目前很多漏洞挖掘者开始注意这一类型的漏洞了,如典型的urldecode:

<span class="pln">$sql </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">"SELECT * FROM article WHERE articleid='"</span><span style="color: #666600;" class="pun">.</span><span class="pln">urldecode</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span class="pln">id</span><span style="color: #666600;" class="pun">]).</span><span style="color: #008800;" class="str">"'"</span><span style="color: #666600;" class="pun">;</span>
ログイン後にコピー

当magic_quotes_gpc=on时,我们提交?id=%2527,得到sql语句为:

<span class="pln">SELECT </span><span style="color: #666600;" class="pun">*</span><span class="pln"> FROM article WHERE articleid</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'''</span>
ログイン後にコピー

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:查找对应的编码函数

?

二次攻击

详细见附录[1]

1)数据库出来的变量没有进行过滤

2)数据库的转义符号:

  • mysql/oracle转义符号同样是\(我们提交'通过魔术引号变化为\',当我们update进入数据库时,通过转义变为')
  • mssql的转义字符为'(所以我们提交'通过魔术引号变化为\',mssql会把它当为一个字符串直接处理,所以魔术引号对于mssql的注射没有任何意义)

从这里我们可以思考得到一个结论:一切进入函数的变量都是有害的,另外利用二次攻击我们可以实现一个webrootkit,把我们的恶意构造直接放到数据库里。我们应当把这样的代码看成一个vul?

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:通读代码

?

魔术引号带来的新的安全问题

首先我们看下魔术引号的处理机制:

<span style="color: #666600;" class="pun">[\-->\\,</span><span style="color: #008800;" class="str">'-->\',"-->\",null-->\0]</span>
ログイン後にコピー

这给我们引进了一个非常有用的符号“\”,“\”符号不仅仅是转义符号,在WIN系统下也是目录转跳的符号。这个特点可能导致php应用程序里产生非常有意思的漏洞:

1)得到原字符(',\,",null])

<span class="pln">$order_sn</span><span style="color: #666600;" class="pun">=</span><span class="pln">substr</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'order_sn'</span><span style="color: #666600;" class="pun">],</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #880000;" class="com">//提交 ? ? ? ? ? ? ? ? '</span><span class="pln"></span><span style="color: #880000;" class="com">//魔术引号处理 ? ? ? ? \'</span><span class="pln"></span><span style="color: #880000;" class="com">//substr ? ? ? ? ? ? ? '</span><span class="pln">$sql </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">"SELECT order_id, order_status, shipping_status, pay_status, "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" shipping_time, shipping_id, invoice_no, user_id "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" FROM "</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $ecs</span><span style="color: #666600;" class="pun">-></span><span class="pln">table</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'order_info'</span><span style="color: #666600;" class="pun">).</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" WHERE order_sn = '$order_sn' LIMIT 1"</span><span style="color: #666600;" class="pun">;</span>
ログイン後にコピー

2)得到“\”字符

<span class="pln">$order_sn</span><span style="color: #666600;" class="pun">=</span><span class="pln">substr</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'order_sn'</span><span style="color: #666600;" class="pun">],</span><span style="color: #006666;" class="lit">0</span><span style="color: #666600;" class="pun">,</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #880000;" class="com">//提交 ? ? ? ? ? ? ? ? '</span><span class="pln"></span><span style="color: #880000;" class="com">//魔术引号处理 ? ? ? ? \'</span><span class="pln"></span><span style="color: #880000;" class="com">//substr ? ? ? ? ? ? ? \ ? ?</span><span class="pln">$sql </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">"SELECT order_id, order_status, shipping_status, pay_status, "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" shipping_time, shipping_id, invoice_no, user_id "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" FROM "</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $ecs</span><span style="color: #666600;" class="pun">-></span><span class="pln">table</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'order_info'</span><span style="color: #666600;" class="pun">).</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" WHERE order_sn = '$order_sn' and order_tn='"</span><span style="color: #666600;" class="pun">.</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'order_tn'</span><span style="color: #666600;" class="pun">].</span><span style="color: #008800;" class="str">"'"</span><span style="color: #666600;" class="pun">;</span>
ログイン後にコピー

提交内容:

<span style="color: #666600;" class="pun">?</span><span class="pln">order_sn</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'&order_tn=%20and%201=1/* </span>
ログイン後にコピー

执行的SQL语句为:

<span class="pln">SELECT order_id</span><span style="color: #666600;" class="pun">,</span><span class="pln"> order_status</span><span style="color: #666600;" class="pun">,</span><span class="pln"> shipping_status</span><span style="color: #666600;" class="pun">,</span><span class="pln"> pay_status</span><span style="color: #666600;" class="pun">,</span><span class="pln"> shipping_time</span><span style="color: #666600;" class="pun">,</span><span class="pln"> shipping_id</span><span style="color: #666600;" class="pun">,</span><span class="pln"> invoice_no</span><span style="color: #666600;" class="pun">,</span><span class="pln"> user_id FROM order_info WHERE order_sn </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'\' and order_tn='</span><span style="color: #000088;" class="kwd">and</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">=</span><span style="color: #006666;" class="lit">1</span><span style="color: #880000;" class="com">/*'</span>
ログイン後にコピー

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:查找字符串处理函数如substr或者通读代码

?

变量key与魔术引号

我们最在这一节的开头就提到了变量key,PHP的魔术引号对它有什么影响呢?

<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//key.php?aaaa'aaa=1&bb'b=2 </span><span class="pln"></span><span style="color: #880000;" class="com">//print_R($_GET); </span><span class="pln">?</span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET AS $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span class="pln">? ? ? ? </span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $key</span><span style="color: #666600;" class="pun">.</span><span style="color: #008800;" class="str">"\n"</span><span style="color: #666600;" class="pun">;</span><span class="pln">? ? ? ? </span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
ログイン後にコピー

1)当magic_quotes_gpc = On时,在php5.24下测试显示:

<span class="pln">aaaa</span><span style="color: #666600;" class="pun">\</span><span style="color: #008800;" class="str">'aaabb\'b</span>
ログイン後にコピー

从上面结果可以看出来,在设置了magic_quotes_gpc = On下,变量key受魔术引号影响。但是在php4和php<5.2.1的版本中,不处理数组第一维变量的key,测试代码如下:

<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//key.php?aaaa'aaa[bb']=1 </span><span class="pln">print_R</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">);</span><span class="pln"> </span><span style="color: #666600;" class="pun">?></span>
ログイン後にコピー

结果显示:

<span style="color: #660066;" class="typ">Array</span><span style="color: #666600;" class="pun">(</span><span style="color: #666600;" class="pun">[</span><span class="pln">aaaa</span><span style="color: #008800;" class="str">'aaa] => Array ( [bb\'] => 1 ) ) </span>
ログイン後にコピー

数组第一维变量的key不受魔术引号的影响。

?

漏洞审计策略
PHP版本要求:php4和php<5.2.1
系统要求:无
审计策略:通读代码

?

2)当magic_quotes_gpc = Off时,在php5.24下测试显示:

<span class="pln">aaaa</span><span style="color: #008800;" class="str">'aaabb'</span><span class="pln">b</span>
ログイン後にコピー

对于magic_quotes_gpc = Off时所有的变量都是不安全的,考虑到这个,很多程序都通过addslashes等函数来实现魔术引号对变量的过滤,示例代码如下:

<span style="color: #666600;" class="pun"><?</span><span class="pln">php </span><span style="color: #880000;" class="com">//keyvul.php?aaa'aa=1'</span><span class="pln"></span><span style="color: #880000;" class="com">//magic_quotes_gpc = Off</span><span class="pln">?</span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(!</span><span class="pln">get_magic_quotes_gpc</span><span style="color: #666600;" class="pun">())</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">?$_GET ?</span><span style="color: #666600;" class="pun">=</span><span class="pln"> addslashes_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #000088;" class="kwd">function</span><span class="pln"> addslashes_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">)</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">return</span><span class="pln"> is_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">?</span><span class="pln"> array_map</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'addslashes_array'</span><span style="color: #666600;" class="pun">,</span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">:</span><span class="pln"> addslashes</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln">print_R</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET AS $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $key</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
ログイン後にコピー

以上的代码看上去很完美,但是他这个代码里addslashes($value)只处理了变量的具体的值,但是没有处理变量本身的key,上面的代码显示结果如下:

<span style="color: #660066;" class="typ">Array</span><span class="pln"></span><span style="color: #666600;" class="pun">(</span><span class="pln">? ? </span><span style="color: #666600;" class="pun">[</span><span class="pln">aaa</span><span style="color: #008800;" class="str">'aa] => 1\')aaa'</span><span class="pln">aa</span>
ログイン後にコピー

?

漏洞审计策略
PHP版本要求:无
系统要求:无
审计策略:通读代码

?

代码注射

PHP中可能导致代码注射的函数

很多人都知道eval、preg_replace+/e可以执行代码,但是不知道php还有很多的函数可以执行代码如:

?

assert()
call_user_func()
call_user_func_array()
create_function()
变量函数
...

?

ここでは、create_function() コード実行の脆弱性に関して最近出現したいくつかのコードを見てみましょう:

<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//このコードの解釈方法</span><span class="pln">$sort_by</span><span style="color: #666600;" class="pun">=</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'sort_by ' </span><span style="color: #666600;" class="pun">];</span><span class="pln">$sorter</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'strnatcasecmp'</span><span style="color: #666600;" class="pun">;</span><span class="pln">$databases</span> <span style="color: #666600;" class="pun">=</span><span class="pln">array</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'テスト'</span><span style="color: #666600;" class="pun">,</span><span style="color: #008800;" class="str">'テスト'</span><span style="color: #666600;" class="pun"> ) ;</span><span class="pln">$sort_function </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">' ?return 1 * '</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $sorter </span><span style="color: #666600;" class="pun"> .</span><span style="color: #008800;" class="str">'($a["'</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $sort_by </span><span style="color: #666600;" class="pun">.</span><span style="color: #008800;" class="str">'"], $b[" ' </span><span style="color: #666600;" class="pun">.</span><span class="pln"> $sort_by </span><span style="color: #666600;" class="pun">.</span>
ログイン後にコピー
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? Apr 03, 2025 am 12:03 AM

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。

PHPとPython:2つの一般的なプログラミング言語を比較します PHPとPython:2つの一般的なプログラミング言語を比較します Apr 14, 2025 am 12:13 AM

PHPとPythonにはそれぞれ独自の利点があり、プロジェクトの要件に従って選択します。 1.PHPは、特にWebサイトの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンス、機械学習、人工知能に適しており、簡潔な構文を備えており、初心者に適しています。

See all articles