2016 HITCON CTF WriteUp
🏆 决赛概况与最终排名
时间与地点:决赛于 2016 年 12 月 2 日至 3 日在中国台湾台北举行
参赛队伍:共有 12 支顶尖战队从线上赛脱颖而出,同场竞技
最终排名与奖金:
冠军:Cykorkinesis (韩国),奖金 10,000 美元
亚军:LC↯BC (俄罗斯),奖金 5,000 美元
季军:PPP (美国),奖金 2,000 美元
特别奖项:为鼓励本土人才,大赛还设立了 “HITCON TAIWAN STAR”奖,由表现优异的台湾队伍 Dispwnable 获得,奖金 1,000 美元
此外,决赛中还出现了 “一个软件、三个0-Day” 的精彩场面。在基于真实开源软件 SugarCRM 设计的 “WEBROP” 赛题中,LC↯BC、PPP和Cykorkinesis 三支队伍先后发现了三个不同的零日漏洞
🏛️ 组织者与合作伙伴
主办方:HITCON (台湾骇客年会)
共同举办:工业技术研究院
赞助商:联发科技、东博资本、和沛移动
Web
leaking(Node.js Buffer 未初始化内存泄露)

1 | ; |
源码分析如下:
第一,服务端启动时通过
require("./config.js").flag读取 flag 内容第二,每次访问
/时,程序都会在主 Node.js 进程里执行一次eval,生成一个随机变量名:flag_随机64字符 = "hitcon{...}"第三,只有当
req.query.data.length <= 12时,用户输入才会被放进 vm2 的VM.run()中执行;否则直接返回源码
这样就会导致:
flag 变量名不可猜
而且 vm2 是一个沙箱,正常情况下它不能直接访问外层 Node.js 主上下文里的变量、
require、process等对象,所以也逃逸不了
ChALkeR 的经典文章《Node.js Buffer knows everything》解释过:new Buffer(size) / Buffer(size) 类似 C 里的 malloc(),底层内存可能残留之前使用过的数据,比如源码片段、配置文件内容、HTTP 流量、密码、证书等敏感信息
1 | new Buffer(size) |
Node.js 后来推荐使用 Buffer.alloc()、Buffer.from() 来避免未初始化内存泄露
这句在 vm2 执行用户代码之前 已经把 flag 字符串放进了当前 Node.js 进程的内存里
1 | eval("var flag_" + randomstring.generate(64) + " = \"hitcon{" + flag + "}\";") |
随后我们在 vm2 沙箱里执行
1 | Buffer(1e4) |
虽然它是在沙箱里执行,但底层仍然走 Node.js 的 Buffer 内存分配机制
旧版 Buffer 可能拿到一块未清零的内存,这块内存里可能残留刚才主进程中生成过的 flag 字符串
其中 1e4 == 10000,于是构造 Payload 反复请求拿到 flag
1 | while true; do curl 'http://1.2.3.4/?data=Buffer(1e4)' | grep -a hitcon; done; |
