hunt-ntlm-info について
hunt-ntlm-infoは、NTLM情報漏えいを調査するペネトレーションテスターやバグバウンティ研究者向けのスキルです。チャレンジデータからホスト名、ドメイン構成、タイムスタンプを読み取り、状況に応じて影響を評価します。
主な機能
- 01公開エンドポイントのNTLM検出
- 02Type-2チャレンジの取得と解析
- 03ドメインとホスト情報の復号
- 04状況に応じた影響度評価
活用シーン
- 01公開IISまたはSharePointの調査
- 02Active Directoryドメイン情報の把握
- 03認証情報攻撃の偵察情報の補強
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-ntlm-infoインストール後、Claude Code で/hunt-ntlm-infoを入力して読み込まれたか確認します。
詳細
最重要の標的
NTLM 情報漏えいは、攻撃の文脈と組み合わせると中程度の深刻度に該当する問題です。漏えいそのものは意図されたプロトコルの動作(RFC に準拠した NTLMSSP チャレンジ)ですが、インターネットに公開されたエンタープライズインフラでは、攻撃の次の段階に向けた正確な偵察情報を提供します。特に価値の高い標的は次のとおりです。
- インターネットからアクセス可能な IIS/SharePoint/Exchange/OWA で、二重認証(Forms + NTLM、または NTLM + Kerberos)を使用しているもの
- NTLM を基盤とする AD 認証を使用する、インターネット公開の Citrix NetScaler/VMware Horizon View ゲートウェイ
- Lync/Skype for Business/Teams On-Prem のエッジサーバー
- NTLM で保護された管理者用パスを持つ WSUS/Windows Update Services
- NTLM をプロキシする CIFS 形式のファイル共有プロキシ(HCL Sametime、IBM Notes Domino)
- パブリックゾーンの IIS バインドで NTLM を有効にしたままの レガシー SharePoint ファーム
この情報が役立つ理由:
- 内部 AD ドメインの開示(親フォレストのマッピング。例:
customer.parent-corp.example→ corporate-AD ツリー内のテナント) - Windows のデフォルトのホスト名の開示(
WIN-XXXXXXXXXXXのパターンは、急いでプロビジョニングされたことを示唆し、デフォルトのサービスアカウントのパスワードが使われている可能性があります) - タイムスタンプの漏えい(NTLMv2 ハッシュのクラッキングを高速化するために使用)
hunt-auth-bypassLegacy-Protocol Matrix と組み合わせた、認証情報のスプレー攻撃向け攻撃マップの直接的な強化
攻撃対象領域のシグナル
NTLM が利用可能であることを示すレスポンスヘッダー:
WWW-Authenticate: NTLM
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM, Negotiate
WWW-Authenticate: Negotiate, NTLM
NTLM が公開されていることが多い URL パターン:
/_api/web/CurrentUser (SharePoint REST)
/_vti_bin/*.asmx (SharePoint legacy SOAP)
/EWS/Exchange.asmx (Exchange Web Services)
/Autodiscover/Autodiscover.xml (Exchange autodiscover)
/owa/ (Outlook Web App)
/Microsoft-Server-ActiveSync (ActiveSync)
/PowerShell (Exchange Mgmt Shell over HTTPS)
/api/v3/ (TeamCity, Atlassian)
/wsus/ (Windows Server Update Services)
/manager/html (some Tomcat behind IIS)
/iisstart.htm (default IIS, sometimes reveals NTLM upstream)
技術スタックのシグナル:
- パブリックインターネット上の IIS(フロントエンドが Forms の場合でも、ほぼ常に NTLM に対応しています)
- SharePoint Web フロントエンド(ほぼ常に Forms + NTLM の二重認証を使用します)
- Exchange エッジトランスポート
- サーバーヘッダー
Microsoft-HTTPAPI/2.0、Microsoft-IIS/*、IIS/*
手順に沿った調査方法
-
匿名でアクセスできるすべてのエンドポイントに対して、
WWW-Authenticate: NTLMを確認します。 通常の GET リクエストを送信し、レスポンスヘッダーを調べます。NTLM が提示された場合は、次に進みます。 -
有効な NTLMSSP Type-1 メッセージを匿名で送信します。 以下の Type-1 の base64 は、サーバーから NetBIOS ドメイン情報とワークステーション情報を要求します:
Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==これは、ネゴシエートフラグ
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_TARGET_INFOを含む標準的なテスト用 Type-1 です。OS Versionフィールド(06 01 B1 1D 00 00 00 0F)は Windows 7 ビルド 7601 を示し、ほぼすべての NTLM レスポンダーで受け入れられます。 -
Python requests や curl の単発リクエストではなく、キープアライブ対応の生ソケットを使用します。 多くの HTTP ライブラリは、Type-1 の送信から Type-2 の受信までの間に接続を閉じます。次のいずれかを使用します:
Connection: keep-aliveを明示的に設定した Burp Repeater- Burp
mcp__burp__send_http1_request(キープアライブをネイティブに処理します) - Python の生
socket+ssl.wrap_socket(「ペイロード」セクションを参照)
-
WWW-Authenticate: NTLM <base64>レスポンスヘッダーから Type-2 チャレンジを解析します。 値を Base64 デコードします。構造は MS-NLMP に準拠する NTLMSSP です:- バイト 0-7:リテラル値
NTLMSSP\0 - バイト 8-11:MessageType =
\x02\x00\x00\x00 - バイト 12-19:TargetName SecurityBuffer(長さ、割り当て長、オフセット)
- バイト 20-23:NegotiateFlags
- バイト 24-31:Server Challenge(8 バイト。オフライン解析に有用)
- バイト 40-47:TargetInfo SecurityBuffer(長さ、割り当て長、オフセット)
- TargetInfo 本文:
AV_PAIRS配列(AvId u16、AvLen u16、Value)
- バイト 0-7:リテラル値
-
AV_PAIRS をデコードします。 確認する AvId は次のとおりです:
1= NetBIOS コンピューター名2= NetBIOS ドメイン名3= DNS コンピューター名(応答サーバーの FQDN)4= DNS ドメイン名(AD ドメイン)5= DNS ツリー名(AD フォレストのルート)7= タイムスタンプ(FILETIME。NTLMv2 ハッシュのリレーや解析に有用)9= ターゲット名(新しい NTLMSSP の場合)
-
調査結果を重大度レベルに割り当てます:
- インターネットに公開されている + デフォルトの
WIN-XXXXXXXXXXXホスト名 + 企業の AD ツリーの開示 → 中 - インターネットに公開されている + 名前付きサーバーのホスト名(
SPWEB01.corp.example)+ 企業の AD ツリー → 低~中 - イントラネット限定 + 何らかの開示 → 参考情報
- 同じホストで
hunt-auth-bypassのレガシープロトコルマトリックスの調査結果と組み合わせる → 攻撃者が UPN/SAM 形式をすぐに利用できるため、認証バイパスの調査結果の重大度を引き上げます
- インターネットに公開されている + デフォルトの
-
タイムスタンプを確認します。
AV[7]がDate:ヘッダーから約 5 秒以内の現在の FILETIME を返す場合、システムクロックは同期されています。これは Kerberos ゴールデンチケットの偽造に役立つ情報です(バグバウンティの対象外ですが、レッドチームには関係します)。 -
サブドメイン列挙の結果と照合します。 DNS Tree 名から、親フォレストが明らかになることがよくあります。たとえば、
customer.parent-corp.exampleは、顧客が別のテナントではなく、企業の親 AD 内のサブドメインであることを示しています。これはプライバシーやネットワーク構成の開示に関する重大度引き上げにつながり、プログラムによっては中として受け入れられることがあります。
ペイロードと検出パターン
汎用 NTLM Type-1 匿名プローブ(curl と生ソケットのフォールバック):
# Most one-shot curl runs DON'T return Type-2 because the connection closes.
# Use this as a quick probe to confirm NTLM is offered:
curl --max-time 30 --connect-timeout 10 -sk -I -H "Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==" \
"https://target.example/_api/web/CurrentUser" 2>&1 | grep -i "WWW-Authenticate"
Burp send_http1_request(Type-2 の全データ取得に推奨):
GET /_api/web/CurrentUser HTTP/1.1
Host: target.example
Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==
Connection: keep-alive
User-Agent: Mozilla/5.0
Python の生ソケット + AV_PAIR デコーダー:
import socket, ssl, base64, struct, re
from datetime import datetime, timezone
HOST = "target.example"
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
s = ctx.wrap_socket(socket.create_connection((HOST, 443)), server_hostname=HOST)
s.sendall(
f"GET /_api/web/CurrentUser HTTP/1.1\r\n"
f"Host: {HOST}\r\n"
"Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==\r\n"
"User-Agent: Mozilla/5.0\r\nConnection: keep-alive\r\n\r\n".encode()
)
data = b""
while True:
chunk = s.recv(8192)
if not chunk: break
data += chunk
if b"\r\n\r\n" in data: break
m = re.search(rb"WWW-Authenticate:\s*NTLM\s+([A-Za-z0-9+/=]{20,})", data, re.I)
if m:
b = base64.b64decode(m.group(1).decode("ascii"))
assert b[:8] == b"NTLMSSP\x00"
tn_len, _, tn_off = struct.unpack_from('<HHI', b, 12)
ti_len, _, ti_off = struct.unpack_from('<HHI', b, 40)
print(f"TargetName: {b[tn_off:tn_off+tn_len].decode('utf-16-le', errors='ignore')!r}")
av_types = {1:'NetBIOS Computer Name', 2:'NetBIOS Domain Name',
3:'DNS Computer Name', 4:'DNS Domain Name',
5:'DNS Tree Name', 7:'Timestamp', 9:'Target Name'}
i = 0
ti = b[ti_off:ti_off+ti_len]
while i < len(ti):
av_id, av_len = struct.unpack_from('<HH', ti, i)
if av_id == 0: break
val = ti[i+4:i+4+av_len]
if av_id == 7:
ts = struct.unpack('<Q', val[:8])[0]
secs = (ts - 116444736000000000) / 10000000
vs = datetime.fromtimestamp(secs, tz=timezone.utc).isoformat()
else:
vs = val.decode('utf-16-le', errors='ignore')
print(f" AV[{av_id}] {av_types.get(av_id, '?'):28s}: {vs!r}")
i += 4 + av_len
この種の調査結果では Burp Collaborator は不要です。データ漏えいは OOB 経由ではなく、同期レスポンス内で発生します。
共通する根本原因
-
パブリックゾーンの IIS バインドで二重認証が有効になっている。 管理者が、フォーム認証を本来のエントリーポイントとしているにもかかわらず、インターネットに公開された IIS サイトで NTLM を有効にしたままにしています。内部ユーザーは SSO を利用できますが、外部の攻撃者には AD トポロジーが漏えいします。
-
既定の IIS アプリケーションプール ID が
ApplicationPoolIdentityのままになっている。 既定のホスト名と組み合わさると、初回起動時の設定以降、プロビジョニングが進んでいないことを示します。 -
サーバー名が Windows インストーラーによって生成されたホスト名のままになっている。 Microsoft の既定の
WIN-XXXXXXXXXXXという 11 文字のパターンは、すぐに見分けられる手掛かりです。古いマシンでは、WORKGROUP\WIN-...になっていることもあります。 -
ゾーン分離なしで、サブドメインが企業フォレストに参加している。 欧州のインテグレーターの事例では、欧州の輸入業者の SharePoint テスト環境が企業のグローバル AD 内の子ドメインであり、そのことが NTLM DNS ツリー名から判明しました。顧客は
customer.parent-corp.exampleを運用上分離された環境にする意図だったと思われますが、NTLM Type-2 により、プローブを行う誰もがフォレストへの所属を把握できます。 -
IIS Extended Protection が有効になっていない。
<system.webServer><security><authentication><windowsAuthentication extendedProtection>がNone(既定値)の場合、NTLM チャレンジはすべての匿名クライアントに送信されます。Requiredに設定すると、NTLM は認証済みの呼び出し元に制限され、AV ペアの漏えいが軽減されます。 -
インターネットに公開されたサイトで、
WindowsAuthenticationがapplicationHost.configから削除されていない。 SharePoint Central Admin では、SP ゾーンの設定でフォーム認証のみを有効にしていても、これが有効なままになっていることがあります。
バイパス手法
このスキルが説明するのは情報漏えいであり、認証のバイパスではありません。「バイパス」に関する問いは、正当な NTLM 認証を許可したまま、この AV ペアの漏えいを防ぐにはどうすればよいか? ということです。
| 防御策 | 有効性 |
|---|---|
| パブリック IIS バインドで NTLM を完全に無効化する(フォーム認証のみ) | 最善 — 攻撃対象領域をなくします |
| IIS Extended Protection = Required | NTLM チャレンジを認証済みの呼び出し元に制限し、AV ペアの漏えいを軽減します |
リバースプロキシで匿名応答から WWW-Authenticate を除去する | 有効な場合もありますが、正当なクライアントに支障が出ます |
| Type-1 → Type-2 エンドポイントにレート制限を適用する | 情報漏えいは防げず、列挙を遅らせるだけです |
Windows ホスト名を WIN-XXXXXXXXXXX から変更する | 「プロビジョニングの手抜き」という手掛かりをなくしますが、漏えいは防げません |
| SP/Exchange ファームを、企業とのクロストラストがない子 AD に移す | フォレストの情報漏えいを軽減しますが、漏えい自体は防げません |
攻撃者にとって、「バイパス」は必要ありません。漏えいそのものが発見事項です。
ゲート 0 の検証
レポートを作成する前に、次の点を確認してください。
-
この情報漏えいによって、攻撃者は今すぐ何ができるか?
- インターネットに公開されており、既定のホスト名と企業フォレストが判明している → 中:攻撃者は
hunt-auth-bypassのマトリクスプローブに使える UPN 形式を把握でき、サーバーに既定のサービスアカウントが残っている可能性が高いことも分かります。 - イントラネット専用、または NetBIOS 名のみ → 情報提供。
- インターネットに公開されており、既定のホスト名と企業フォレストが判明している → 中:攻撃者は
-
プログラムは、影響を連鎖させていない情報漏えいの報告を受け付けるか?
- 多くのプログラム(Microsoft、大規模エンタープライズ VDP)は、漏えいした情報に内部 AD トポロジーが含まれる場合、受け付けます。
- 多くのプログラム(Shopify、GitHub)は、影響を連鎖させていない情報漏えいを却下します。
- 提出前にプログラムのスコープを確認してください。判断が難しい場合は、
hunt-auth-bypassの Tier-A 発見事項と組み合わせてください。
-
新しいシェルから 5 分以内に再現できるか?
- 上記の Python スニペットが標準的な再現方法です。レポートにはそのまま記載してください。
実際の影響例
シナリオ A — 親会社の企業 AD 内にあるエンタープライズ SharePoint
対象:https://target-portal.example/ — システムインテグレーターが運用するエンタープライズディーラーポータル(テスト用ミラー)。
/_api/web/CurrentUser に匿名の Type-1 メッセージを送信したところ、AV_PAIRS をデコードすると次のような Type-2 チャレンジが返されました。
NetBIOS Domain Name: <CustomerName>
NetBIOS Computer Name: WIN-XXXXXXXXXXX
DNS Domain Name: customer.parent-corp.example
DNS Computer Name: WIN-XXXXXXXXXXX.customer.parent-corp.example
DNS Tree Name: customer.parent-corp.example
Timestamp: 2026-05-13T15:55:37.922Z
エスカレーション経路は 3 つあります。
- Windows インストーラーのデフォルトのホスト名(
WIN-XXXXXXXXXXX) — OS のインストール後にサーバー名が変更されていません。プロビジョニングがずさんだったことを示す有力な兆候です。SQL バックエンドのデフォルトのサービスアカウントパスワード、デフォルトの WSUS 設定などが考えられます。 - 企業の親 AD 内のサブドメイン(
customer.parent-corp.example) — 顧客は のグローバル Active Directory 内の子ドメインです。このテストファームが侵害されると、企業の親ドメインとの信頼関係を越えて影響が及ぶ可能性があります。 - UPN 形式が判明している —
hunt-auth-bypassが/_vti_bin/Authentication.asmxにある匿名のブルートフォースエンドポイントを発見したことと組み合わせると、攻撃者は認証情報の形式([email protected]または<CustomerName>\firstname.lastname)と、無制限に送信できるエンドポイントの両方を手にしています。
報告された重大度:中。Authentication.asmx への匿名ブルートフォースと組み合わせた攻撃は、全体として重大度「致命的」になるという注記があります。
シナリオ B — NTLM で保護された EWS がある Exchange エッジ
対象:https://mail.example.com/EWS/Exchange.asmx。Type-1 プローブに対して、DNS Tree Name が corp.example.com、DNS Computer Name が MAIL01.corp.example.com の Type-2 が返されます。これにより、Exchange エッジが DMZ で隔離された AD ではなく、企業 AD に参加していることが確認できます。一致する hunt-mfa-bypass/hunt-auth-bypass の攻撃チェーンを持つ攻撃者にとって、漏えいした UPN 形式とサーバー名の形式は偵察の手順を省けるため、認証情報のスプレー攻撃を効率化できます。報告された重大度は、プログラムによって「低」から「中」です。
シナリオ C — 意図的に漏えいするイントラネット限定のケース(報告対象外)
対象:https://intranet.corp.example(明らかに内部向けで、VPN の背後にあります)。Type-1 に対して、AV ペアの全セットが返されます。報告対象ではありません。これはイントラネットでの意図された NTLM の動作であり、情報が開示されるのは、すでに nltest /dsgetdc:corp.example.com で同じデータを確認できる VPN 認証済みユーザーに限られるためです。該当しないものとして認識し、除外してください。
検証
次のセルフテストを実行して、ntlm-info のハンティングを行う準備ができていることを確認してください。
-
スキルの整合性 — スキルファイルが読み取り可能で、適切な形式であることを確認します。
grep -q "name: hunt-ntlm-info" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL" grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL" -
カテゴリの確認 — スキルにカテゴリがあることを確認します。
grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL" -
落とし穴のセクション — 落とし穴が記載されていることを確認します。
grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
3 つのテストすべてにより、スキルが適切に構成され、使用する準備ができていることを確認できます。
落とし穴
- リレー先がない NTLM Type-2 チャレンジ — NTLM チャレンジの取得は偵察です。影響を及ぼすには、リレー先(SMB、HTTP、LDAP)が必要です。
- AV_PAIR によるドメイン名の開示 — AV_PAIR から判明する内部ドメイン名は、参考情報です。影響を及ぼすには、認証情報の取得またはリレーが必要です。
- 同一ホスト上での NTLM リレー — 同一ホスト上での SMB から SMB へのリレーは、SMB 署名によって阻止されることがよくあります。プロトコルをまたぐリレー(HTTP から SMB、LDAP から HTTP)をテストしてください。
- NTLMv1 と NTLMv2 — NTLMv1 のハッシュは数分で解読できます。NTLMv2 の解読には相当な労力が必要です。レポートでは両者を区別してください。
関連するスキルとチェーン
hunt-sharepoint— SharePoint ファームは、デフォルトで/_vti_bin/に匿名の Type-2 チャレンジを送信します。これは、内部 AD トポロジーを入手する最も確実な方法の 1 つです。チェーンのプリミティブ:SharePoint を発見 →/_vti_bin/Lists.asmxで NTLM Type-2 をキャプチャ →hunt-ntlm-infoで AV_PAIR をデコード → 内部フォレスト名を特定 → そのフォレストに関連付けられた Entra テナントに対してm365-entra-attackで ROPC スプレー。m365-entra-attack— 漏えいした NetBIOS ドメインと UPN サフィックスは、信頼性の高いパスワードスプレーに必要な欠落情報です。チェーンのプリミティブ:NTLM Type-2 からcorp.example.comの DNS ツリーを取得 →https://login.microsoftonline.com/corp.example.com/.well-known/openid-configurationを通じて Entra テナントと照合 → 解決したテナントに対してm365-entra-attackで AADSTS エラー差分を利用したユーザー名列挙。hunt-aspnet— ASP.NET を実行する IIS サイトでは、管理用パスで NTLM が公開されていることがよくあります。チェーンのプリミティブ:/owa/、/ecp/、/rpc/、/aspnet_client/で NTLM Type-2 を取得 → IIS と ASP.NET のバージョンを確認 → 同じホストでhunt-aspnetを使って ViewState/.axdを列挙。offensive-osint— ホスト名のパターンWIN-XXXXXXXXXXXは、ずさんなプロビジョニングを示し、ほかの管理不備も予測できます。チェーンのプリミティブ:NTLM Type-2 からデフォルトインストーラーのホスト名を取得 → 成熟度の低い環境としてフラグを設定 → この組織ではoffensive-osintによる詳細な偵察(証明書の透明性、GitHub への漏えい、漏えいデータベースとの相関)が大きな成果につながります。triage-validation— NTLM 情報開示に関する調査結果のほとんどは、「悪用可能か」という「7 つの質問ゲート」で行き詰まります。トポロジーの開示だけでは、重大度は低または参考情報にとどまります。チェーンのプリミティブ:NTLM 情報に関する調査結果はすべて、報告書を作成する前にtriage-validationで検証してください。(a)スプレーを効率化できる UPN 形式が漏えいしている場合、または(b)本番環境のホスト名マッピングが漏えいしている場合に限り報告します(チェーンの説明にはredteam-report-templateを使用)。password-spray-methodology— すべてのプロトコルに対応した汎用パスワードスプレーパイプラインと、エラーコードの差分