PowerShellのトランスクリプトの分析

ライド・カロとLiisa Tallinnによる
5月28日2020

WindowsマシンでPowerShellを使用していない場合でも、敵とペンテスターはそうです。 すべてのWindowsマシンに組み込みのスクリプト環境が付属している場合、カスタムhax0rツールを使用するのはなぜですか? Powershellを使用すると、攻撃者はディスクに痕跡を残さずにほとんど何でも行うことができます。 PowerShellを攻撃者として愛していないのは間違いであり、powershellログを防御者として愛していないのは間違いです。

以下は、SpectXの無料のlog analyzerを使用して、一般的な統計情報と、解析が難しいことで知られるPowerShellトランスクリプトログから特定の洞察を得るための解析およ 現在の出力ディレクトリからファイルをインポートまたは取り込む必要はありません-SpectXは生のログで直接クエリを実行します。 生のログからクリーンなビューを作成するには、ほんの数分かかります。

私たちは、私たちの公開S3リポジトリにトランスクリプトファイルの小さなセットをアップロードしました-このサンプルデータに以下のクエリを クエリで私たちが尋ねた質問は、ベースラインを探索し、異常な(潜在的に悪意のある)動作を発見することを目的としています。 トップコマンドは何を実行しましたか? ほとんどのコマンドはいつ実行されましたか? 彼らはいつ初めて走ったのですか? コマンドを実行したときにコンソールに表示されたコマンド出力は何でしたか-珍しいものは何ですか? トップユーザーは誰ですか? 実行すべきではないコマンドを実行しているユーザーはいますか? トップホストアプリケーション? 時間/日/週あたりどのように多くのコマンド? 難読化されたコマンドはどうですか? というように-あなたはSpectXクエリのこつを取得したら、フォローアップの質問は停止することはありません。

目次

転写物について
転写ログを有効にする方法
転写ログの形式
SpectXでログを読み取り、解析する
誰ですか? 何? いつ? どう? -クエリ

転写産物はそれをすべて知っています。.. またはほぼPowerShell

PowerShellで有効にできるロギングには、モジュールロギング、スクリプトブロック、トランスクリプションの3つのタイプがあります。 最初の2つはWindowsイベントとして表示されるため、最初の2つの監視で問題が発生した場合にのみ、トランスクリプトテキストファイルを手動で読 同時に、トランスクリプトに含まれる情報は三つの中で最も包括的であり、フラットテキストファイルは、モジュールやスクリプトブロックのログによ たとえば、単純な書き込みホスト’hello world’またはこの場合は’All You Need is Logs’を実行すると、モジュールとスクリプトブロックのログから22のWindowsイベントが生成さこんにこんにこんにこんにこんにこんにこんにこんにこんにちは、同じ情報とコマンド出力もこの1KBのPowerShellトランスクリプトに記録されます。:

**********************
Windows PowerShell transcript start
Start time: 20200521135800
Username: DESKTOP-7KL6SCQ\Loki
RunAs User: DESKTOP-7KL6SCQ\Loki
Configuration Name:
Machine: DESKTOP-7KL6SCQ (Microsoft Windows NT 10.0.18363.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 5624
PSVersion: 5.1.18362.752
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.18362.752
BuildVersion: 10.0.18362.752
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20200521135818
**********************
PS C:\Users\Loki> write-host "All You Need is Logs"
All You Need is Logs
**********************
Command start time: 20200521135821
**********************
PS C:\Users\Loki> exit
**********************
Windows PowerShell transcript end
End time: 20200521135821
**********************

問題は-トランスクリプトログは歴史的にデバッグ目的、つまり機械ではなく人間が読むために設計されていました。 彼らのコンテンツはほとんど自由形式であり、解析するのが難しいことで有名です。 ウェブを掘り下げてみると、ウェブ上で転写物をログ処理ツールに取り込む試みがいくつかありますが、コマンドの抽出やコマンド出力を別々のフィー コマンド出力は転写産物にのみ記録され、PSコマンドの結果として実際に何が起こったのかの洞察は貴重なものになるため、これは残念です。
インジェクションフェーズをスキップし、構文解析言語でビルディングブロックを使用すると、プロローグのユーザーフィールドとホスト/マシンフィールドだけでなく、コマンドの開始時間、コマンド、出力も抽出できます。 SpectXのパーサーは、クエリの実行時に生のログファイルに適用されるため、ログ形式が変更された場合に備えて、各クエリでパーサーをデバッグ、拡張、修正するこ とパスワードを入力してください。

この記事を書き始めたとき、私たちはすべてのことを記録していると信じていました。 しかし、コマンドと出力で遊んでみると、例外があることが判明しました。 URLからPSスクリプトを実行すると、トランスクリプトはコマンド(URLを含む)と出力をキャッチしますが、スクリプトの内容やスクリプトによって実行さ たとえば、urlから実行されるこの特定のスクリプトが何をしたかを知るには、モジュールログによって生成されるWindowsイベントに目を向ける必要があ

**********************
Windows PowerShell transcript start
Start time: 20200521141014
Username: DESKTOP-7KL6SCQ\Loki
RunAs User: DESKTOP-7KL6SCQ\Loki
Configuration Name:
Machine: DESKTOP-7KL6SCQ (Microsoft Windows NT 10.0.18363.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 788
PSVersion: 5.1.18362.752
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.18362.752
BuildVersion: 10.0.18362.752
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20200521141021
**********************
PS C:\Users\Loki> iex (New-Object "net.webclient").DownloadString("http://spectx.com/test.ps1")
All You Need is Logs!
**********************
Command start time: 20200521141023
**********************
PS C:\Users\Loki> exit
**********************
Windows PowerShell transcript end
End time: 20200521141023
**********************

PowerShellトランスクリプトログを有効にする方法∞

1. スタートメニューを開き、”gpedit”と入力して、ローカルグループポリシーエディターウィンドウを開きます

2. 管理テンプレート>Windowsコンポーネント>Windows PowerShellに移動します

3. “をクリックして、”‘

4. “有効”を選択し、出力ディレクトリへのパスを指定します。 重要! 呼び出しヘッダーをオンにするには、チェックボックスをオンにします。 これにより、各コマンドの実行がコマンドの開始時刻とともに記録されます。

5. クリックOK
6. PowerShellウィンドウを開き、ログが機能するかどうかをテストします。 コマンドを入力します。 単純な書き込みホスト:’必要なのはログだけです’の後に’exit’が続きます。

7. 手順4で指定した出力ディレクトリに、手順6でタイムスタンプとアクションを含むトランスクリプトが含まれているかどうかを確認します。

長期的には、PowerShellのトランスクリプトのコレクションを一元化して、大規模に分析することをお勧めします。 4sysopsブログの@dan_franciscusによるこのチュートリアルを確認してください。

トランスクリプトログフォーマット¶

ログフォーマットとパーサーロジックについてのいくつかの単語。 クエリを取得したいが、ログファイルとパーサーの構造にあまり興味がない場合は、次のセクションにスキップしてください。 生のPS v.5.1トランスクリプトログのサンプルは次のとおりです:

**********************
Windows PowerShell transcript start
Start time: 20171030223248
Username: WIN-FT17VBNL4B2\Administrator
RunAs User: WIN-FT17VBNL4B2\Administrator
Machine: WIN-FT17VBNL4B2 (Microsoft Windows NT 10.0.14393.0)
Host Application: C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell.exe
Process ID: 4268
PSVersion: 5.1.14393.1770
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.14393.1770
BuildVersion: 10.0.14393.1770
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20171030223255
**********************
PS C:\Users\Administrator> echo test
test
**********************
Command start time: 20171030223256
**********************
PS C:\Users\Administrator> exit
**********************
Windows PowerShell transcript end
End time: 20171030223256
**********************

各PowerShellセッションでトランスクリプトファイルが作成されます。 トランスクリプトの最初のセクションは、セッションの開始時刻、ユーザー、PowerShellのバージョンなどのセッション固有のフィールドを含むプロローグです。 その後、アスタリスクの行の後、このセッション中にコマンドと出力のコレクションが実行されます。 最後に、オプションのエピローグセクションは、セッション終了時刻を持つファイルの最後にありますが、セッションが終了コマンドで終了した場合に

プロローグとエピローグの間のコマンドの数は異なります。 このため、最初にプロローグ、エピローグ、コマンド出力を一括で解析し、次にコマンドと出力をクエリレイヤーの別々のフィールドに抽出するという2つのステッ

トランスクリプトの読み取りと解析方法¶

SpectXは生のログファイルから直接データを読み取り、実行時にそれらを解析します。 つまり、各PowerShellコマンドはコマンドの開始時刻で記録されます。 成績証明書をきれいな表として表示するには:

1. 無料SpectXをダウンロードしてインストールします。

2. このベースクエリ(Github)をクエリウィンドウにコピーします

3. トランスクリプトログファイルの出力ディレクトリと一致するように、47行目のパスを変更します。 パス内の時間変数を変更しないでください-これは、ファイルパス内のタイムスタンプに基づいてログをフィルタリングすることができます。 たとえば、トランスクリプトファイルの1つへのパスが

C:\Logs\powershell200405\PowerShell_transcript.WS01.5OoA7WLR.20200405152828.txt

の場合、SpectXクエリ内のURIは、spectxクエリ内の同様のパスを持つすべてのログファイルを指C:\Logs\powershell フォルダは次のようになります:

file:/C:/Logs/powershell/$yyyy$$MM$$dd$/PowerShell_transcript.*.$yyyy$$MM$$dd$$HH$$mm$$ss$.txt

4. 古い/新しいログを見たい場合は、スクリプトの冒頭(2-4行目)のinit-scriptの日数を変更してください。

5. [実行]を押します。 結果は次のようになります:

誰? 何? いつ? どう? クエリ∞

ログから質問をするときは、既知のものか未知のものを探しています。 既知のものを探すのは簡単です-必要なデータをフィルタリングするだけです。 たとえば、

| filter(lower(output) CONTAINS 'error') 

は、出力に文字列’error’を含むすべてのコマンドを提供します。

特定の期間を確認する場合は、ベースクエリスクリプトの先頭にタイムスタンプを含むinitブロックを変更します。

あなたが未知のものを探していて、珍しいものにドリルダウンしたいのであれば、それはより面白くなります。 ここでの最初のステップは、ベースラインを確立することです-通常は、あなたが興味がないものとして除外します。 たとえば、コマンドが最初に実行されたときを見てから、他のコマンドよりも後に最初に表示されたコマンドに焦点を当てることです(以下のサンプルクエリ#2を参照)。
これらのクエリをコピーして、ベースクエリの最後に1つずつ貼り付けます。 レコードをダブルクリックしてすべての内容を表示し、フィールドを右クリックして(負の)フィルタを適用します。

1. トップコマンド

| select(cnt:count(*), command)
| group(@2)
| sort(cnt DESC)

2. コマンドが初めて実行されたのはいつですか?

| select(min(commandStartTime),count(*),command,*)
| group(command)
| sort(min_commandStartTime)

3. トップコマンドと出力のペア

| select(cnt:count(*), command,output)
| group(command,output)
| sort(cnt DESC)

4. 1時間あたりのコマンド数

| select(count(*),trunc_cmd_start:commandStartTime)
| group(trunc_cmd_start)

5. おそらく手動で書かれたコマンド、すなわち’c’で始まるコマンド:\\’

| select(start_time, end_time, Username, RunAs_User, Machine, PID, PSVersion, commandText)
| filter(lower(commandText) contains 'c:\')

6. 出力フィールドをもう一度解析して、commandTextのIPアドレスを検出します

| select(parse("DATA* IPADDR:ip DATA*", commandText), commandText, *)
| filter_out(ip IS NULL)

7. 難読化されていてもcommand_output内の文字列’download’を見つけます(句読点を削除します)。 たとえば、invoke-commandが次のようになっているとします:

| select(deobf_commandText:lower(REPLACEALL(commandText, "" , '')) ) 
| filter(deobf_commandText contains 'download')

一般統計

8. 時間あたりどのように多くのPowerShellセッション?

| select(start_time:start_time,count(*))
| group(start_time)

9. トップ100ユーザー名

| select(Username, cnt:count(*))
| group(@1)
| sort(cnt DESC)
| limit(100)

10. ユーザーがマシンごとに生成したレコードの数

| select(Username,Machine,cnt:count(*))
| group(@1,@2)
| limit(100)

11. トップホストアプリケーション-PowerShellを実行するアプリケーションのリスト。

| select(cnt:count(*),Host_Application)
| group(@2)
| sort(cnt DESC)
| limit(100)

12. ユーザーごとの上位100ホストアプリケーション

| select(Host_Application, Username, cnt:count(*))
| group(@1,@2)
| sort(cnt DESC)
| limit(100)

13. コマンドの句読点を詳しく見てみましょう。 外れ値(カウントが小さい)であるコマンドは、詳細な外観に値します。

| select(PUNCT(command, 64, false), cnt:count(*),uniq_commands:ARRAY_LEN(ARRAY_UNIQ(ARRAY_AGG(command))),commands_array:ARRAY_UNIQ(ARRAY_AGG(command)))
| group(@1)
| sort(cnt)
| limit(100)

結論

PowerShellのトランスクリプトログはマシンにとって読みやすくはありませんが、それらに含まれる情報は包括的であり、分析する価値があります。 結局のところ、PowerShellはWindowsのほぼすべてのタスクを自動化および構成するためのツールです-それは「それらすべてを支配するリング」です。 PowerShellの統計、コマンド、およびそれらの出力に焦点を当てて見ることは、リングが間違った手に入っていないか、無知に使用されていないことを確認する
謝辞
ありがとう[email protected]セキュリティを明確にしました。 Hunt The Hackerコースの成績証明書は、この記事の素晴らしい出発点でした。

記事へ戻る

コメントを残す

メールアドレスが公開されることはありません。