3

クラスに変数を復号化して返すメソッドがあります。使用後、返された変数を「del」で削除します。

これらのガベージ値がアクセスされることの危険性は何ですか...どうすればそれらから身を守ることができますか?

コードは次のとおりです。

import decrypter
import gc

# mangled variable names used
def decrypt(__var):
    __cleartext = decrypter.removeencryption(__var)
    return __cleartext

__p_var = "<512 encrypted password text>"
__p_cleartext = decrypt(__p_var)
<....do login with __p_cleartext...>
del  __p_var, __p_cleartext
gc.collect()

この時点で、__var や __cleartext などの変数が悪用される可能性はありますか?

ありがとう!


私はもう少しグーグルをしました。間違った道をたどる数時間を費やす前に...私が聞いているのは次のとおりです。

  1. パスワードをソルト付きハッシュとしてシステムに保存します (これは現在実行中です)。
  2. ハッシュのソルトは、スイートの開始時にユーザーが入力する必要があります (現在行われています)。
  3. ただし、salt は Python ではなく C プロセスで保持する必要があります。
  4. Python スクリプトは、復号化のためにハッシュを C プロセスに渡す必要があります。

Python スクリプトは mysql データベースのログインを処理しており、DB 接続を開くにはパスワードが必要です。

コードが次の行に沿っていた場合...

# MySQLdb.connect(host, user, password, database)
mysql_host = 'localhost'
mysql_db = 'myFunDatabase'
hashed_user = '\xghjd\xhjiw\xhjiw\x783\xjkgd6\xcdw8'
hashed_password = 'ghjkde\xhu78\x8y9tyk\x89g\x5de56x\xhyu8'
db = MySQLdb.connect(mysql_host, <call_c(hashed_user)>, <call_c(hashed_password)>, mysql_db])  

これは(少なくとも)ゴミがいたるところに残っているpythonの問題を解決しますか?


Ps memset ( Mark data assensitive in python ) に関する投稿も見つけましたが、C を使用してハッシュを復号化する場合、これは役に立ちません。

PPS dycrypter は現在 Python スクリプトです。スクリプトに memset を追加してから、py2exe または pyinstaller を使用して「コンパイル」するとしたら、これは実際にパスワードを保護するのに役立ちますか? pyinstaller が行うことは、通常のインタープリターとローカル インタープリターが作成する同じバイトコードをパッケージ化することだけなので、私の本能はノーと言います...しかし、私はそれについて十分に知りません...?


それで...暗号化モジュールをCで作成するというAyaの提案に従って、次のセットアップでどれだけの識別可能なメモリフットプリントが残るでしょうか。大きな問題の一部は次のとおりです。パスワードを解読する機能は、繰り返し呼び出されるため、プログラムの実行中ずっと利用可能である必要があります...これは1回限りのものではありません.

ユーザーがログインしたときに開始される C オブジェクトを作成します。これには復号化ルーチンが含まれており、ログイン時にユーザーが入力したソルトのコピーを保持します。保存されたソルトは、ランダムに生成されたソルトを使用して独自の暗号化ルーチンによってハッシュされることにより、実行中のオブジェクト (メモリ内) で隠されます。

ランダムに生成されたソルトも、オブジェクトの変数に保持する必要があります。これは実際にはソルトを保護するためではなく、誰かがメモリ フットプリントをのぞき見した場合にメモリ フットプリントを難読化しようとするためです (ソルトを特定しにくくします)。つまり、c-obj

mlock() /*to keep the code memory resident (no swap)*/

char encrypt(data, salt){ 
    (...) 
    return encrypted_data
}

char decrypt(data, salt){ 
    (...) 
    return decrypted_data
}

stream_callback(stream_data){
    return decrypt(stream_data, decrypt(s-gdhen, jhgtdyuwj))
}

void main{ 
    char jhgtdyuwj=rand();
    s-gdhen = encrypt(<raw_user_input>, jhgtdyuwj);
}

次に、Python スクリプトは C オブジェクトを直接呼び出します。これにより、暗号化されていない結果が直接 MySQLdb 呼び出しに渡され、変数に戻り値が格納されることはありません。いえ

#!/usr/bin/python
encrypted_username = 'feh9876\xhu378\x&457(oy\x'
encrypted_password = 'dee\x\xhuie\xhjfirihy\x^\xhjfkekl'
# MySQLdb.connect(host, username, password, database)
db = MySQLdb.connect(self.mysql_host,
                     c-obj.stream_callabck(encrypted_username),
                     c-obj.stream_callback(encrypted_password),
                     self.mysql_database)

これにより、スヌープされる可能性のあるメモリフットプリントはどのようなものになるでしょうか?

4

3 に答える 3

3

値への他の参照が存在しない場合、gc.collectは通常、オブジェクトを破棄します。

ただし、文字列のインターンやキャッシュなどの単純な処理によって、予期しない参照が保持され、値がメモリ内に残ったままになる場合があります。Python には、内部でさまざまなことを行う多数の実装 (PyPy、Jython、PyPy) があります。言語自体は、値が実際にメモリから消去されるかどうか、またはいつ消去されるかについてほとんど保証しません。

あなたの例では、名前マングリングも使用しています。マングリングは手で簡単に再現できるため、セキュリティはまったく追加されません。

もう 1 つの考え: セキュリティ モデルが何であるかが明確ではありません。攻撃者が復号化関数を呼び出して同じプロセスで任意のコードを実行できる場合、入力と出力のコードを保持するために復号化をラップすることを防ぐものは何ですか。

于 2013-05-27T16:47:29.740 に答える
3

gc.collect を呼び出してこれらの文字列の割り当てを解除しても、メモリ内に残っている可能性があります。また、文字列は不変です。つまり、文字列を上書きする (標準的な) 方法はありません。また、これらの文字列に対して操作を実行した場合、それらのコピーがいくつか転がっている可能性があることに注意してください。

そのため、可能であれば文字列を使用しないでください。

メモリを上書きする必要があります (それでも、メモリはページ ファイルなどのどこかにダンプされる可能性があります)。バイト配列を使用し、完了したらメモリを上書きします。

于 2013-05-27T16:54:37.677 に答える
2

セキュリティ システムは、その最も弱いリンクと同程度の強度しかありません。

全体的なアーキテクチャの詳細を実際に提供していないため、現在のシステムで最も弱いリンクが何であるかを判断するのは困難ですが、質問に投稿したような Python コードを実際に使用している場合 (これを と呼びましょうmyscript.py)。 .

#!/usr/bin/python
encrypted_username = 'feh9876\xhu378\x&457(oy\x'
encrypted_password = 'dee\x\xhuie\xhjfirihy\x^\xhjfkekl'
# MySQLdb.connect(host, username, password, database)
db = MySQLdb.connect(self.mysql_host,
                     c-obj.stream_callabck(encrypted_username),
                     c-obj.stream_callback(encrypted_password),
                     self.mysql_database)

...そして、パスワードを解読する方法や場所に関係なく、どのユーザーも一緒に来て、このようなスクリプトを実行できます...

import MySQLdb

def my_connect(*args, **kwargs):
    print args, kwargs
    return MySQLdb.real_connect(*args, **kwargs)

MySQLdb.real_connect = MySQLdb.connect
MySQLdb.connect = my_connect
execfile('/path/to/myscript.py')

...プレーンテキストのパスワードが出力されるため、C で復号化を実装することは、正面玄関に 10 個のデッドボルトを配置し、窓を大きく開けたままにしておくようなものです。

システムを保護する方法について適切な回答が必要な場合は、アーキテクチャ全体と、防止しようとしている攻撃ベクトルに関する詳細情報を提供する必要があります。

誰かが root のハッキングに成功した場合、あなたはかなり困惑していますが、root 以外のユーザーからパスワードを隠すためのより良い方法です。

ただし、このコードを実行しているマシンが安全であることに満足している場合 (「権限のない」ユーザーがアクセスできないという意味で)、このパスワードの難読化は必要ありません。同様に、クリアテキストのパスワードを Python ソース コードに直接入力するだけです。


アップデート

アーキテクチャに関しては、いくつの個別のサーバーを実行しているか、それらにはどのような責任があり、どのように相互に、および/または外の世界と通信することを意味していますか?

主な目的が MySQL サーバーへの不正アクセスを防止することであり、MySQL が Python スクリプトとは別のサーバーで実行されていると仮定すると、Python スクリプトを実行しているサーバーに誰かがアクセスしてパスワードを取得することを心配する必要があるのはなぜですか。 MySQLサーバーに直接アクセスするのではなく、MySQLサーバーにアクセスしますか?

暗号化された MySQL パスワードの復号化キーとして「ソルト」を使用している場合、許可されたユーザーはどのようにしてその値をシステムに渡しますか? たとえば、ssh 経由でサーバーにログインし、コマンドラインからスクリプトを実行する必要がありますか、それとも、たとえば Web サーバー経由でアクセスできるものですか?

いずれにせよ、誰かが Python スクリプトを実行しているシステムを侵害した場合、次の許可されたユーザーが来るまで待って、入力した「ソルト」を「嗅ぐ」だけで済みます。

于 2013-05-28T17:09:01.117 に答える