我正在为一个javascript框架做出贡献,该框架具有以下代码:
eval("'" + user_input.replace(/'/g, "'") + "'");
我知道这太可怕了 - 不需要说服我。我想知道的是,我可以在这里注入任意代码吗?
乍一看,user_input.replace("'", "'")
似乎会阻止我突破弦乐。但是,我可以通过换行符,例如\nalert(123)\n
,但结果始终是语法错误,例如
'
alert(123)
'
这里是否实际存在代码注入的向量,而不仅仅是导致语法错误?
答案 0 :(得分:8)
虽然这无疑是一种令人担忧的模式,但如果完全按照描述的方式使用它是安全的。可以在Javascript中终止单引号字符串的唯一字符是单引号字符。只要该字符没有出现在插入单引号的字符串中,就不能将其解释为字符串以外的任何字符。
关于我能想到的最糟糕的事情是你可以做的是用反斜杠结束一个字符串,这会产生一个未终止的字符串,例如如果user_input
是:
example\
然后评估的代码将是
'example\'
会导致语法错误,因为eval
中包含的字符串永远不会终止。但是,如果真实eval
实际上更复杂,这是可利用的。例如,如果代码是:
var escaped_input = user_input.replace(/'/g, "&39;");
eval("'" + escaped_input + "' some more stuff '" + escaped_input + "'");
然后 可以通过以下输入进行利用:
; alert(1); // \
会导致:
'; alert(1); // \' some more stuff '; alert(1); // \'
^^^^^^^^^
其中带下划线的内容将被评估,因为应该退出该字符串的引用被转义,将下一个单引号转换为结束引用!为了安全起见,我建议尽可能转义或替换反斜杠(除非您明确尝试使用eval()
来处理它们,在这种情况下,您可能只是捕获异常)。