5

一般的な質問は次のとおりです: PHP で変数が設定解除された後、文字列変数の値を物理メモリから削除することは可能ですか?

この問題は、セキュリティ標準の特定の要件から発生しました (特定の重要なデータの処理中にメモリからディスクにデータをダンプする方法はありません)。「メモリは暗号化されていますか? 」トピックによると、メモリ内のデータを暗号化する良い方法はありません。

そのため、PHP で文字列変数の設定を解除すると、メモリ内のデータが上書きされたとは言えません。変数に新しい値を設定することについての同じ話。

unsetしたがって、メソッドのコアコードを変更せずにメモリから変数値を消去できるかどうかに興味がありますか?

4

3 に答える 3

5

まず第一に、文字列がとにかく消去される前に理論的にはメモリをダンプできるため、文字列を消去することがあなたが説明したセキュリティ要件を満たすかどうかはわかりません。しかし、データをメモリに保持しないとデータを処理できないため、とにかくそれを満たすことは不可能です。

とにかく、文字列を確実に消去したい場合、PHP でこれを行う唯一の方法は、文字列をループして各文字を変更することだと思います: メモリの内容は上書きされるまで消えません。変数への参照がなく、PHP GC が実行されました。

私はこれがうまくいくと信じています:

for( $i=0; $i < strlen($str); $i++ )
    $str[$i] = 'x';
于 2012-04-10T12:48:59.797 に答える
0

tl;dr:多くの組み合わせを徹底的にテストした後、for各文字を上書きするループがメモリ内の文字列の内容をクリア/変更しているようです。最初の内容がどこから来るのか注意してください。それらの変数にまだ存在している可能性があります! 以下の更新を参照してください。

PHP 5.6でいくつかのテストを行いました:

<?php
     $cc = 'AAAABBBBCCCCDDDD';
     #v1:  unset($cc);
     #v2:  $cc=null;
     #v3:  for( $i=0; $i < strlen($cc); $i++ ) $cc[$i] = 'x';
     sleep(500); // enough time for taking script pid and run the memory dump
?>

上記のスクリプトの各バージョンを試しました (#v1 有効、#v2 有効、#v3 有効)。プロセスのメモリをダンプし ( https://serverfault.com/a/408929/374467を参照)、生成されたバイナリ ファイル (プロセス メモリを含む) に「AAAABBBBCCCCDDDD」文字列が常に表示されます。$cc 値がコマンド ライン引数 ($argv) として送信された場合にもテストされます。同じ結果です。

これまでのところ、PHP でこれを行う信頼できる方法は見つかりませんでした。

アップデート

コメントで示唆されているように、文字列リテラルを使用して変数を初期化すると、リテラルがメモリに保持される可能性があるため、結果に影響を与える可能性があります。したがって、スクリプトを変更して、cli から引数を取り、それに適用して変数を初期化し、変数の内容がnewstr_rot13()であることを確認します。また、ガベージ コレクションを強制するように追加しました。したがって、テスト スクリプトは次のようになります。gc_collect_cycles()

<?php
     $cc = str_rot13($argv[1]);
     #v1:  unset($cc);
     #v2:  $cc=null;
     #v3:  for( $i=0; $i < strlen($cc); $i++ ) $cc[$i] = 'x';
     gc_collect_cycles();
     sleep(120); // enough time for taking script pid and run the memory dump
     echo "done \n";
?>

最初の 2 つのメソッド (unset/null) はメモリからの新しい値をクリアしないよう$ccです (gc_collect_cycles をオンにしても)が、実際にforループによって値が変更されます! gc_collect_cycles が使用されているかどうかに関係なく。

PHP 7.2.20 (cli) でテスト済み。

注意引数の初期値 ($argv) はメモリ内にまだあります!

于 2016-11-18T15:10:12.810 に答える
-2

私が理解している限り、問題はunset()PHP のガベージ コレクターを使用することではなく、使用されているメモリが実際に物理レベルでクリアされていることを確認することですか?

簡単な方法 - 設定を解除するに null (またはその他の値)に設定するだけです。

困難で賢明な方法は、すべてのphpメモリをガベージで割り当てて上書きすることですが、仮想メモリが事前定義されたdiapasonに固定されているか、プロセスのニーズに基づいて変更されているかはわかりません。

于 2012-04-10T12:38:14.020 に答える