コンテンツにスキップ

NetExec と WinRM による列挙

HTB の Windows / Active Directory マシンで初期資格情報を得たあと、NetExec で何を確認し、WinRM 接続後にどこを調べるかを順にまとめます。

扱う範囲は次の通りです。

  • netexec / nxc による SMB、LDAP、WinRM の初期確認。
  • 共有、ユーザー、グループ、コンピュータ、WinRM 候補の見方。
  • WinRM 接続後のユーザー、ホスト、ファイル、資格情報、ドメイン、共有の手動列挙。
  • 手動列挙の見落としを winPEAS で確認する方法。

AD の ACL や Kerberos 委任など、個別の仕組みは関連ページで詳しく扱います。

最初に target、domain、DC の名前解決を固定する。

<dc-ip> <dc-fqdn> <domain> <hostname>

例:

10.129.13.247 DC01.checkpoint.htb checkpoint.htb DC01

以後のコマンド例では次を使う。

ターミナルウィンドウ
DC='<dc-fqdn-or-ip>'
DC_FQDN='<dc-fqdn>'
DOMAIN='<domain>'
REALM='<DOMAIN uppercase>'
USER='<user>'
PASS='<password>'
HASH='<nt-hash>'

Kerberos を使う場合は、IP ではなく FQDN を優先する。/etc/hosts で名前解決できても、MIT Kerberos の realm mapping が合っていないと TGT/TGS 取得で失敗することがある。

netexec に入る前に、Nmap の出力から環境の前提を読む。

観察読み方
53, 88, 389, 445, 464, 3268, 9389Domain Controller (DC) として扱う根拠になる。
389 / 3268 に Domain: <domain>LDAP / Global Catalog から domain 名が取れている。
5985/tcp open有効な資格情報を得たら WinRM を試す価値がある。ただし認可までは意味しない。
smb2-security-mode: signing requiredSMB relay を主経路にせず、認証済み SMB/LDAP/Kerberos 列挙を優先する。
clock-skew が大きいKerberos、BloodHound/RustHound、TGS 要求の失敗原因になる。
LDAP signing / channel binding / NTLM:FalseLDAP の認証方式、relay 可否、Kerberos 必須化の判断材料になる。

Kerberos で KRB_AP_ERR_SKEW が出る場合は、攻撃端末側の時刻を target に合わせる。HTB では ntpdate <dc-fqdn> や faketime を使った記録がある。

ターミナルウィンドウ
sudo ntpdate "$DC_FQDN"
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' <kerberos-command>

初期資格情報を得たら、まず protocol ごとに認証と認可を分けて見る。

ターミナルウィンドウ
netexec smb "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS"
netexec ldap "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS"
netexec winrm "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS"

見るべき分離は次の通り。

結果意味
SMB +credential が SMB で受理された。共有を読めるとは限らない。
LDAP +AD object の認証済み列挙に使える。WinRM 可能とは限らない。
WinRM + / Pwn3d!WinRM shell の候補。evil-winrm で prompt を取って事後確認する。
WinRM -password 不正とは限らない。Remote Management Users などの認可不足や認証方式不一致を疑う。
STATUS_NOT_SUPPORTED と NTLM:FalseNTLM が無効または使えない可能性が高い。Kerberos に切り替える。
No Kerberos credentials availablepassword ではなく ccache 選択の問題。

Puppy、Pirate、Checkpoint では、SMB/LDAP は成功しても初期ユーザーでは WinRM できない状態があった。一方 Administrator では初期ユーザーが WinRM まで通っている。5985 が開いていること、資格情報が正しいこと、WinRM への認可があることは別々に確認する。

NTLM が使えない、Protected Users に入っている、または Kerberos を明示したい場合は TGT を取って cache を使う。

ターミナルウィンドウ
getTGT.py "$DOMAIN/$USER:$PASS" -dc-ip '<dc-ip>'
export KRB5CCNAME="$USER.ccache"
netexec smb "$DC_FQDN" --use-kcache --shares --rid-brute
netexec ldap "$DC_FQDN" --use-kcache --users --groups --computers
netexec winrm "$DC_FQDN" --use-kcache

WinRM / WSMan は HTTP/<host> service principal (SPN) の TGS を使う。TGT は KDC に認証済みであることを示す ticket であり、WinRM サーバーに直接提示する ticket ではない。KRB_AP_ERR_MODIFIED が出る場合は、hostname、SPN、realm、ccache を疑う。

/etc/hosts に FQDN を書いただけでは、MIT Kerberos が <dc-fqdn> を正しい realm に属すると判断できないことがある。その場合は target ごとの krb5.conf を作り、KRB5_CONFIG で明示する。

一時的に使うなら /tmp に置く。

ターミナルウィンドウ
cat > /tmp/krb5-example.conf <<'EOF'
[libdefaults]
default_realm = EXAMPLE.HTB
dns_lookup_realm = false
dns_lookup_kdc = false
rdns = false
udp_preference_limit = 1
[realms]
EXAMPLE.HTB = {
kdc = dc01.example.htb
admin_server = dc01.example.htb
}
[domain_realm]
.example.htb = EXAMPLE.HTB
example.htb = EXAMPLE.HTB
dc01.example.htb = EXAMPLE.HTB
EOF
export KRB5_CONFIG=/tmp/krb5-example.conf

TGT を取得し、使う ccache を明示する。

ターミナルウィンドウ
getTGT.py 'example.htb/<user>:<password>' -dc-ip '<dc-ip>'
export KRB5CCNAME='<user>.ccache'
klist

TGT だけでなく、実際に使う service principal の TGS が取れるか確認する。

ターミナルウィンドウ
KRB5_TRACE=/dev/stderr kvno "ldap/dc01.example.htb"
KRB5_TRACE=/dev/stderr kvno "cifs/dc01.example.htb"
KRB5_TRACE=/dev/stderr kvno "http/dc01.example.htb"
klist
SPN主な用途
ldap/<dc-fqdn>LDAP query、BloodHound / RustHound、ADSI 系。
cifs/<dc-fqdn>SMB share、netexec smb --use-kcache。
http/<dc-fqdn>WinRM / WSMan、Evil-WinRM Kerberos。

TGS 取得で別 realm が出る、または KDC が見つからない場合は、[domain_realm]、default_realm、KRB5_CONFIG の参照先を確認する。

永続的に切り替えたい場合は、target ごとの設定を ~/.config/krb5/ に置く。

ターミナルウィンドウ
mkdir -p ~/.config/krb5 ~/.ccache
cat > ~/.config/krb5/example.htb.conf <<'EOF'
[libdefaults]
default_realm = EXAMPLE.HTB
dns_lookup_realm = false
dns_lookup_kdc = false
rdns = false
udp_preference_limit = 1
[realms]
EXAMPLE.HTB = {
kdc = dc01.example.htb
admin_server = dc01.example.htb
}
[domain_realm]
.example.htb = EXAMPLE.HTB
example.htb = EXAMPLE.HTB
dc01.example.htb = EXAMPLE.HTB
EOF

~/.zshrc や ~/.bashrc に alias を置くと、box ごとの Kerberos 設定と ccache を簡単に切り替えられる。

ターミナルウィンドウ
alias krb_example='export KRB5_CONFIG=$HOME/.config/krb5/example.htb.conf; export KRB5CCNAME=$HOME/.ccache/example.htb.ccache; klist'
alias krb_off='unset KRB5_CONFIG KRB5CCNAME'

読み込み直す。

ターミナルウィンドウ
source ~/.zshrc
# または
source ~/.bashrc

使い方。

ターミナルウィンドウ
krb_example
# kinit を使える場合は KRB5CCNAME の場所に直接 TGT を作る
kinit '<user>@EXAMPLE.HTB'
klist

Impacket getTGT.py を使う場合は、出力された ccache を alias が参照する場所へ移す。

ターミナルウィンドウ
getTGT.py 'example.htb/<user>:<password>' -dc-ip '<dc-ip>'
mv '<user>.ccache' "$HOME/.ccache/example.htb.ccache"
krb_example
netexec ldap dc01.example.htb --use-kcache --users --groups
netexec smb dc01.example.htb --use-kcache --shares
evil-winrm -i dc01.example.htb -r example.htb --ccache "$HOME/.ccache/example.htb.ccache"
krb_off

profile には password を置かない。保存するのは KRB5_CONFIG と KRB5CCNAME の切り替えだけにする。

NT hash が得られたら、まず SMB と WinRM の両方で検証する。

ターミナルウィンドウ
netexec smb "$DC" -d "$DOMAIN" -u "$USER" -H "$HASH" --shares
netexec winrm "$DC" -d "$DOMAIN" -u "$USER" -H "$HASH"
evil-winrm-py -i "$DC" -u "$USER" -H "$HASH"

machine account や gMSA は末尾の $ を shell が展開しないように quote する。

ターミナルウィンドウ
evil-winrm-py -i "$DC" -u 'gMSA_ADCS_prod$' -H '<nt-hash>'

ローカルアカウントで認証する場合

Section titled “ローカルアカウントで認証する場合”

Standalone host や local administrator credential を試すときだけ --local-auth を使う。Domain Controller 上では通常の domain auth と混同しない。

ターミナルウィンドウ
netexec smb '<host>' -u '<local-user>' -p '<password>' --local-auth
netexec winrm '<host>' -u '<local-user>' -p '<password>' --local-auth
ターミナルウィンドウ
netexec smb "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS" --shares --rid-brute

IPC$、NETLOGON、SYSVOL の READ は domain user として自然な baseline である。DEV、Logs、IT、VMBackups、DevDrop、Finance のような業務名の共有が見えたら優先して中を見る。

ターミナルウィンドウ
smbclient "//$DC_FQDN/<share>" -U "$DOMAIN/$USER%$PASS" -m SMB3

NT hash の場合:

ターミナルウィンドウ
smbclient "//$DC_FQDN/<share>" \
-U "$DOMAIN/$USER%$HASH" \
--pw-nt-hash -m SMB3

共有名が見えることと読めることは違う。Puppy では DEV は最初に見えたが、グループ所属変更後に初めて READ が得られた。Checkpoint では VMBackups が見えても初期ユーザーでは読めず、BackupAccess に属する svc_deploy で読み直して初めて使えた。

SMB share に入った後は、share root を基準にパスを書く。//dc/IT に接続しているなら remote path はすでに C:\IT 相当であり、C:\IT\... を指定すると NT_STATUS_OBJECT_NAME_INVALID になり得る。

LDAP でユーザー・グループ・コンピューターを調べる

Section titled “LDAP でユーザー・グループ・コンピューターを調べる”
ターミナルウィンドウ
netexec ldap "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS" \
--users --groups --computers

最初に見るもの。

対象注目点
userssvc_*、*_adm、職位名、description、password hint、無効化状態。
groupsRemote Management Users、業務名グループ、Backup/Recovery/IT/WSUS/Certificate 関連。
computersDC 以外の server、pre-created computer account、machine account。
gMSAmsDS-GroupMSAMembership、Remote Management Users 所属。
descriptionspassword、運用メモ、担当、共有名の手がかり。

候補ユーザーは LDAP query で絞って確認する。

ターミナルウィンドウ
netexec ldap "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS" \
--query "(sAMAccountName=<target-user>)" \
"sAMAccountName memberOf description userAccountControl servicePrincipalName"

Remote Management Users 所属は WinRM 候補であって、password や hash が正しいことの証明ではない。BackupAccess のような名前も SeBackupPrivilege とは限らない。Checkpoint の svc_deploy は BackupAccess に属していたが、whoami /all では SeBackupPrivilege はなく、実際には VMBackups share の READ につながった。

Kerberoasting と AS-REP Roasting の候補

Section titled “Kerberoasting と AS-REP Roasting の候補”

初期資格情報で AS-REP roast / Kerberoast を試す価値はあるが、空振りは珍しくない。

ターミナルウィンドウ
netexec ldap "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS" --asreproast asrep.hashes
netexec ldap "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS" --kerberoasting kerberoast.hashes

または Impacket:

ターミナルウィンドウ
GetNPUsers.py "$DOMAIN/$USER:$PASS" -dc-ip '<dc-ip>' -request -outputfile asrep.hashes
GetUserSPNs.py "$DOMAIN/$USER:$PASS" -dc-ip '<dc-ip>' -request -outputfile kerberoast.hashes

Targeted Kerberoasting は単なる列挙ではなく、対象の servicePrincipalName を一時変更できる ACL が必要になる。詳細は AD ACL ノートへ回す。

ターミナルウィンドウ
rusthound-ce -d "$DOMAIN" -f "$DC_FQDN" -u "$USER" -p "$PASS" -c All --zip

BloodHound は「最短経路を押す道具」ではなく、LDAP 属性、group membership、ACL、SPN、delegation の関係をまとめる地図として読む。

確認するときは次を分ける。

  • Principal: 誰が権限を持つか。
  • Object: どの user / group / computer / OU / domain に対する権限か。
  • Edge: GenericAll、GenericWrite、WriteOwner、AddMember、WriteSPN などの意味。
  • 実操作: password reset、group member 追加、SPN 追加、shadow credentials 追加など。
  • 再読取り: 変更後に LDAP / SMB / WinRM で事後確認できたか。

BloodHound が LDAPS へ逃げて失敗する場合、LDAPS そのものではなく Kerberos の時刻差や realm 解決が根本原因のことがある。Checkpoint では clock skew が原因で Kerberos が失敗し、NTLM LDAP に落ち、LDAP signing に阻まれ、LDAPS が reset される流れだった。

Password:

ターミナルウィンドウ
evil-winrm -i "$DC_FQDN" -u "$USER" -p "$PASS"

Kerberos:

ターミナルウィンドウ
export KRB5CCNAME="$USER.ccache"
evil-winrm -i "$DC_FQDN" -r "$DOMAIN" --ccache "$USER.ccache"

NT hash:

ターミナルウィンドウ
evil-winrm-py -i "$DC_FQDN" -u "$USER" -H "$HASH"

接続に成功したら、prompt がどの user と host を示しているかを記録する。netexec winrm の成功だけで止めず、実際の remote PowerShell prompt を事後確認にする。

症状優先して疑うこと
SMB/LDAP は +、WinRM は -WinRM 認可不足、Remote Management Users 未所属、WinRM の認証方式不一致。
No Kerberos credentials availableKRB5CCNAME または --ccache 指定漏れ。
KRB_AP_ERR_SKEWattack box と DC の時刻差。
KRB_AP_ERR_MODIFIEDSPN、hostname、realm、service ticket の不一致。WinRM では HTTP/<host> を意識する。
STATUS_NOT_SUPPORTEDNTLM 不可。Kerberos cache を使う。

最初に現在の security context を確定する。

ターミナルウィンドウ
whoami
whoami /upn
whoami /all
whoami /groups
whoami /priv
hostname

見るべき点。

観察判断
BUILTIN\Remote Management UsersWinRM できる理由。管理者権限そのものではない。
SeImpersonatePrivilege / SeAssignPrimaryTokenPrivilegetoken abuse の候補。
SeBackupPrivilege / SeRestorePrivilegeNTFS ACL を越えた backup 系読み取りや hive / NTDS 取得の候補。
SeDebugPrivilegeprocess memory / credential access の候補。
SeMachineAccountPrivilege、SeChangeNotifyPrivilege、SeIncreaseWorkingSetPrivilege 程度即時 local privesc ではなく、ファイル、共有、AD、資格情報を優先する。
Custom group共有 ACL、アプリ権限、証明書、WSUS、backup などの運用権限につながるか確認する。

whoami /all は必ず残す。Puppy の最終セッションではこれを記録しておらず、最終アカウントの正確な group / privilege を後から説明しづらくなった。

ターミナルウィンドウ
systeminfo
ipconfig /all
route print
netstat -ano

サービスとタスク:

ターミナルウィンドウ
Get-CimInstance Win32_Service |
Select-Object Name,StartName,State,PathName
Get-ScheduledTask |
Select-Object TaskName,TaskPath,State

プロセス:

ターミナルウィンドウ
Get-Process -ErrorAction SilentlyContinue |
Select-Object ProcessName,Id,Path

ここでは「全部を暗記する」より、実行ユーザー、path、書き込み可能な directory、設定ファイル、credential を探す。

ファイルシステムはルート直下から絞る

Section titled “ファイルシステムはルート直下から絞る”

いきなり C:\ 全体を再帰しない。まず root 直下を見る。

ターミナルウィンドウ
Get-ChildItem -LiteralPath 'C:\' -Force

次に意味のある候補だけを深掘りする。

ターミナルウィンドウ
$targets = @(
'C:\Backups',
'C:\inetpub',
'C:\IT',
'C:\Logs',
'C:\Shares',
'C:\StorageReports',
'C:\ProgramData'
) | Where-Object { Test-Path $_ }
if ($targets) {
Get-ChildItem -LiteralPath $targets -Force -ErrorAction SilentlyContinue
Get-ChildItem -LiteralPath $targets -Recurse -Force -ErrorAction SilentlyContinue
}

優先して見る名前。

名前意味
Backups, VMBackups, NightlyBackup設定、旧 DB、snapshot、memory dump、NTDS / hive の候補。
inetpub, wwwroot, app directoryWeb config、LDAP bind password、connection string。
IT, Dev, DevDrop, Logs運用共有、deployment artifact、script、credential leak。
StorageReports, WSUSTemp, vendor directory標準外の運用痕跡。
user profile archiveDPAPI、SSH key、browser、Credential Manager の候補。

検索は範囲を絞ってから行う。

ターミナルウィンドウ
if ($targets) {
Get-ChildItem -LiteralPath $targets -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { -not $_.PSIsContainer } |
Where-Object { $_.Length -lt 5MB } |
Select-String -Pattern 'password|passwd|pwd|secret|token|credential|ldap|bind|backup|winrm' `
-ErrorAction SilentlyContinue
}

flag や既知ファイル名の検索も範囲を限定する。

ターミナルウィンドウ
Get-ChildItem -LiteralPath 'C:\Users' -Filter 'root.txt' -Recurse -Force -ErrorAction SilentlyContinue
ターミナルウィンドウ
Get-ChildItem -LiteralPath 'C:\Users' -Force
$userDirs = @(
"$env:USERPROFILE\Desktop",
"$env:USERPROFILE\Documents",
"$env:USERPROFILE\Downloads"
) | Where-Object { Test-Path $_ }
if ($userDirs) {
Get-ChildItem -LiteralPath $userDirs -Force -ErrorAction SilentlyContinue
}

PowerShell history:

ターミナルウィンドウ
Get-Content (Get-PSReadLineOption).HistorySavePath -ErrorAction SilentlyContinue

Evil-WinRM では ls は Get-ChildItem、type は Get-Content の alias である。後から再利用するコマンドは完全名と -LiteralPath に直す。

ターミナルウィンドウ
Get-Content -LiteralPath 'C:\Users\<user>\Desktop\user.txt'

まず現在ユーザーの保存済み資格情報を確認する。

ターミナルウィンドウ
cmdkey /list
Get-ChildItem "$env:APPDATA\Microsoft\Credentials" `
-Force -ErrorAction SilentlyContinue
Get-ChildItem "$env:LOCALAPPDATA\Microsoft\Credentials" `
-Force -ErrorAction SilentlyContinue
Get-ChildItem "$env:APPDATA\Microsoft\Protect" `
-Recurse -Force -ErrorAction SilentlyContinue

他ユーザーや archived profile が読める場合は、次の組を探す。

AppData\Roaming\Microsoft\Credentials
AppData\Local\Microsoft\Credentials
AppData\Roaming\Microsoft\Protect\<SID>
AppData\Local\Microsoft\Vault

DPAPI で必要なのは、Credential Blob だけではない。

Credential Blob
|
| 参照する Master Key GUID
v
Protect\<SID>\<MasterKeyGUID>
|
| user password + SID、または domain backup key などで復号
v
decrypted masterkey
|
v
Credential Blob の復号

Puppy では Credentials と Protect\<SID> の対応を winPEAS が示し、ユーザー password と SID で Master Key を復号した。Voleur では archived profile から Credentials と Protect\<SID> を両方回収し、削除済み AD object から SID を確認した。

WinRM で入った後も、AD の事実は LDAP / AD module / ADSI で確認できる。

ターミナルウィンドウ
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = [ADSI]'LDAP://RootDSE'
$root.defaultNamingContext

現在ユーザーの group membership:

ターミナルウィンドウ
$searcher = [adsisearcher]"(sAMAccountName=$env:USERNAME)"
$result = $searcher.FindOne()
$result.Properties.memberof

ユーザーを探す:

ターミナルウィンドウ
$searcher = New-Object DirectoryServices.DirectorySearcher
$searcher.Filter = '(objectClass=user)'
$searcher.PageSize = 1000
$searcher.PropertiesToLoad.AddRange(@(
'samaccountname',
'distinguishedname',
'memberof',
'useraccountcontrol',
'description',
'serviceprincipalname'
))
$searcher.FindAll() |
ForEach-Object { $_.Properties }

AD module がある場合:

ターミナルウィンドウ
Import-Module ActiveDirectory
Get-ADUser '<user>' -Properties MemberOf,Description,ServicePrincipalName,UserAccountControl |
Select-Object SamAccountName,Enabled,Description,MemberOf,ServicePrincipalName,UserAccountControl
Get-ADPrincipalGroupMembership '<user>' |
Select-Object Name,DistinguishedName

BloodHound が見せる edge は、最終的には LDAP 属性、ACE、group membership、SPN、delegation などの事実に戻せる。グラフだけで判断せず、実際に読める属性と操作結果で裏付ける。

新しい user、hash、group membership を得たら、attacker 側から SMB shares を再列挙する。

ターミナルウィンドウ
netexec smb "$DC_FQDN" -d "$DOMAIN" -u "$USER" -p "$PASS" --shares
netexec smb "$DC_FQDN" -d "$DOMAIN" -u "$USER" -H "$HASH" --shares

WinRM target 内から見る場合:

ターミナルウィンドウ
$dc = '<dc-fqdn>'
net view "\\$dc"
net use

共有 ACL は「今の credential」で変わる。初期ユーザーで access denied だった共有でも、別ユーザー、別グループ、別 hash で読めることがある。

winPEAS は最初から答えを探すためではなく、手動列挙の抜けを確認する baseline として使う。

ターミナルウィンドウ
.\winPEASx64.exe *> C:\Windows\Temp\winpeas.txt

比較する観察点。

観察項目手動で確認winPEAS で確認次の判断
root 直下の非標準 directoryC:\Backups, C:\IT など追加候補があるか深掘り対象を限定する。
Credential Manager / DPAPICredentials, Protect\<SID>Master Key と Blob の対応復号材料が揃うか確認する。
PowerShell historyhistory path抽出漏れがあるかcommand / password leak を確認する。
services / scheduled tasksservice path、run userwritable path の候補実行コンテキストと ACL を確認する。
writable path手動 ACL / file write追加候補実行される path かを確認する。
token privilegeswhoami /all特権候補share access と token privilege を混同しない。

Living off the Land (LOTL) なら検知されないわけではない。PowerShell command line、Script Block Logging、AMSI、短時間での大量 file enumeration、WMI/CIM 列挙、資格情報 directory への access、WinRM provider host 配下の process は監視対象になり得る。巨大ツールか手動コマンドかより、何をどの範囲で読んだかを意識する。

同じ事実を複数レイヤーで取る

Section titled “同じ事実を複数レイヤーで取る”

1 つの事実を、専用ツール、OS 標準機能、LDAP / API の 3 層で確認できると強い。

例: ユーザーの group membership。

NetExec:

ターミナルウィンドウ
netexec ldap "$DC" -d "$DOMAIN" -u "$USER" -p "$PASS" \
--query "(sAMAccountName=<user>)" "sAMAccountName memberOf"

Windows 標準:

ターミナルウィンドウ
whoami /groups

AD module:

ターミナルウィンドウ
Get-ADPrincipalGroupMembership '<user>' |
Select-Object Name,DistinguishedName

ADSI:

ターミナルウィンドウ
$searcher = [adsisearcher]'(sAMAccountName=<user>)'
$searcher.FindOne().Properties.memberof

BloodHound、bloodyAD、Impacket は強力だが、裏では LDAP、Kerberos、SMB、RPC、WinRM、Windows API を使っている。ツール名ではなく、観測したい事実と使われる protocol / API を対応付ける。

目的よく使うツール別経路
SMB 共有列挙netexec smb --sharessmbclient, net view
LDAP users / groupsnetexec ldap --users --groupsADSI, Get-ADUser, ldapsearch
Kerberos TGT/TGSgetTGT.py, GetUserSPNs.pykinit, kvno, Rubeus
AD graphBloodHound / RustHoundLDAP query, AD module, ADSI
LDAP 属性変更bloodyADSet-ADUser, ADSI, ldapmodify
WinRM shellEvil-WinRMPowerShell Remoting, Metasploit WinRM module
Box観察一般化
Puppy5985 は開いていたが、Remote Management Users と Kerberos ccache を分けて確認した。C:\Backups から LDAP bind password、DPAPI から別 credential へ進んだ。WinRM は認証と認可を分ける。foothold 後は root 直下の非標準 directory、backup、DPAPI を狭い範囲で見る。
Checkpointsvc_deploy は Remote Management Users と BackupAccess に所属。SeBackupPrivilege はなく、VMBackups share の READ が本線だった。group 名を privilege と誤読しない。whoami /all と share 再列挙で意味を確定する。
Pirate初期 pentest は LDAP/SMB 可、WinRM 不可。gMSA が Remote Management Users に所属し、hash で WinRM できた。machine account、gMSA、group membership は WinRM 候補の発見に使う。
Certifiedmanagement_svc が Remote Management Users に所属することを LDAP と BloodHound で確認し、hash で WinRM した。Remote Management Users は候補であり、最終的には shell 成功で裏付ける。
Administrator初期ユーザー Olivia は WinRM が Pwn3d!。後続で Kerberos 時刻ずれも問題になった。初期資格情報が WinRM まで通る box もある。成功時点で identity と group を残す。
LoggingLogs share、Remote Management Users、Emergency Recovery、msa_health$ が序盤から見えていた。WinRM 後に whoami /groups で認可を確認した。share 名と group 名は運用設計のヒント。machine account の WinRM も候補になる。
VoleurNTLM が使えず STATUS_NOT_SUPPORTED。Kerberos cache で SMB/LDAP を列挙し、archived profile の DPAPI へ進んだ。password 不正と認証方式不一致を混同しない。profile archive は DPAPI の入口になる。

初期資格情報を得たら:

  • smb, ldap, winrm を別々に確認する。
  • --shares --rid-brute と --users --groups --computers を取る。
  • Remote Management Users、custom groups、service accounts、machine accounts、gMSA を拾う。
  • SMB signing、LDAP signing、NTLM 可否、clock skew を読む。
  • BloodHound/RustHound は関係の地図として使い、実操作と再読取りで検証する。

WinRM に入れたら:

  • whoami /all を最初に保存する。
  • C:\ 直下から非標準 directory を探し、候補だけ再帰する。
  • user profile、PowerShell history、Credential Manager、DPAPI、backup、app config を確認する。
  • 新 credential / hash / group membership を得るたびに SMB shares と WinRM を再確認する。
  • winPEAS は手動列挙の差分確認に使う。