javascript - 我在服务器中安全地使用 eval() 吗?
问题描述
简而言之,我正在使用eval动态调用用于验证客户端 cookie 的函数(前面都有相同的名称,最后一位不同)。
const cookie_names = ['cookiename_1', 'cookiename_2'];
exports.validateCookies = (req, res, next) => {
const cookie_types = filterUnknownCookies(Object.keys(req.cookies));
for(let cookie of cookie_types){
res.locals[cookie] = eval(`validateCookie${cookie}('${req.cookies[cookie]}')`);
}
next();
}
const filterUnknownCookies = (cookie_arr) => {
cookie_arr = cookie_arr.filter(name => cookie_names.findIndex( validnames => validnames === name) + 1);
return cookie_arr;
}
因为我知道使用 eval 函数可能很危险,所以我硬编码了有效的 cookie 名称并过滤了数组中与它们不匹配的任何内容。所以问题是:从任何不需要的字符串(名称)中过滤数组是否足够安全以对抗 eval 的可利用性?提前致谢
解决方案
所以问题是:从任何不需要的字符串(名称)中过滤数组是否足够安全以对抗 eval 的可利用性?
不,这不安全。事实上,它基本上对保护您没有任何作用,因为您允许的 cookie 名称仍然完全不受保护和未经消毒。您所拥有的可能是不安全的,因为恶意客户端可以将他们想要的任何内容放入该 cookie 中,而您“希望”他们找不到会超出您拥有的字符串分隔符的内容。但是,可以通过终止字符串然后添加函数调用来打破该字符串分隔符。这可能会允许攻击者在您的服务器上执行任意代码。
您应该使用的唯一东西eval()
是来自您自己的服务器端代码的受信任字符串或来自外部的完全净化的字符串。但是,几乎总是不需要eval()
,因为还有另一种更安全的编码方式。
在这里,你根本不需要使用eval()
。您可以为要调用的合法函数创建一个查找表,然后将函数直接传递给它:
try {
res.locals[cookie] = validateCookie[cookie](req.cookies[cookie]);
} catch(e) {
// either invalid cookie or exception in the function
// handle that here
}
而且,当然,您的validateCookie[cookie]()
函数还必须进行防御性编码,以知道它可以传递任何东西。您没有向我们展示该函数的代码以便能够进一步评论它。
在这种情况下,validateCookie
是一个包含有效cookie
名称及其对应函数的查找表:
// cookie processing lookup table
const validateCookie = {
cookieName1: validateCookieName1,
cookieName2: validateCookieName2
};
像这样的查找表通常是您避免尝试制造函数名称和字符串并eval()
用来调用它的方法。这还添加了此代码无法调用不在查找表中的任何函数的安全功能。
推荐阅读
- nginx - Nginx 阻止特定端口上的 GET 请求
- c - 如何使用 FIFO(在 C 中)为父进程提供文件名?
- kotlin - 协程中的 Kotlin 异步:异常被捕获并仍在传播?
- javascript - Three.js - 如何从自己的角度旋转对象?
- c# - System.Data.SqlClient.SqlException(提供者:SQL 网络接口,错误:50 - 本地)错误
- python - 当我使用 pygame 混音器在主游戏循环中运行声音时,声音会在每个循环之间滞后并中断,我该如何解决这个问题?
- python - Numpy pColormesh TypeError:C 的尺寸与 X 和/或 Y 不兼容,请参阅帮助(pcolormesh)
- laravel - 我没有加入 ad_categories 表的数据
- laravel - 如何在 Heroku 中为自定义域生成 ssl 证书的 CSR?
- python - 使用arabic-reshaper和python-bidi(在多行情况下)时如何修复反向行?