最近、PRNGの脆弱性について、基礎([1])からさまざまなプログラミング言語の脆弱性まで、またそれらに基づいてCMSやその他のソフトウェア([2]、[3]、[4] )
PRNGはWebアプリケーションセキュリティの多くの側面の基盤であるため、これらの出版物は人気があります。 擬似乱数/文字シーケンスは、以下のWebアプリケーションを保護するために使用されます。
- さまざまなトークンの生成(CSRF、パスワードリセットトークンなど);
- ランダムパスワード生成;
- CAPTCHAでのテキスト生成。
- セッション識別子の生成。
George ArgyrosとAggelos Kiayias ([3])の研究に基づく以前の記事では 、 PHPSESSIDに基づいてPHPの乱数を予測し、さまざまな方法で擬似乱数のエントロピーを減らすことを学びました。
Pythonで開発されたWebアプリケーションのPRNGを見てみましょう。
Python PRNG機能
Pythonには、ランダム/擬似乱数を生成するように設計された3つのモジュールがあります: random 、 urandomおよび_random :
- _randomは、C言語に若干の変更を加えたMersenne Twister (MT)アルゴリズム( [6]、[7] )を実装しています。
- urandomは、C言語でエントロピーの外部ソース(CryptGenRandom関数のWindows暗号化プロバイダー)を使用します。
- randomは、Pythonの_randomモジュールのラッパーであり、両方のライブラリを組み合わせて、擬似乱数を生成するための2つの主要な関数:random()およびSystemRandom()を備えています。
ランダム()
最初はMTアルゴリズム( _randomモジュール)を使用しますが、まず最初にurandomから取得したSEEDを使用して初期化を試み、PRNGをRNG(乱数ジェネレーター)に変換します。 urandomを呼び出せない場合(たとえば、 / dev / urandomが見つからない場合、またはadvapi32.dllライブラリから目的の関数を呼び出せない場合)、 int(time.time()* 256)が SEEDとして使用されます(既にご存じのとおり、エントロピーが不十分)。
システムランダム()
SystemRandom()は、外部ソースを使用してランダムデータを生成するurandomモジュールを呼び出します。
MTアルゴリズムの実装の変更点は、PRNG 状態の現在の状態からの624の番号の1つに基づく1つの番号の代わりに、2つの番号が使用されることです。
random_random() { unsigned long a=genrand_int32(self)>>5, b=genrand_int32(self)>>6; return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0)); }
また、PHPとは異なり、ジェネレーターは長い変数だけでなく、任意のバイトシーケンス( init_by_array()が呼び出されます)を使用して初期化できます。これは、エントロピーの外部ソースを使用してランダムモジュールをインポートするときに発生します(32バイトが取得されます) urandomから)、これが失敗した場合、 時間()が使用されます:
if a is None: try: a = int.from_bytes(_urandom(32), 'big') except NotImplementedError: import time a = int(time.time() * 256)
保護
これらの変更は、PHPとは異なり、 random.random()を呼び出した場合でも十分なジェネレーターエントロピーを提供するようです。 しかし、すべてが「悪い」わけではありません。
Pythonフレームワークの機能は、PHPとは異なり、PythonがWebサーバーで1回実行されることです。つまり、 import randomコマンドが実行されるか、 random.seed()が強制されると、デフォルト状態の初期化が1回発生しますWebアプリケーションのまれなケース)、次のアルゴリズムを使用してMT状態への攻撃を許可します。
- 値random.random()を表示するスクリプトを見つけます(たとえば、Ploneでこれはエラーロガー(ファイルSiteErrorLog.py )によって行われ、ページに表示される「 番号***固定のエラー 」、乱数が表示されます)。
- 乱数を修正する一連のクエリを順番に実行します。 リクエスト番号: 1,2,199,200,511,625 ;
- 313番目のリクエストまでに、予測可能なアクション(パスワードリセットリンクの生成など)を行います。
- クエリ1,199に基づいて、状態state_1 [1]、state_1 [2]、state_1 [397]を決定します。
- 2,200件のクエリに基づく-state_1 [3]、state_1 [398] ;
- リクエスト511 - state_2 [397]に基づきます。
- リクエスト625 - state_3 [1]に基づきます。
状態を決定する精度は、状態要素( i )のインデックスに依存します。imod 2 = 0の場合、エントロピーは2 ^ 6 、 i mod 2 = 1-2 ^ 5の場合です。
次に、クエリ1,2,199,200を使用して、状態state_1 [1] 、 state_1 [2] 、 state_1 [3] 、 state_1 [397] 、 state_1 [398]を決定し 、それに基づいて状態state_2 [1]およびstate_2 [2]を生成し、リクエスト番号313の乱数が取得されます。 ただし、この数のエントロピーは2 ^ 24(16M)です。 エントロピーは、クエリ511および625を使用して削減されます。 これらのクエリは、 state_2 [397] 、 state_3 [1]の計算に役立ちます。 これにより、状態オプションの数が2 ^ 8に減少します。 クエリNo. 313で使用される「乱数」の合計256のバリアントがあります。
攻撃の前提条件は、クエリプロセスに干渉しないことです。これにより、PRNGの状態に影響します(つまり、状態インデックスが正しく決定される)。 また、リクエストNo. 1はインデックスが224以下のPRNGの状態要素を使用する必要があります。そうでない場合、リクエストNo. 200はアルゴリズムの実行を許可しないジェネレータの異なる状態を使用します。 このイベントの確率は36%です。
したがって、リクエストNo. 625の追加タスクは、以前のすべてのリクエストが実際に必要な状態で行われ、リクエストプロセスに誰も参加していないことを判断することです。
さらに、6つのリクエストの乱数を受け取るスクリプトに注目します。 出力では、リクエスト番号313のすべての可能な乱数が生成されます。
実用化
いくつかのPythonフレームワークとWebアプリケーション(特にPloneとDjango)を分析しました。 残念ながら、(そしておそらく幸いなことに)それらの間で脆弱性を見つけることはできませんでした。
最も可能性の高い候補はPloneで、これは乱数出力( SiteErrorLog.py )を持っていますが、攻撃の問題は次のとおりです。 PloneはPython 2.7で動作します。*は 、 floatが str()に出力されると、最後の5桁を切り捨て、反復オプションの数(ローカル列挙とサーバーへの外部要求の両方)を非常に大きな数に拡張します。
3番目のブランチのPythonは、 st()r関数のフロートをカットしません。この関数は、そのアプリケーションを攻撃の主な候補にします。
入力で6つの乱数を受け取るスクリプト (テストスクリプトvuln.pyなどから必要なインデックスを使用して状態によって初期化されます)に注目し、出力で選択した乱数の可能なバリアントを生成します。 このシナリオの平均的なコンピューターでの実行時間は約1時間です。
注:このシナリオでは、(i mod 2 = 1)の状態要素を決定する際に発生する可能性のあるエラーは考慮されないため、効率は36%から18%に低下します。
おわりに
(Webサーバー側での)Pythonフレームワークコードの実行の特性により、攻撃者はPHP言語で実装することが不可能または非常に困難な攻撃を実行できます。 PRNGを保護するには、単純なルールに従う必要があります。
- urandomモジュールまたはrandom.SystemRandom()関数を使用します。
- 十分なSEEDエントロピーでrandom.random()を呼び出す前にrandom.seed()で初期化する( urandomモジュールが利用できない場合は、たとえば関数md5(time.time()*(int)salt1 + str(salt2 )) 、ここでsalt1とsalt2は Webアプリケーションのインストール中に初期化されます);
- Webアプリケーションでの乱数の出力を制限します( md5などのハッシュ関数を使用します)。
参照資料
[1] http://habrahabr.ru/post/151187/
[2] http://jazzy.id.au/default/2010/09/20/cracking_random_number_generators_part_1.html
[3] http://crypto.di.uoa.gr/CRYPTO.SEC/Randomness_Attacks_files/paper.pdf
[4] http://www.slideshare.net/d0znpp/dcg7812-cryptographyinwebapps-14052863
[5] http://media.blackhat.com/bh-us-10/presentations/Kamkar/BlackHat-USA-2010-Kamkar-How-I-Met-Your-Girlfriend-slides.pdf
[6] http://en.wikipedia.org/wiki/Mersenne_twister
[7] http://jazzy.id.au/default/2010/09/22/cracking_random_number_generators_part_3.html
著者:ユヌソフ・ティムール。