ホームページ >php教程 >php手册 >PHP の「==」演算子のセキュリティ問題

PHP の「==」演算子のセキュリティ問題

大家讲道理
大家讲道理オリジナル
2016-11-12 10:28:271159ブラウズ
はじめに

PHP は一般的なオープンソースのスクリプト言語であり、その構文は C、Java、Perl などの優れた言語の構文を混合しています。さらに、開発者が使用できる多数の関数ライブラリも提供します。ただし、PHP は不適切に使用すると、アプリケーションに非常に大きなセキュリティ リスクをもたらす可能性があります。

この記事では、PHP アプリケーションでよく発生するいくつかの問題、特に「== (比較演算子) を使用して文字列比較を実行する場合に、セキュリティ上の問題が発生する可能性がある」について詳しく分析します。このトピックについては最近多くの記事で議論されていますが、私はこの問題を利用してターゲットに侵入し、攻撃する方法を「ブラック ボックス テスト」の観点から議論することにしました。まず、この問題の根本原因を分析して、その動作メカニズムをより深く理解し、このセキュリティ問題を可能な限り回避できるようにします。

問題の説明

2011 年、PHP 公式バグ追跡システムは、文字列と数値を比較するとプログラムで非常に奇妙な現象が発生することを発見しました。セキュリティの観点から見ると、この問題は実際にはセキュリティ上の問題ではありません。たとえば、次のコードを見ることができます:

PHP の「==」演算子のセキュリティ問題

実際、この状況は、「==」などの比較演算子を使用して操作するときに発生します。上記例の問題は、PHPが提供する「型変換」と呼ばれる機能であるため、脆弱性とはみなされません。基本的に、特定の比較演算子 (==、!=、 など) を使用して操作する場合、PHP はまず比較に関与するデータ型を決定しようとします。ただし、このような型変換メカニズムにより、計算結果が予期した結果と大きく異なる可能性があり、非常に深刻なセキュリティ問題が発生する可能性もあります。セキュリティ研究の専門家は、この問題に関する完全な開示レポートで、「この型変換メカニズムは権限昇格につながり、プログラムのパスワード検証プロセスが安全でなくなる可能性さえある」と書いています。

Gynvael は、このトピックに関する古典的な記事を書きました。PHP の等号演算子「==」でカバーされるデータ型は非常に広範囲にわたり、比較的完全な比較参照リストといくつかの例を提供します。具体的な内容は次のとおりです。 :

PHP の「==」演算子のセキュリティ問題

ご覧のとおり、「==」を使用してこれらの数値文字列を比較する場合、安全性を考慮して、比較に関係するのは文字列内の数値の実際のサイズです。この観点から、これは次のようになります。とても興味深い質問です。この場合、科学的記数法を使用して数値を表し、それを文字列に入れると、PHP は自動的にそれを数値型として扱います。このような出力タイプが得られる理由は、PHP が処理にハッシュ アルゴリズム (通常は 16 進値で表される) を使用するためです。たとえば、数値が 0 の場合、PHP は疎比較中にその型を自動的に変換しますが、その値は常に 0 になります。特定のハッシュ アルゴリズムでは、パスワードが置き換え可能になる場合があります。たとえば、パスワード ハッシュを科学的表記法を使用して数値に変換すると、他のパスワード ハッシュと一致する可能性があります。このようにして、まったく異なるパスワードでもシステムの検証に合格する可能性があります。しかし、興味深いのは、科学的表記法で表現された特定の数値を比較すると、その結果に驚くかもしれないということです:

PHP の「==」演算子のセキュリティ問題

この問題を「ブラック ボックス テスト」の観点から考えてみましょう

静的分析の観点から見ると、これらのセキュリティ問題は少し普通のことのように見えます。しかし、これらの問題をブラック ボックスの観点から見ると、アプリケーションが最も一般的なハッシュ アルゴリズム (SHA1 や MD5 など) を使用してパスワードを処理している場合、アプリケーション内のユーザー アカウントについてどのような洞察が得られるでしょうか? PHP ではパスワード ハッシュを検証するときに比較が緩いため、この時点でセキュリティ上の問題が発生する可能性があります。ここで、一般的な侵入テストを考えてみましょう。通常のアカウントを作成し、類似したハッシュ値を持つパスワードの 1 つにパスワードを設定し、もう 1 つのパスワードを使用してログインできます。明らかに、システムのセキュリティは、使用するハッシュ アルゴリズムに完全に依存します。したがって、ハッシュ アルゴリズムで「Salt」値を使用していないと仮定すると、パスワードには少なくとも 2 つの異なるハッシュ アルゴリズムを使用する必要があります。

さて、これらのパスワードの組み合わせを検討する前に、パスワード要件についても考慮する必要があります。これらのパスワードとハッシュ アルゴリズムを分析する前に、まず設定した初期パスワードがパスワードの複雑さの要件を満たしていることを確認する必要があります。そうしないと、分析と調査が無意味になってしまいます。したがって、パスワードが少なくとも 8 文字の長さであり、大文字と小文字、数字、および少なくとも 1 つの特殊文字が含まれていることを確認する必要があります。 詳細は次のとおりです。
import random
import hashlib
import re
import string
import sys
prof = re.compile("^0+ed*$") # you can also consider: re.compile("^d*e0+$")
prefix = string.lower(sys.argv[1])+'!'+string.upper(sys.argv[1])+"%s"
num=0
while True:
    num+=1
    b = hashlib.sha256(prefix % num).hexdigest()
    if (b[0]=='0' and prof.match(b)):
        print(prefix+str(num),b)
このために、私は特別に Python スクリプトを作成しました。このスクリプトのパフォーマンスを最適化するための努力はまったく行われていませんが、PyPy コンパイラーの助けにより、このよく書かれたスクリプトは、AMD FX8350 の使用可能なすべての CPU コアで安定して実行されます。さらに、hashlib ライブラリのハッシュ関数も使用し、Python GIL のプロセス同期の問題を回避するために、パスワード データを処理するための独立したプロセスも生成しました。それだけでなく、上記のコードに示すように、非常に洗練された手法を使用して、パスワードごとに異なるプレフィックスを生成しました。
分析結果

1時間以上の分析の後、4つのパスワードのSHA1値が得られました。驚いたことに、4 つのパスワードの MD5 値を取得するのにかかる時間は短縮されました。

以下に示すように、パスワードの計算結果は非常に似ています。

PHP の「==」演算子のセキュリティ問題

比較のために 2 つのパスワードをランダムに選択できます。 比較のデモンストレーション結果は次のとおりです。

PHP の「==」演算子のセキュリティ問題

次のようなパスワードを取得できない場合。上に示した結果を計算してみると、幸運だと感じるはずです。ユーザー名とパスワードを一緒にバンドルし、「ソルト」値を含むハッシュ アルゴリズムを使用して計算してみてください。これを実現するには、コードの一部を変更するだけで済みます。変更されたスクリプトを入手するには、「ここ」をクリックしてください。
解決策

PHP は解決策を提供します。ハッシュ値を比較したい場合は、password_verify() 関数または hash_equals() 関数を使用する必要があります。データの厳密な比較を実行し、他の干渉要因を排除します。ただし、 hash_equals() 関数は文字列比較にも使用できることに注意してください。
分析の結論

分析手順は実行するには少し複雑すぎますが、ブラック ボックス テストの観点から、説明した方法は貴重な情報を提供できる可能性があります。アプリケーションのパスワードでそのような検証メカニズムが使用されている場合、それがもたらすセキュリティ上の問題は、PHP データ型変換自体の問題を超えたものになります。
問題はそれをはるかに超えています

この問題が私たちに与える影響はそれをはるかに超えています。攻撃者はこれらのパスワードを辞書ファイルに追加し、アプリケーション内のすべてのユーザーに対してブルート フォース攻撃を実行できます。さらに、アプリケーションのパスワード回復メカニズムに安全でない要素がある場合、攻撃者は攻撃が成功するまでターゲット アカウントに対して無制限の攻撃を行う可能性があります。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。