Help us understand the problem. What is going on with this article?

Zerologon (CVE-2020-1472) 「ドメインコントローラーにパッチ適用を」

はじめに

9/11(現地時間) に オランダのセキュリティ企業 Securaより Netlogon Remote Protocol (MS-NRPC) に関する脆弱性(Zerologon CVE-2020-1472) の情報が公開されました。

9/18 には米国土安全保障省(CISA) から行政機関に対しパッチ適用の「緊急命令」
が出てから、Twitter でもこの脆弱性についてのツイートが増えている気がします。

さらに 9/24には、マイクロソフトが本脆弱性を悪用した攻撃を確認したとのツイートがありました。


本記事では、「ドメインコントローラーにパッチ適用しましょう」 ということ、攻撃を受けたかもしれない場合の確認方法、本脆弱性の根本原因となる実装上の問題について記載します。

脆弱性について

前提として この脆弱性を悪用するには 攻撃者は ドメインコントローラーと通信できるネットワーク上に足場を築く必要があります。「内部に悪い人はいない」のかもしれないですが、例えば ウィルスに感染するなどして 他の脆弱性により乗っ取られてるデバイスがある場合は、攻撃を受ける可能性があります。

脆弱性の内容や対応については、冒頭のホワイトペーパーの他、たくさん記事がでているのでそちらを参照してください。

対策

すでに 8月にマイクロソフトから Windows Server のセキュリティ更新プログラムが提供されています。システム管理者は、ドメインコントローラーに対して直ちに更新プログラムを適用することが求められています。

攻撃されたかどうかの確認

POCが複数公開されていますが、決して商用環境で実行しないでください。ドメインコントローラーのコンピュータアカウントパスワードがリセットされると 最悪の場合 ドメイン環境が壊れます。

検証環境( Windows Server 2016 / Active Directory) で確認した限りですが、POCを実行すると、ドメインコントローラーのイベントログに 4742, 5805 が記録されました。

イベントID:4742, 5805 は、他のコンピューターについても上がるイベントなので、これ自体が攻撃を受けたことを示すものではありませんが、脆弱性の情報が公開された日付以降で、ドメインコントローラーについての当該ログを確認するのが指標になるかと思います。

イベントID 4742

POCのコードを実行した場合、ドメインコントローラーに対して以下のように、NT AUTHORITYANONYMOUS LOGN して、パスワードが変更された旨のログが記録されます。

ログの名前:         Security
ソース:           Microsoft-Windows-Security-Auditing
日付:            2020/09/23 14:06:04
イベント ID:       4742
タスクのカテゴリ:      コンピューター アカウント管理
レベル:           情報
キーワード:         成功の監査
ユーザー:          N/A
コンピューター:       <DCのコンピュータ名>.<ドメイン>
説明:
コンピューター アカウントが変更されました。

サブジェクト:
    セキュリティ ID:      ANONYMOUS LOGON
    アカウント名:     ANONYMOUS LOGON
    アカウント ドメイン:       NT AUTHORITY

イベントID 5805

同時刻にシステムログに以下のイベントが記録されました。

日付:            2020/09/23 14:06:04
イベント ID:       5805
タスクのカテゴリ:      なし
レベル:           エラー
キーワード:         クラシック
ユーザー:          N/A
コンピューター:      <DCのコンピュータ名>.<ドメイン> 
説明:
コンピューター <DCのコンピュータ名> からのセッション設定を認証できませんでした。 次のエラーが発生しました: 
アクセスが拒否されました。

脆弱性を利用した攻撃によりドメインコントローラーのコンピュータアカウントパスワードがリセットされても、しばらくは問題なく動いているように見えますが、ドメインコントローラーを再起動するとドメイン環境は正常に動作しなくなりました1

脆弱性の根本原因

Secura の ホワイトペーパーにあるように、本脆弱性の根本原因は、Netlogon 認証プロセスで使われている 暗号モードの実装上の問題にあります。

こちらの動画がとても参考になりますのでお勧めします。ホワイトペーパーを読んでもチンプンカンプンでしたが、この説明を見て分かりました。すごいです!
CVE-2020-1472 ZeroLogonの原因をわかりやすく解説!

何が問題なのか

Netlogon リモートプロトコル の ComputeNetlogonCredential 関数 では、8ビットCFBモードの AES-128 暗号アルゴリズム (AES-CFB8) が使われていますが、初期化ベクトル (Initialization Vector) を オールゼロで固定する実装2 になっていることが問題です。 初期ベクトルは毎回ランダムに作成する必要があります。

ホワイトペーパーにはこう書いています(訳はDeepL)

(ホワイトペーパーより引用) In order to be able to encrypt the initial bytes of a message, an Initialisation Vector (IV) must be specified to bootstrap the encryption process. This IV value must be unique and randomly generated for each separate plaintext that is encrypted with the same key.
The ComputeNetlogonCredential function, however, defines that this IV is fixed and should always consist of 16 zero bytes.
This violates the requirements for using AES-CFB8 securely: its security properties only hold when IVs are random.

「メッセージの初期バイトを暗号化できるようにするには、暗号化プロセスを起動するために初期化ベクトル(IV)を指定しなければなりません。この IV 値は、同じキーで暗号化される個別の平文ごとに一意で、ランダムに生成されなければなりません。
しかし、ComputeNetlogonCredential 関数では、この IV は固定であり常に 16 個のゼロバイトで構成されるべきであると定義しています。
これは、AES-CFB8 を安全に使用するための要件に違反しています。」

AES-CFB8 暗号化

ホワイトペーパーには、AES-CFB8 暗号アルゴリズムの解説があります。

通常時(ランダムな初期ベクトルの場合)

AES-CFB8では、16バイトの 初期化ベクトル(IV) をメッセージの前に付加し、AES を IV + メッセージの最初の16バイトに適用します。次に AES出力の最初のバイトとXORをとってメッセージの各バイトを暗号化します。

  1. ランダムな初期ベクトル(IV) を メッセージ(平文ブロック 8バイト)の前に付加
  2. AES を 初期ベクトル(IV) に適用し、先頭バイトのみを取得
  3. AES出力 と メッセージ先頭バイトの XOR をとって 先頭バイトを暗号化
  4. AES を 次の16バイト に適用 (右に 8ビットシフト)
  5. メッセージ全体が暗号化されるまで 繰り返す

画像は Secura のホワイトペーパーより引用
aes-cfb8_normal.png

初期ベクトルとメッセージをオールゼロにした場合

初期ベクトルの暗号文の先頭バイトが ゼロ となった場合(図の1,2の部分) は、生成される暗号文は 全てゼロになってしまうということが示されています。暗号文の先頭バイトが ゼロ になる確率は 1/256 です。

画像は Secura のホワイトペーパーより引用

aes-cfb8.png

つまり、初期ベクトル を ゼロ で固定すると 256回 鍵を作成したうち 1回 は 全て ゼロ の暗号文が生成される可能性があります。この脆弱性を悪用すると 1/256の確実で 認証が成功してしまうことになります。

初期ベクトル(IV) をオールゼロすると 暗号文は 本当にゼロになってしまうのか

CVE-2020-1472 ZeroLogonの原因をわかりやすく解説! にあるコードを真似して cryptography で確認しました。

  • 暗号化アルゴリズムは AESなので ブロック長は 16バイト(128ビット)です。モードは CFB8 です。
  • key は毎回ランダムに生成します。
  • 暗号処理では 脆弱性の原因となった 初期ベクトル(iv) を オールゼロで固定します。
  • また、メッセージ message(平文ブロック) 8バイトも 全てゼロにします。
# This code is based on
# https://cryptography.io/en/latest/hazmat/primitives/symmetric-encryption/
# https://github.com/kurenaif/aes_cfb8

import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

def encrypt(key, plaintext):
    iv = b"\x00" * 16
    # when IVs are random
    ##iv = os.urandom(16)
    encryptor = Cipher(algorithms.AES(key), modes.CFB8(iv)).encryptor()
    ciphertext = encryptor.update(plaintext) + encryptor.finalize()
    return iv, ciphertext

def decrypt(key, iv, ciphertext):
    decryptor = Cipher(algorithms.AES(key), modes.CFB8(iv)).decryptor()
    return decryptor.update(ciphertext) + decryptor.finalize()

MAX_ATTEMPTS = 100000
cnt = 0
for i in range(MAX_ATTEMPTS):
    # Only 128, 192, and 256 bit keys are allowed for this AES mode
    key = os.urandom(32)
    message = b"\x00" * 8
    iv, ciphertext = encrypt(key, message)
    if ciphertext == message:
        cnt += 1
        #print(f"ciphertext: {ciphertext} decrypted:{decrypt(key, iv, ciphertext)}")

print("score: ", cnt)
print("probability: ", cnt/MAX_ATTEMPTS)
print("1/256: ", 1/256)    

実行結果:

score:  395
probability:  0.00395
1/256:  0.00390625

100000 回 試行のうち 395回、 オールゼロ の 暗号文 が返ってきました。初期ベクトル(IV) を オールゼロで固定すると 1/256 (0.4 %) の 確率で 認証が通ってしまうであろうことが推測できます。

なお、初期ベクトル(IV) をランダム iv = os.urandom(16) にすると、暗号文は ゼロになりません。

参考書籍: 「暗号技術入門 第3版

Netlogon認証プロセスで考える

ホワイトペーパーには、Netlogon リモートプロトコルにおける クライアントとサーバーの認証プロセス3において、この脆弱性がどのように悪用されるのか、その概要が書かれています。

  1. 最初のフェーズ NetrServerReqChallenge では、クライアントとサーバーは チャレンジと呼ばれる nonce(一度しか使われないランダムな値) を交換します。これにより、クライアントとサーバの両方が、セッションキーを計算4することができます。

  2. 次のフェーズ NetrServerAuthenticate3 では、クライアントとサーバーは、計算されたセッションキーを使用して自身の チャレンジを入力として Netlogon クレデンシャルを計算5し交換します。
    最初のフェーズで チャレンジ が交換されているため、クライアントとサーバーは相手の Netlogon クレデンシャルを ローカルで再計算し、受信した Netlogon クレデンシャルと比較します。

  3. クライアント(攻撃者)は、本脆弱性を悪用して Netlogon クレデンシャル がオールゼロになるまで 認証プロセスを繰り返し 認証を突破します。認証が通ったあと、攻撃者は 長さゼロのパスワードを指定して コンピュータアカウントパスワードに空パスワード6を設定(NetrServerPasswordSet2) します。

画像は Secura のホワイトペーパーより引用
zerologon_attack.png

最後に

ドメインコントローラーにパッチ適用を。


  1. Microsoft-Windows-DNS-Server-Service のエラー(イベントID: 4000)発生, メンバーサーバーのセキュアチャネル破損等) 

  2. [MS-NRPC]:Netlogon Remote Protocol - 3.1.4.4.1 AES Credential -「If AES support is negotiated between the client and the server, the Netlogon credentials are computed using the AES-128 encryption algorithm in 8-bit CFB mode with a zero initialization vector.」 

  3. [MS-NRPC]:Netlogon Remote Protocol - 3.1.4.1 Session-Key Negotiation - を参考にしました。 

  4. [MS-NRPC]:Netlogon Remote Protocol - 3.1.4.3 Session-Key Computation -セッションキーを計算する際、shared secret (身元を証明するための情報;パスワード等)も使われます。 

  5. ここで ComputeNetlogonCredential 関数が使われています。 

  6. コンピュータに空のパスワードを設定することは禁止されていない 

kodamap
インフラ系の仕事をしています。Machine Learning を勉強中です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away