考点Node.js Buffer 未初始化内存泄露漏洞、代码执行长度限制、内存读取打开题目看到是一堆代码而这些代码里不仅有python还有CJavascript而这些元素组合起来就是完整的 Node.js 源码。Node.js 源码是什么Node.js 源码是开源跨平台 JavaScript 运行时环境的实现代码它不是单一语言编写的而是由C约 60%、JavaScript约 30%和少量 Python构建工具混合组成核心目标是让 JavaScript 能在服务器端运行。这些代码不用完全看懂直接看向带flag的那行代码eval(var flag_ randomstring.generate(64) \hitcon{ flag }\;)对其进行部分拆解最核心randomstring.generate(64)作用生成一个 64 位的完全随机字符串例子每次运行都会生成不一样的比如第一次是abc123def456...第二次是xyz789uvw012...目的让变量名永远无法被猜到2. 字符串拼接var flag_ 随机字符串 \hitcon{ flag }\;用号把几个字符串拼在一起最终会变成一行完整的 JavaScript 代码。举个具体的例子假设randomstring.generate(64)生成了abc123假设真正的 flag 是hitcon{123456}拼接后的结果就是var flag_abc123 \hitcon{123456}\;3. 最关键eval(...)作用把括号里的字符串当成真正的 JavaScript 代码来执行上面例子中eval 执行后就相当于在程序里写了这么一行代码var flag_abc123 hitcon{123456};先搞懂 3 个最基础的概念1. 计算机内存到底是什么内存是计算机的 临时工作台所有正在运行的程序和数据都存在这里。内存本质上是一个巨大的字节数组每个字节有一个唯一的编号叫做 内存地址每个字节可以存储一个 0-255 之间的数字所有的文字、图片、代码、flag最终都会被转换成数字存在内存里类比内存就像一个有 10 亿个格子的储物柜每个格子有一个编号每个格子能放一张写着数字的小纸条。2. 什么是 内存分配程序运行时需要存东西就必须向操作系统 申请 一块内存这个过程就叫内存分配。操作系统有一个 内存管理员负责记录哪些格子已经被占用哪些是空的程序说我要 800 个格子存东西内存管理员找到连续 800 个空格子把第一个格子的编号告诉程序程序就可以往这 800 个格子里写数据了3. 两个最关键的内存分配函数mallocvscalloc这是整个漏洞的核心中的核心。函数作用行为类比malloc(size)分配size个字节的内存只分配格子不擦除格子里原来的纸条租一个储物柜管理员只给你钥匙不打扫里面的东西上一个租客留下的纸条还在calloc(count, size)分配count * size个字节的内存分配格子并且把所有格子里的纸条都擦成 0租一个储物柜管理员会把里面打扫得干干净净所有格子都是空的malloc分配的内存是 脏的里面有之前的数据calloc分配的内存是 干净的全是 0。在 Node.js 8.0 之前当你写Buffer(800)时底层会执行这样的 C 代码// 只做一件事调用malloc分配800个字节的脏内存 char* data malloc(800); // 没有任何清零操作 return Buffer::New(data, 800);它用的是 **malloc**所以分配到的内存里全是之前残留的数据这就是为什么叫AllocUnsafe不安全分配这就是漏洞的产生总结当服务器收到你的请求执行Buffer(800)后底层调用malloc(800)向内存管理员申请 800 个连续的格子内存管理员在空闲格子里找正好找到了刚才存放 flag 的那 800 个格子把这 800 个格子的起始地址返回给 Buffer。漏洞原理当你在 JS 中执行Buffer(800)时会调用上面的Buffer::New函数AllocUnsafe使用malloc分配 800 字节的内存malloc 只分配内存不初始化内容内存中保留着之前的数据之前eval(var flag_xxxx hitcon{...})执行时flag 被写入了内存当新分配的 Buffer 正好覆盖了之前存放 flag 的内存区域时就能读取到 flag而代码里明确写了参数名是dataif (req.query.data req.query.data.length 12) {因此我们可以得出这样的paylaod。?dataBuffer(800)把它拼接到靶机地址后面每运行一次就会下载一个文件等下载到第三四次的时候就会看到flag(其实我之前一直在尝试用自动化脚本找到内存里的flag但是一直出问题所以才下载了这么多文件......最后只能改手动了)。