nknskn ネタ置き場

IT使ってなんかやってる人間のたわごと

NTLMv2 Hashをvbscript + phpで手に入れる

2020年2月あたりのssmjpで、vbscriptで結構頑張れるってことを言いたいがために紹介したツールの解説です. 利用可能なコードは公開していませんのでご承知ください.
※コンセプトさえわかれば、結構な人がパパッと作れる類のものだと思います. 実際にどんな感じのコードになるのか気になる人は絡んでください(かまってちゃんスタイル)

ssmjpの中でも触れましたが、ガチガチの環境(生パスワードが入ってるファイルなんて見つからない、最新のパッチが適用されていて権限昇格可能/横展開可能な脆弱性がない、とかシステム・運用的に堅牢)だと、なかなか攻撃の糸口が見つからずに大変だったりするケースがあります.
※もちろん防御側にとっては非常に望ましい環境です

そんな感じで、HTTP(S)通信を使用したstagerの埋め込みには成功しているものの、管理者権限なし、脆弱性なし、クライアント端末上にめぼしい情報なしでどうしたもんかなーなんて思いつつ、NTLM v2認証の流れをなんとなく眺めている時に思いついた仕組み&ツールです. 思いついてからおおよそ1時間(+debug time)で作れました.
ちなみにその時眺めていたサイトは以下.

IIS認証NTLMおよびASP.NET偽装によるWebアプリケーションの負荷分散| ゼベネット

NTLM認証がどこまで生き残っているのか正直わからないものの、Responderを使用したMITMによるHash取得が可能なシチュエーションを多く見ているので、NTLM認証の設定はまだまだ有効なんだろうなぁ、という印象があります. BlueTeam側の方にはケーススタディとして参考にしてもらえればと思います.

以下ToC

そもそもの認証情報窃取について

Windows環境における認証情報の窃取はいろいろな方法があるので書き切れないですが、大きく分けると以下のような感じだと思います.

  • 生パスワードの取得(mimikatz、キーロガー、bat/ps1/txtファイルの中など)
  • NTLM Hashの取得(Pass the Hash用)
  • NTLMv2 Hash取得によるOfflineパスワード解析(ResponderによるMITM、Redirect to SMBなど)

生パスワードの取得に成功すれば御の字ですが、以下のような感じでなかなかそうはいかない&見つからない場合調査にかけた時間が無駄になる可能性があります.

  • mimikatz
    • 権限昇格可能な脆弱性がそもそもない、ツラい
  • Responder
    • MITMでNTLMv1/NTLMv2 Hashを取得できるpythonツール
    • MITM用の端末を対象のネットワークに持ち込める?python.exeを突っ込める?
    • pyinstallerとかでexeにしたとしても管理者権限必要、ツラい
  • Inveigh.ps1
    • MITMでNTLMv1/NTLMv2 Hashを取得できるPowerShellツール
    • Port開ける必要があるので管理者権限が必要、ツラい
  • Redirect to SMB
    • FWのOutboundで139/tcp, 445/tcpって普通開いてない、ツラい

まあこのような状況下で少なくともNTLMv2のNTLM Responseは取得できないかを考えていた状況でした.

前提

以下の3つだと考えています. (Group policyの設定で、止められる項目が別にあるかも?)

  • WSHが動作すること ※WinHTTPRequest オブジェクトが扱えるものならなんでも良い
  • OutboundでHTTP(S)が開いていること
  • クライアント端末でNTLM認証が有効になっていること

スクリプトを動かした時の挙動、HashcatでCrackするまで

ユーザ権限でスクリプトを実行した際の挙動を撮ってgifにしています. ※hatenaへのアップロードがこけてめんどくさくなったのでgithubに置いた、反省も後悔もしていない

GitHub - nknskn/Get-NTLMv2: Gif only

NTLMv2 Hashの生成の流れ、およびHTTPにおけるNTLMv2認証プロセスについて

Hash生成

こちらのブログの「Net-NTLMv2認証」を参照してもらうのが良いと思います.

Pass-the-Hashの仕組み - Binary Pulsar

見ていただければわかりますが、NTLMv2 Hashの生成に使用されているのは以下の5要素です.

  • パスワード(NTLM hash)
  • ユーザが所属しているドメイン
  • ユーザが所属しているドメインにおける、ユーザ名
  • Client-issued NTLM Challenge
  • Server-issued NTLM Challenge

攻撃者から見た場合、「NTLMv2 Hash」「ドメイン名」「ユーザ名」「Client-issued NTLM Challenge」「Server-issued NTLM Challenge」の5要素、およびパスワード候補の辞書があれば、NTLMv2 Hashを計算・取得したHashに衝突するかどうかを検証することで、パスワードのOffline crackが可能になります.

通常のHTTPにおけるNTLMv2認証プロセス

上記の生成時に使用した情報をサーバとクライアントで共有することで、認証が可能になります. 認証時のステップは以下の通りです.
※図用にリンク再掲
IIS認証NTLMおよびASP.NET偽装によるWebアプリケーションの負荷分散| ゼベネット

f:id:news-nknskn:20201121031553p:plain
ntlmauth

文字にするとざっくり以下です.

  1. クライアント -> サーバ
    • GET /
    • コンテンツ見せてー
  2. サーバ -> クライアント
    • 401 Unauthorizaed
    • WWW-Authenticate: NTLM
    • NTLMでの認証必須やで
  3. クライアント -> サーバ
    • GET /
    • Authorization: NTLM Tl...
    • NTLMSSP_NEGOTIATE
    • 了解、Server Challenge送ってー
  4. サーバ -> クライアント
    • 401 Unauthorizaed
    • WWW-Authenticate: NTLM Tl...
    • NTLMSSP_CHALLENGE
    • よっしゃこれチャレンジな. わしはこのドメインのサーバだから、この情報使ってハッシュ値送ってくれ
  5. クライアント -> サーバ
    • GET /
    • Authorization: NTLM Tl...
    • NTLMSSP_AUTH
    • ハッシュ計算したー. あたしゃはこういうもん(ドメイン名、ユーザ名)で使ったチャレンジはこれっす. 認証ヨロー.
      • ドメイン名(サーバから返送されたものと同じ)
      • ユーザ名
      • Client-issued Challenge
      • NTLMv2 Hash
  6. サーバ -> クライアント
    • 200 OK
    • 認証通ったわ、コンテンツ見せたる

ツール化する上での、上記フローにおける要点は次の2点です.

  • サーバは、自分がどのドメインに所属しているかをクライアントに通知する
  • クライアントは、サーバから送信されたドメインと対応するユーザ名を基に、NTLM v2 Hashを計算する
    • その後、使用したドメイン名、ユーザ名、Client-issued Challenge、NTLMv2 Hashをサーバへ送信する

ドメインに所属していない(攻撃者)サーバで、NTLMv2 Hashを取得するための仕様について

上記の通常時の認証プロセスから、認証プロセス開始前においてサーバ・クライアントがそれぞれ保持している情報は以下のように考えられます.

  • サーバ:ドメイン名、Server-issued NTLM Challenge
  • クライアント:ドメイン名(サーバからの指定)、ユーザ名、Client-issued NTLM Challenge、NTLMv2 Hash

それに対し、端末に侵入した攻撃者にとっての事前情報は以下のような状態と考えられます.

  • サーバ:Server-issued NTLM Challenge
  • クライアント:ドメイン名、ユーザ名、Client-issued NTLM Challenge、NTLMv2 Hash

このことから攻撃者は、認証プロセス開始前に攻撃対象のドメイン情報をサーバへ送信しておけば、通常のNTLMv2認証プロセスにおける認証開始前状態と一致し、そのまま認証プロセスを行えると考えられます.
このことから、クライアント側の要件は以下のようになります.

  • コンピュータ/ユーザが所属しているドメイン情報を取得し、サーバへ送信可能なこと
  • ドメイン情報に基づくNTLM認証に対応したHTTP communicationが可能なこと

またクライアントはドメイン情報通知のHTTPリクエスト(リクエスト1)を発生させたのち、NTLM認証要求リクエスト(リクエスト2)を送信しますが、サーバ側ではリクエスト1とリクエスト2が同一ユーザであることを識別する必要があります.
したがって、サーバ側の要件は以下となります.

  • リクエスト1とリクエスト2に対するセッション管理が可能なこと
  • NTLM情報の要求が可能なこと

それぞれの要件について、考察していきます.

(クライアント)コンピュータ/ユーザが所属しているドメイン情報を取得可能なこと

Windows APIを利用可能なもの、あるいはwmiを利用可能であれば、容易に取得が可能です. vbscriptであればそれこそggれば秒で見つかるので、ここでは割愛します.

(クライアント)ドメイン情報を用いたNTLM認証をサポートしている、HTTP communicationが可能なこと

一番考えなければならない項目がこれです.
XMLHTTPRequestのようなモジュールを利用した場合、システムに保存されている認証情報を投げてくれるかはわかりません(これは調査してない). また、認証ダイアログを出すパターンではユーザに怪しまれる可能性が非常に高くなります.
今回の場合、その辺りを解決してくれているのが「WinHttp.WinHttpRequest」オブジェクトです. このオブジェクトは「SetAutoLogonPolicy」メソッドを持っており、値にAutoLogonPolicy_Always(0)が設定された場合は、NTLM認証が要求された際ユーザに認証を求めず、オブジェクトの方でよしなに(システムに保存されている認証情報を参照)してくれるようになっています.

WinHttpRequest object - Win32 apps | Microsoft Docs
IWinHttpRequest::SetAutoLogonPolicy method - Win32 apps | Microsoft Docs
Authentication in WinHTTP - Win32 apps | Microsoft Docs
WinHttpRequestAutoLogonPolicy enumeration - Win32 apps | Microsoft Docs

この仕様を用いてDomain NTLM認証対応なHTTPリクエストを送るスクリプトを書くと、以前書いたブログ(以下)のような感じになります.

Windows認証のHTTPリクエスト(Net-NTLMv2)を送るVBScript(超ヤバイ) - nknskn ネタ置き場

(サーバ)リクエスト1とリクエスト2に対するセッション管理が可能なこと
(サーバ)NTLM情報の要求が可能なこと

この2項目についてはNTLM認証用のバイナリデータ生成をどの言語でどこまで頑張るか、という話で、実現困難性の観点では考えるまでもなく可能で容易(制限もない)ため、割愛します. 作成した際には突貫工事だったため、以下のプログラムをベースに条件分岐や出力などをいじって形にしました.

php-ntlm/ntlm.php at master · loune/php-ntlm · GitHub

プログラムの流れ

クライアント、およびサーバにおける一連の動作を書くと以下になります.

  1. (クライアント)ドメイン情報をwmiかなにかで取得
  2. (クライアント)取得した情報をサーバへ送信、HTTP POST 1
  3. (クライアント)サーバへリソース要求、HTTP GET 2
  4. (サーバ)NTLM認証要求、HTTP GET 2 - Response
  5. (クライアント)NTLM認証開始、HTTP GET 3
  6. (サーバ)POST 1で取得したドメイン情報を基にServer-issued Challengeの返送、HTTP GET 3 - Reponse
  7. (クライアント)NTLMv2 Hashの送信、HTTP GET 4
  8. (サーバ)200 OK(なんでもいい)、logging、HTTP GET 4 - Response

上記の通り、事前のドメイン情報送信+NTLM認証用リクエストの計 4 HTTP Request(POST or GET, GET, GET, GET)でNTLM v2 Hashの取得が可能です.

再掲 GitHub - nknskn/Get-NTLMv2: Gif only

感想・考察

  • おそらくですが、BlueTeam側で知識なくこれらのHTTPリクエストを発見するのは非常に困難だと思います. ※Cloudfront経由でもハッシュの取得が可能であることを確認しています.
  • 感染した端末上のexe/vbsなどで、これらの組み合わせ(WinHTTPRequest/AutoLogonPolicy_Always)が発見された場合、NTLM v2 hashが窃取されていると想定して、パスワード変更の実施を推奨するのがベターなのかなと. (それ以上の被害が出ているケースがほとんどなんでしょうけど)
  • VBScript結構すごい!COM objectしか触れなくてもわりとイケるやん! -再掲:実際にどんな感じのコードになるのか気になる人は絡んでください(かまってちゃんスタイル)

その他参考

以上