[PowerShell] HEY YOU WHAT'S YOUR NAME?アクセスしてるのはお前さBABY!アカウント名をセキュリティログから取るぜ!
皆さんごきげんよう。ういこです。気が付いたら 6 月。カエル型宇宙人がいたら肌艶が良くなりそうな気候になっていますが私の肌艶は全然よくなりません。ヒアルロン酸が足りないんでしょうか。さて今日は、『セキュリティ イベントログを PowerShell で取る際「アカウント名」を引っこ抜く方法』をお送りします。
【今日のお題】 オレをすりこぎにしちまった奴 そいつは誰だ 誰なんだ HEY YOU HEY YOU WHAT'S YOUR NAME? -- 左とん平「とん平のヘイ・ユウ・ブルース」より |
(※) 敬称略
…一応、Script 担当チームとして Hey, Scripting Guy! を気取ってみましたが、いきなりやらかした感じですみません。なんか引用とかして見たかったんです。すりこぎとか意味不明すぎますね。すみません。いきなりこのページをご参照頂いた方、当ブログは決して怪しいブログではありませんので、ご安心ください。 ちなみに名曲です。
セキュリティ イベントログからアカウント名を取得する - コマンドレット Get-EventLog・Get-WinEvent
さて、世迷言は置いておいて、唐突ですが、システム管理者様に取って、必要不可欠ながら手がかかるので愛憎合いまみえることもあるものの一つ…そのなかにイベント ログは入っていらっしゃいませんか?特にセキュリティ イベントログ。 監査増やした日にはあっという間にログが流れていくわ、WMI で取ろうとするとバッファサイズ超えることもありえるわ、だけど保存しなきゃ…と、すごく手がかかる子です。その辺の話は、過去熱く語ったことがあります。
[WMIは万能ではない] 大容量イベントログ取得時によくある問題と回避策 ~ Script からも wevtutil.exe が使える ~
https://blogs.technet.com/b/jpilmblg/archive/2011/02/15/wmi-script-wevtutil-exe.aspx
イベントログを取るコマンドレットとして、Windows PowerShell には、以下の二つがあります。
・Get-EventLog
古い Windows XP / Windows Server 2003 以前のイベントログ形式で動作するため、処理時間のパフォーマンスに問題を及ぼす場合があります。また、Windows Vista / Windows Server 2008 以降の新イベントログ形式 (EventLog 2.0) のログは取得できません。
・Get-WinEvent
新しいイベントログ形式で動作しますし、Get-EventLog と比較すると安定した高速な動作ですが、PowerShell 2.0 以降に搭載されたコマンドレットですので OS 既定の PowerShell のバージョンが 1.0 の Windows Server 2008 無印以前では PowerShell をアップグレード頂く必要があります。
※ PowerShell 2.0 に興味をもたれた Windows Vista 以前のユーザの皆様、ダウンロードはこちらから実施いただけます!
Article ID: 968929 - Last Review: June 10, 2011 - Revision: 3.1
Windows Management Framework (Windows PowerShell 2.0, WinRM 2.0, and BITS 4.0)
(※注 : 下記文書中にダウンロード直リンク群あり)
https://support.microsoft.com/kb/968929/ja
たとえば監査ログを取っていて、「何だか変…最近わたしの可愛いサーバに誰かが繰り返し入り込もうとしているようだわ!!気持ち悪い!誰か突き止めてとっちめてやるわ!」とか、気になる人のサーバをチェックしてあげて、「べっ…別に、あなたのためにやったんじゃなくて、会社のセキュリティのためなんだからねっ!」なんて思ったとします。でもイベントログ一個一個見てると疲れるので、アクセスしている連中のアカウント名を一気にリストにして晒し挙げ差上げてやりたいときとかあるかもしれませんよね。
では、アカウント名ってどうやってとったらよいのでしょう?実は、セキュリティ イベントの中の「アカウント名」って独立したプロパティではなく、イベントログ エントリに関連付けられている文字列の中に紛れていて、抜き出さないといけません。案外面倒なのです。イベント ビューア上では綺麗にみられるのに!と思われる方、イベント ビューアは健気に水面下で激しく水を掻く白鳥のように実はがんばっているのです。材料のイベント ログそのものは XML の面倒なデータそのものだったりするのです。イベント ビューア、がんばってます!
ではアプローチ方法はないのかというと、少々泥臭い方法を取らなくてはなりません。
(1) Get-EventLog コマンドレットの場合
イベント ログ エントリに関連付けられている置換文字列 " ReplacementStrings " を取得し、配列番号を指定して抽出する。
一般的には、アカウント名は ReplacementStrings の二番目の配列 (ReplacementStrings[1]) に格納されていますので、この配列[1] を取得する対処を実施します。なお、これはあくまでも一般的なログの話であり、すべてのイベントログに共通する処理ではないことに注意が必要です。
######## コマンド例ここから、最新 15 件を取得して(-newest 15) ######## そこからさらにデータ抽出しています。 $Events = Get-Eventlog Security -newest 15 foreach ($event in $Events) { $Event.ReplacementStrings[1] } ######## コマンド例ここまで |
参考 : EventLogEntry.ReplacementStrings プロパティ
https://msdn.microsoft.com/ja-jp/library/system.diagnostics.eventlogentry.replacementstrings.aspx
(2) Get-WinEvent コマンドレットの場合
■情報を抽出する
Get-EventLog は旧来の Event Log 1.0 ベースのイベント ログ形式に対応していますが、Get-WinEvent は 2.0 以降のイベント XML 形式に対応しておりますため、以下のような段階を踏んで情報を抽出する必要があります。
1. Get-WinEvent コマンドレットにてイベントログを取得する
2. Select-Object コマンドレットにパイプで受け渡しし、-Property オプションで Property パラメーターを取得する
3. Expression キーの n 番目の値 (Value) を取得する
Property パラメーターの配列数は、"イベント XML" の下の <EventData> 要素配下の数に一致します。
<Event xmlns="https://schemas.microsoft.com/win/2004/08/events/event"> <EventData> ★ 下記要素数に一致する ………… </EventData> </Event> |
例)
######## コマンド例ここから、イベント ID 4624 15 件を取得して(-MaxEvents 15) ######## そこからさらにデータ抽出しています。 Get-WinEvent -FilterHashtable @{LogName="Security"; ID=4624} -MaxEvents 15 | Select-Object -Property @{n="Account Name of SUBJECT AREA";e={$_.properties[1].value}} ######## コマンド例ここまで |
図 1 : アカウント名が二つある場合もある
図 2 : アカウントが “-” ハイフンになっている場合もある
実行結果例)
Account Name of SUBJECT AREA ---------------------------- UIKOU-SEVEN$ - UIKOU-SEVEN$ - UIKOU-SEVEN$ |
■イベントログの Property 要素数
イベント ビューアで個別のイベントを開くと、[詳細] タブが選択できます。このタブには、XML が表示されています。
例)
イベント XML: <Event xmlns="https://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" /> <EventID>4624</EventID> <Version>0</Version> <Level>0</Level> <Task>12544</Task> <Opcode>0</Opcode> <Keywords>0x8020000000000000</Keywords> <TimeCreated SystemTime="2011-05-24T07:34:53.910829500Z" /> <EventRecordID>5138894</EventRecordID> <Correlation /> <Execution ProcessID="572" ThreadID="5472" /> <Channel>Security</Channel> <Computer>uikou-seven.JPDSFIM.corp.microsoft.com</Computer> <Security /> </System> <EventData> <Data Name="SubjectUserSid">S-1-5-18</Data> <Data Name="SubjectUserName">UIKOU-SEVEN$</Data> <Data Name="SubjectDomainName">JPDSFIM</Data> <Data Name="SubjectLogonId">0x3e7</Data> <Data Name="TargetUserSid">S-1-5-21-2146773085-903363285-719344707-1205599</Data> <Data Name="TargetUserName">FABRIKAM01$</Data> <Data Name="TargetDomainName">JPDSFIM</Data> <Data Name="TargetLogonId">0xee4ced</Data> <Data Name="LogonType">3</Data> <Data Name="LogonProcessName">Advapi </Data> <Data Name="AuthenticationPackageName">Kerberos</Data> <Data Name="WorkstationName">UIKOU-SEVEN</Data> <Data Name="LogonGuid">{E7C2D064-03C2-6232-CE07-590C1823359E}</Data> <Data Name="TransmittedServices">-</Data> <Data Name="LmPackageName">-</Data> <Data Name="KeyLength">0</Data> <Data Name="ProcessId">0x3e4</Data> <Data Name="ProcessName">C:\Windows\System32\svchost.exe</Data> <Data Name="IpAddress">-</Data> <Data Name="IpPort">-</Data> </EventData> </Event> |
このうち、<Event> セクション配下には、<System> 要素と <EventData> 要素があります。<System> 要素は、それぞれ独立した名前で Property として取得できます。一例をあげますと、以下のような形になります。
> Get-WinEvent -FilterHashtable @{LogName="Security"; ID=4624} -MaxEvents 5 | Select-Object -Property ID,Keywords,ProviderName,Task ★← 独立した名前を持つプロパティ Id Keywords ProviderName Task -- -------- ------------ ---- 4624 -9214364837600034816 Microsoft-Windows-Security...12544 4624 -9214364837600034816 Microsoft-Windows-Security...12544 4624 -9214364837600034816 Microsoft-Windows-Security...12544 4624 -9214364837600034816 Microsoft-Windows-Security...12544 4624 -9214364837600034816 Microsoft-Windows-Security...12544 |
上記例では、(Event)ID、Keywords、Provider Name、Task の要素を取得して表示しています。一方、<EventData> 要素配下にあるデータを取得する際は、上述の<System> 要素内にある値と異なり、EventData のひと塊の配列として取得後、添え字(インデックス)を入れて分解する必要があります。
■EventData の文字列を分解する - イベント ID 4624 の場合の例
<EventData> <Data Name="SubjectUserSid">S-1-5-18</Data> → $_.properties[0].value <Data Name="SubjectUserName">UIKOU-SEVEN$</Data> → $_.properties[1].value <Data Name="SubjectDomainName">JPDSFIM</Data> → $_.properties[2].value <Data Name="SubjectLogonId">0x3e7</Data> → $_.properties[3].value <Data Name="TargetUserSid">S-1-5-21-2146773085-903363285-719344707-1205599</Data> → $_.properties[4].value <Data Name="TargetUserName">FABRIKAM01$</Data> → $_.properties[5].value <Data Name="TargetDomainName">JPDSFIM</Data> → $_.properties[6].value <Data Name="TargetLogonId">0xee4ced</Data> → $_.properties[7].value <Data Name="LogonType">3</Data> → $_.properties[8].value <Data Name="LogonProcessName">Advapi </Data> → $_.properties[9].value <Data Name="AuthenticationPackageName">Kerberos</Data> → $_.properties[10].value <Data Name="WorkstationName">UIKOU-SEVEN</Data> → $_.properties[11].value <Data Name="LogonGuid">{E7C2D064-03C2-6232-CE07-590C1823359E}</Data> → $_.properties[12].value <Data Name="TransmittedServices">-</Data> → $_.properties[13].value <Data Name="LmPackageName">-</Data> → $_.properties[14].value <Data Name="KeyLength">0</Data> → $_.properties[15].value <Data Name="ProcessId">0x3e4</Data> → $_.properties[16].value <Data Name="ProcessName">C:\Windows\System32\svchost.exe</Data> → $_.properties[17].value <Data Name="IpAddress">-</Data> → $_.properties[18].value <Data Name="IpPort">-</Data> → $_.properties[19].value </EventData> |
※ properties[20] のように、データが存在する数以上の添え字を指定しても空白のみが返ります。
■ "アカウント名" が二つあるログの場合もある
「アカウント名」が表示上二つ存在するイベントも存在します。上記のイベントを例にとりますと、配列要素 2 番目 ($_.properties[1].value) “SubjectUserName” および配列要素 6 番目 ($_.properties[5].value) が "アカウント名 = TargetUserName" として
イベント ビューア上に表記されている値と一致します。
<EventData> <Data Name="SubjectUserSid">S-1-5-18</Data> <Data Name="SubjectUserName">UIKOU-SEVEN$ </Data> <Data Name="SubjectDomainName">JPDSFIM</Data> <Data Name="SubjectLogonId">0x3e7</Data> <Data Name="TargetUserSid">S-1-5-21-2146773085-903363285-719344707-1205599</Data> <Data Name="TargetUserName">TK5-DFS-02$ </Data> <Data Name="TargetDomainName">JPDSFIM</Data> <Data Name="TargetLogonId">0xee4ced</Data> <Data Name="LogonType">3</Data> <Data Name="LogonProcessName">Advapi </Data> <Data Name="AuthenticationPackageName">Kerberos</Data> <Data Name="WorkstationName">UIKOU-SEVEN</Data> <Data Name="LogonGuid">{E7C2D064-03C2-6232-CE07-590C1823359E}</Data> <Data Name="TransmittedServices">-</Data> <Data Name="LmPackageName">-</Data> <Data Name="KeyLength">0</Data> <Data Name="ProcessId">0x3e4</Data> <Data Name="ProcessName">C:\Windows\System32\svchost.exe</Data> <Data Name="IpAddress">-</Data> <Data Name="IpPort">-</Data> </EventData> |
以下配列要素 6 番目 ($_.properties[5].value) が "アカウント名" としてとってきた際のスクリーンショットです。
以下のように参照頂ければ、情報は取得できるかと存じます。下記の例では、サブジェクトの "アカウント名" を取得しています。アカウント名は、配列 2 番(添え字 1) ですので、以下のような取得方法になります。
例)
Get-WinEvent -FilterHashtable @{LogName="Security"; ID=4624} -MaxEvents 15 | Select-Object -Property @{n="SubjectUserName";expression={$_.properties[1].value}}
補足 : 各イベントごとの要素配列の設計資料などについて
なお、Select-Object コマンドレットは、配列の名前を付けなおすこともできます。後述 "■参考資料" 中の MSDN マガジンの記事などがご参考になるかと思います。イベント ID によって要素の配列位置が移動する可能性もありますので、# のコメントで参照データ名を PS1 ファイル内に記載しておき、万が一将来参照先のイベントログの ID を変える必要ができた時などは、配列の添え字だけ変えることで対処するということもよいでしょう。
(例: 二番目から八番目に参照箇所を変える場合 /
$_.properties[1].value -> $_.properties[7].value など)
■注意 : 配列内部のデータフォーマットは各イベント ID ごとに配列のデータ配置が違う可能性がある
イベントは、各ソース、ID 毎にフォーマットが異なります。「概ね共通して同じような形式」ではありますが、明示的に「配列の何番に何を入れなければならない」ということは決まっていないということがどうしてもあります。また今後も追加、変更される可能性などもあり、実際に確認いただきつつ必要な情報の取捨選択を実施頂く必要があります。Message プロパティ内にどれだけのイベントログ内の情報を採れるかについては、そのイベントログの構造に依存する動作になります。コマンドレットはイベントログに取得を依頼したあとは、そのログが返すデータをそのまま格納するため、イベント ログそれぞれがどのようにデータを渡してくるかまでは(明らかに NULL の場合などを除き)特に形式や中身を意識しないためです。
■参考資料
Select-Object
https://technet.microsoft.com/ja-jp/library/dd315291.aspx
Windows PowerShell の機能 Select-Object コマンドレットの使用
https://technet.microsoft.com/ja-jp/library/ee176955.aspx
Windows PowerShell 続すてきなパイプラインの手法
(Select-Object による要素の rename など)
https://technet.microsoft.com/ja-jp/magazine/ff394367.aspx
Windows PowerShell: コマンドを再利用可能なツールにする
https://technet.microsoft.com/ja-jp/magazine/gg537351.aspx
さて、すごく久しぶりに書いたのでちょっと緊張しております。少しでも皆様のイベントログ管理の負担が減って、すりこぎにされそうな日々が解消しますように。
それでは皆様ごきげんよう。
ういこう@人生はすりこぎなんだよ! OH MY BABYこのブルースを聴いてくれ!!