Windowsネットワークの深淵を覗くRPCインターフェーススキャナー
ネットワークセキュリティの世界、特にWindows環境のペネトレーションテストやセキュリティ評価において、Microsoft Remote Procedure Call (MSRPC) は重要な役割を果たします。MSRPCは、ネットワーク上の異なるコンピュータ間でプログラムが互いにサービスを要求するためのプロトコルです。これにより、クライアントはリモートシステム上のプロセスをローカルにあるかのように呼び出すことができます。しかし、この便利な機能は攻撃者にとっても魅力的なターゲットとなり得ます。
ここで登場するのが、Impacketという強力なPythonツールキットです。Impacketは、ネットワークプロトコルを扱うためのPythonクラスのコレクションであり、特にSMB (Server Message Block) やMSRPCの実装を提供しています。その豊富なツール群の中に、今回注目する rpcmap.py
が含まれています。
rpcmap.py
は、ターゲットシステム上で待ち受けているDCE/RPC (Distributed Computing Environment/Remote Procedure Call) インターフェースをスキャンするためのスクリプトです。具体的には、MSRPCのエンドポイントマッパー (通常TCPポート135で動作) や、SMB (TCPポート139, 445) 経由、さらにはHTTP (TCPポート593) 経由でアクセス可能なRPCサービスに関する情報を収集します。
このブログ記事では、rpcmap.py
の基本的な使い方から、より高度なオプション、出力結果の解釈、そしてセキュリティ上の意味合いまで、包括的に解説していきます。Windowsネットワークの内部構造を理解し、潜在的な脆弱性を特定するために、rpcmap.py
をどのように活用できるか見ていきましょう。
MSRPCとエンドポイントマッパーの基礎知識
rpcmap.py
を理解する上で、MSRPCとその中心的なコンポーネントである「エンドポイントマッパー」について基本的な知識を持つことが重要です。
MSRPCとは?
Microsoft Remote Procedure Call (MSRPC) は、分散コンピューティング環境におけるプロセス間通信 (IPC) のためのプロトコルです。簡単に言えば、あるコンピュータ上のプログラム(クライアント)が、ネットワーク上の別のコンピュータ(サーバー)にある手続き(関数やメソッド)を実行させるための仕組みです。これにより、ネットワークを介したシームレスな機能連携が可能になります。Windows環境では、ファイル共有、プリンタ共有、Active Directory操作、リモートでのサービス管理など、多くの基本的な機能がMSRPCに依存しています。
エンドポイントマッパー (epmapper)
RPCサービスは、特定の「インターフェース」 (提供する機能群を定義) と「エンドポイント」 (通信を受け付ける具体的なアドレス、ポート番号、または名前付きパイプ) を持ちます。しかし、特にTCP/IPを使用する場合、サーバー上のRPCサービスが使用するポート番号は動的に割り当てられることがあります。クライアントは、接続したいサービスが現在どのポートで待ち受けているかを知る必要があります。
ここで「エンドポイントマッパー」 (epmapper) が登場します。これは、サーバー上で動作する特別なRPCサービスで、他のRPCサービスが自身を登録する場所です。クライアントはまず、既知のポート (通常はTCP 135) で動作しているエンドポイントマッパーに問い合わせます。目的のサービスのインターフェースUUID (Universally Unique Identifier) を伝えると、エンドポイントマッパーはそのサービスが現在待ち受けている具体的なエンドポイント情報 (例: TCPポート番号) を返します。クライアントは、この情報を使って目的のサービスに直接接続します。
MSRPCの通信は、主に以下のトランスポート経由で行われます:
- TCP/IP: エンドポイントマッパー (TCP 135) と、動的または静的に割り当てられた高位ポートを使用。
- SMB (Named Pipes): SMBプロトコル (TCP 139, 445) 上の名前付きパイプを使用。
- HTTP: RPC over HTTP (TCP 593) を使用。インターネット越しの通信などに利用される。
rpcmap.py
は、これらのトランスポートを利用してエンドポイントマッパーに接続し、登録されているインターフェース情報を取得しようと試みます。
前提条件とインストール
rpcmap.py
を使用するには、Impacketライブラリがインストールされている必要があります。ImpacketはPythonで書かれているため、Python 3の環境が必要です。
多くの場合、Kali Linuxなどのペネトレーションテスト用ディストリビューションにはImpacketがプリインストールされています(impacket-scripts
パッケージなど)。
もしインストールされていない場合は、pipを使って簡単にインストールできます。
pip install impacket
または、GitHubリポジトリからソースコードを取得してインストールすることも可能です。
git clone https://github.com/fortra/impacket.git
cd impacket/
python setup.py install
インストール後、rpcmap.py
スクリプトは通常、Impacketの examples
ディレクトリ内、あるいはシステムのPATHが通った場所 (Kaliの場合など) に配置されます。
注意: Impacketのツール群は、正当な目的(セキュリティ評価、教育、研究など)でのみ使用してください。許可なく他者のシステムに対して使用することは、法律で禁止されている場合があります。
rpcmap.py の基本的な使い方
rpcmap.py
の最も基本的な使い方は、ターゲットのIPアドレスと、接続に使用するRPC文字列バインディングを指定することです。文字列バインディングは、使用するプロトコル、ネットワークアドレス、エンドポイント(ポート番号やパイプ名など)を指定する形式です。
最も一般的なのは、TCPポート135のエンドポイントマッパーに接続するケースです。
rpcmap.py <ターゲットIPアドレス>
または、より明示的にプロトコルシーケンスを指定する場合:
rpcmap.py ncacn_ip_tcp:<ターゲットIPアドレス>
ここで ncacn_ip_tcp
は、TCP/IPプロトコルを使用することを示します。rpcmap.py
は、指定されたターゲットのエンドポイントマッパー(デフォルトではポート135)に接続し、登録されているRPCインターフェースとそのエンドポイント情報をリストアップしようとします。
例えば、IPアドレス 192.168.1.100
のホストに対して実行する場合:
rpcmap.py 192.168.1.100
あるいは
rpcmap.py ncacn_ip_tcp:192.168.1.100
これにより、ターゲットホストで公開されているRPCインターフェースに関する情報が表示されます。認証が必要な場合や、特定のポートを指定したい場合は、後述するオプションを使用します。
ヒント: rpcmap.py
は、まず MGMT (Management) インターフェースにバインドしてインターフェースUUIDのリストを取得しようとします。これが利用できない場合、rpcmap.py
は既知の一般的なインターフェースUUIDのリストを使用し、それぞれへのバインドを試みます。
主要なコマンドラインオプション
rpcmap.py
は、スキャン動作をカスタマイズするための様々なオプションを提供しています。rpcmap.py -h
でヘルプメッセージを表示できます。以下に主要なオプションを解説します。
オプション | 説明 | 例 |
---|---|---|
target (位置引数) | ターゲットを指定します。IPアドレス、ホスト名、または完全な文字列バインディング (例: ncacn_ip_tcp:192.168.1.100[135] ) で指定できます。 | 192.168.1.100 dc01.corp.local ncacn_np:192.168.1.100[\pipe\epmapper] |
-h, --help | ヘルプメッセージを表示して終了します。 | rpcmap.py -h |
-port <ポート番号> | 接続先のポート番号を指定します。デフォルトは、プロトコルシーケンスに基づいて決定されます (例: ncacn_ip_tcp では 135)。SMB (ncacn_np ) の場合は 445 が使われることが多いです。 | rpcmap.py ncacn_ip_tcp:192.168.1.100 -port 135 |
-stringbinding <文字列バインディング> | 接続するMSRPCインターフェースの文字列バインディングを直接指定します。位置引数でターゲットを指定する代わりに使用できます。 | rpcmap.py -stringbinding 'ncacn_ip_tcp:192.168.1.100[49152]' |
-target-ip <IPアドレス> | ターゲットのIPアドレスを明示的に指定します。ターゲット名がNetBIOS名などで、名前解決ができない場合に便利です。 | rpcmap.py CORP-DC01 -target-ip 10.0.0.5 |
-auth-level <レベル> | RPC認証レベルを指定します (例: connect , call , pkt , pkt_integrity , pkt_privacy )。デフォルトは connect です。 | rpcmap.py target -auth-level pkt_privacy |
-brute-uuids | 一般的なUUIDのリストを使用して、インターフェースへのバインドを試みます。MGMTインターフェースが利用できない場合に役立ちます。 | rpcmap.py target -brute-uuids |
-brute-opnums | 見つかった各UUIDに対して、オペレーション番号 (opnum) のブルートフォースを試みます。これにより、インターフェースがどのような関数呼び出しを受け付けるかを探ることができます。 注意: 多くの接続が発生する可能性があります。 | rpcmap.py target -brute-opnums |
-opnum-max <数値> | -brute-opnums と併用し、試行する最大のopnumを指定します。デフォルトは256です。 | rpcmap.py target -brute-opnums -opnum-max 100 |
-brute-versions | 見つかった各UUIDに対して、異なるインターフェースバージョンでのバインドを試みます。 | rpcmap.py target -brute-versions |
-version-max <数値> | -brute-versions と併用し、試行する最大のバージョン番号 (マイナーバージョン) を指定します。デフォルトは2です。 | rpcmap.py target -brute-versions -version-max 5 |
-uuid <UUID> | 特定のインターフェースUUIDのみをスキャン対象とします。 | rpcmap.py target -uuid e1af8308-5d1f-11c9-91a4-08002b14a0fa |
-debug | デバッグモードを有効にし、詳細なログ情報を表示します。トラブルシューティングに役立ちます。 | rpcmap.py target -debug |
認証関連オプション | ||
<ドメイン>/<ユーザー名>:<パスワード>@<ターゲット> | ユーザー名とパスワードで認証します。 | rpcmap.py CORP/Administrator:Password123@192.168.1.100 |
-hashes <LMHASH:NTHASH> | パスワードの代わりにLMハッシュとNTハッシュを使用して認証します (Pass-the-Hash)。 | rpcmap.py CORP/Administrator@192.168.1.100 -hashes aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 |
-no-pass | パスワードの入力を求めません (例: -k オプション使用時)。 | rpcmap.py -k -no-pass target |
-k | Kerberos認証を使用します。事前に有効なKerberosチケットキャッシュ (ccache) が必要です (環境変数 KRB5CCNAME で指定)。 | export KRB5CCNAME=/tmp/kerberos.ccache rpcmap.py -k -no-pass target |
-aesKey <ヘキサキー> | Kerberos認証用のAESキー (128/192/256ビット) を指定します (Pass-the-Key)。 | rpcmap.py -k -no-pass -aesKey deadbeef... target |
これらのオプションを組み合わせることで、特定の状況に合わせてRPCインターフェースのスキャンを詳細に制御できます。例えば、特定のユーザーの認証情報を使用して、SMB経由でRPCインターフェースを調査する場合は、次のようにします。
rpcmap.py -port 445 ncacn_np:192.168.1.100 CORP/User1:Pa$$w0rd@192.168.1.100
出力結果の解釈
rpcmap.py
の実行結果は、ターゲットシステムで発見されたRPCインターフェースに関する情報を提供します。典型的な出力は以下のようになります。
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Retrieving endpoint list from ncacn_ip_tcp:192.168.1.100
[*] Trying ncacn_ip_tcp:192.168.1.100[135]
Protocol: ncacn_ip_tcp
Provider: rpcss.dll
UUID: e1af8308-5d1f-11c9-91a4-08002b14a0fa v3.0
Annotation: Remote Procedure Call Endpoint Mapper
Bindings: ncacn_ip_tcp:192.168.1.100[135] Status: ACTIVE ncacn_np:192.168.1.100[\PIPE\epmapper] Status: ACTIVE ncacn_ip_tcp:192.168.1.100[49664] Status: ACTIVE ncacn_ip_tcp:192.168.1.100[593] Status: ACTIVE
Protocol: ncacn_ip_tcp
Provider: scmr.dll
UUID: 367abb81-9844-35f1-ad32-98f038001003 v2.0
Annotation: Service Control Manager Remote Protocol
Bindings: ncacn_ip_tcp:192.168.1.100[49667] Status: ACTIVE ncacn_np:192.168.1.100[\PIPE\svcctl] Status: ACTIVE
... (他のインターフェース情報が続く) ...
出力の主要な要素を解説します。
[*] Retrieving endpoint list from ...
: どのターゲットとプロトコルシーケンスに対してスキャンを開始したかを示します。[*] Trying ...
: 具体的にどのエンドポイントに接続を試みているかを示します。Protocol:
このインターフェースが通信に使用しているプロトコルシーケンス (例:ncacn_ip_tcp
,ncacn_np
)。Provider:
このRPCインターフェースを提供するDLLファイル名(判明している場合)。これはサービスの特定に役立ちます。UUID:
インターフェースの一意識別子 (Universally Unique Identifier) とバージョン番号 (例:v3.0
)。UUIDはインターフェースの種類を特定するための鍵となります。Annotation:
インターフェースに関する簡単な説明や既知の名称 (例: “Remote Procedure Call Endpoint Mapper”, “Service Control Manager Remote Protocol”)。Bindings:
このインターフェースが実際に待ち受けている具体的なエンドポイントのリスト。各バインディングには、プロトコルシーケンス、ネットワークアドレス、エンドポイント(ポート番号やパイプ名)、およびステータス(通常はACTIVE
)が含まれます。
この情報から、攻撃者はターゲットシステムでどのようなサービスが動作しており、それらにどのように接続できるかを把握できます。例えば、上記の例では、Endpoint Mapper (UUID: e1af8308...
) が TCPポート 135, 49664, 593 および Named Pipe \PIPE\epmapper
で待ち受けていることがわかります。また、Service Control Manager (UUID: 367abb81...
) は TCPポート 49667 および Named Pipe \PIPE\svcctl
でアクセス可能です。
特定のUUIDが何を表すかについては、Microsoftの[MS-RPCE]: Remote Procedure Call Protocol Extensionsなどのドキュメントや、Web検索で調べることができます。これにより、発見されたインターフェースがどのような機能を提供し、潜在的な攻撃対象となりうるかを評価できます。
高度な使用例と応用シナリオ
認証付きスキャン
NULLセッションではアクセスできないインターフェース情報を取得するために、有効な認証情報を使用します。
# パスワード認証
rpcmap.py CORP\\svc_account:MyPassword@10.0.0.10
# Pass-the-Hash
rpcmap.py -hashes :NTHashValue CORP\\Administrator@10.0.0.10
# Kerberos認証 (事前に kinit などでチケット取得)
export KRB5CCNAME=/tmp/krb5cc_myticket
rpcmap.py -k -no-pass 10.0.0.10
認証されたセッションでは、より多くの、あるいはより機密性の高いRPCインターフェース情報が明らかになる可能性があります。
特定のインターフェースの探索
特定の脆弱性に関連するインターフェースや、関心のあるサービス (例: Print Spooler (MS-RPRN), Task Scheduler (MS-TSCH)) が存在するかを確認したい場合、-uuid
オプションを使用します。
# Print Spooler (MS-RPRN) のUUIDを指定してスキャン
rpcmap.py 192.168.1.100 -uuid 12345678-1234-abcd-ef00-0123456789ab
(注: 上記UUIDは例です。実際のMS-RPRNのUUIDを使用してください。)
また、rpcdump.py
(同じくImpacketのツール)と組み合わせて使うことも有効です。rpcdump.py
はエンドポイントとそのバインディングをリストアップし、rpcmap.py
は特定のインターフェースが実際にバインド可能かを確認します。
# rpcdumpでエンドポイントリストを取得
rpcdump.py @192.168.1.100
# rpcdumpの結果から特定のエンドポイントをrpcmapで調査
rpcmap.py ncacn_ip_tcp:192.168.1.100[49152]
ブルートフォースオプションの活用
-brute-uuids
, -brute-opnums
, -brute-versions
は、未知の、あるいは文書化されていないインターフェースや機能を発見するために使用できますが、注意が必要です。
# 一般的なUUIDを試す
rpcmap.py 192.168.1.100 -brute-uuids
# 特定のインターフェースのOpnumを0から50まで試す
rpcmap.py 192.168.1.100 -uuid 367abb81-9844-35f1-ad32-98f038001003 -brute-opnums -opnum-max 50
警告: ブルートフォースオプション、特に -brute-opnums
は、ターゲットシステムに対して大量の接続試行を発生させます。これはシステムのパフォーマンスに影響を与えたり、セキュリティ監視システムによって検知されたりする可能性があります。使用する際は、影響を十分に理解し、許可された環境でのみ実行してください。
ペネトレーションテストにおける役割
rpcmap.py
は、ペネトレーションテストの情報収集フェーズで非常に役立ちます。
- サービス特定: ターゲットでどのようなWindowsサービスが動作しているかを特定します (例: Service Control Manager, Task Scheduler, Remote Registry)。
- 攻撃経路の発見: 特定されたサービスやインターフェースに関連する既知の脆弱性 (例: PrintNightmare (MS-RPRN), ZeroLogon (MS-NRPC)) の存在を示唆する可能性があります。
- アクセス制御の評価: 認証なし (NULLセッション) でアクセス可能なインターフェースと、認証が必要なインターフェースを区別することで、システムのアクセス制御設定の堅牢性を評価します。
- ラテラルムーブメントの足がかり: 発見されたRPCインターフェースは、他のImpacketツール (例:
services.py
,atexec.py
,wmiexec.py
) を使用したラテラルムーブメント(横方向への侵害拡大)のターゲットとなり得ます。
例えば、rpcmap.py
で \PIPE\svcctl
(Service Control Manager) がアクセス可能であることがわかれば、services.py
を使ってリモートでサービスを操作できる可能性があります。
セキュリティ上の意味合いと対策
rpcmap.py
によって収集される情報は、攻撃者にとって非常に価値があります。公開されているRPCインターフェースは、潜在的な攻撃対象領域 (Attack Surface) を示しています。特に、認証なしでアクセス可能なインターフェースや、既知の脆弱性を持つインターフェースは、システム侵害のリスクを高めます。
リスク
- 情報漏洩: システム構成、実行中のサービス、場合によってはユーザー情報などが漏洩する可能性があります。
- 脆弱性の悪用: 特定されたインターフェースに存在する既知または未知の脆弱性が悪用され、リモートコード実行や権限昇格につながる可能性があります (例: 2022年のCVE-2022-26809 MSRPC脆弱性)。
- サービス運用妨害 (DoS):
-brute-opnums
のようなスキャンは、意図せずともターゲットサービスに負荷をかけ、応答不能にする可能性があります。 - ラテラルムーブメント: 攻撃者がネットワーク内部に侵入した後、RPCインターフェースを利用して他のシステムへ侵害を拡大する足がかりとされることがあります。
対策
RPCインターフェースに関連するリスクを軽減するためには、以下のような対策が考えられます。
- ファイアウォールによるアクセス制御: 不要なRPCポート (特にTCP 135, 139, 445, 593 および動的RPCポート範囲) へのアクセスを、信頼されたネットワークやホストからのみに制限します。
- RPCフィルターの設定: Windowsファイアウォールなどの機能を使用して、特定のRPCインターフェースUUIDへのアクセスを制御します。不要なインターフェースへのアクセスをブロックします。
- 認証の要求: RPCインターフェースへのアクセスには、常に認証を要求するように設定します。NULLセッションでのアクセスを無効化します (ただし、互換性の問題に注意が必要です)。
- 不要なサービスの無効化: システム上で不要なサービスは停止し、無効化します。これにより、関連するRPCインターフェースも公開されなくなります。
- パッチ適用: OSやアプリケーションに存在する既知の脆弱性を修正するため、セキュリティパッチを迅速に適用します。
- ネットワークセグメンテーション: ネットワークをセグメント化し、重要なサーバーへのアクセスを制限します。
- セキュリティ監視: RPC関連の異常なトラフィックや接続試行を監視し、検知する仕組みを導入します (例: EDR, SIEM)。
rpcmap.py
のようなツールは、これらの対策が適切に機能しているかを確認するための監査ツールとしても有効活用できます。定期的なスキャンにより、意図せず公開されているインターフェースや設定ミスを発見することができます。
まとめ
Impacketの rpcmap.py
は、Windowsネットワーク環境におけるMSRPCインターフェースの調査に不可欠なツールです。ターゲットシステムで公開されているRPCサービスとそのエンドポイントを特定し、システムの攻撃対象領域を理解する上で重要な情報を提供します。
基本的な使い方から、認証オプション、ブルートフォース機能まで、rpcmap.py
は多様なスキャンシナリオに対応できます。しかし、その強力さゆえに、使用には注意が必要です。特にブルートフォースオプションは、ターゲットシステムへの影響や検知リスクを伴います。
セキュリティ専門家は、rpcmap.py
を用いて自組織のシステムの脆弱性を評価し、適切なアクセス制御やパッチ適用といった対策を講じることが推奨されます。一方で、攻撃者も同様のツールを使用して弱点を探していることを認識し、防御策を継続的に見直す必要があります。
この記事が、rpcmap.py
の理解と、Windowsネットワークセキュリティの向上に役立つことを願っています。 Happy Hacking (ethically, of course)!