当使用ESAPI执行器运行一个简单的命令时,如。
C:\\Windows\\System32\\cmd.exe /c echo test >> D:\\wow\\test.txt
当 C:/Windows/System32/cmd.exe 是可执行文件,而 C echo test >> D:\wow\test.txt 是参数,问题是 编解码器 毁掉了操作符>>(这意味着要避开它或将它作为一个字符串来引用,所以输出将只是打印 "test >> D:\wow\test.txt"。
编解码器正在做它应该做的事情。也许一个过于简单的例子可以让我们更清楚地了解为什么这是正确的行为。
让我们假设您有一个网络应用,您让用户上传一个文档,然后您为他们运行拼写检查,并将纠正后的结果发送给他们。 为了简单起见,我们假设你已经将当前的工作目录设置为特定于使用你的服务的每个用户,并且你有一个 "spellcheck.bat",它接受一个单一的文件名作为参数,你计划执行这个字符串。
C:\Windows\System32\cmd.exe /c C:\spelling\spellcheck.bat userFilename > spelling-errors.txt
其中 用户文件名 是用户上传文件的名称。你的目的是用用户上传的文件和文件名运行spellcheck.bat,然后读取并显示 "拼写错误.txt "文件给用户。(IRL,那可能是一个在不同目录下的临时文件,但我想让它变得简单。)
那么,如果'userFilename'中包含'>'字符会怎样呢?你当然希望它被适当地引用,不是吗?因为否则攻击者可能会覆盖一些你不希望被覆盖的文件,包括像web.xml或其他配置属性文件。因为运行像(比如)这样的东西
C:\Windows\System32\cmd.exe /c C:\spelling\spellcheck.bat myDoc.txt >sucker.txt > spelling-errors.txt
将会创建'sucker.txt',如果该文件名存在,它将被截断,并被 "spellcheck.bat myDoc.txt "的输出所取代。这可能不是你想要的。
所以防止通过'<'、'<<'、'>'和'>'进行文件IO重定向操作是有目的的。如果你真的想允许它们(我建议不要这样做),那么你将不得不根据你想允许的内容来解析你自己的命令串。
另外,虽然我不确定对于Window的cmd提示符shell来说是不是真的,但对于*nix shell来说,作为文件重定向的一部分,也可以在重定向中进行命令执行,这肯定是真的。例如,在bash中,我可以做这样的事情。
cat < $(ls foo)
如果文件'foo'存在,'ls foo'命令将列出输出的foo,所以这条命令变成了:
cat < foo
我们只是从文件 "foo "中获取stdin来执行 "cat "命令。但是攻击者可以用它做一些更恶毒的事情。当然,操作系统的编解码器也可以防止'$(...)'式的命令替换,但希望我已经说明了我的观点。