我在检查Shellshock漏洞时得到了这个:
host1:~$ env x='(){ :;}; echo vulnerable' bash -c "echo hello"
hello
host1:~$ env x='() { :;}; echo vulnerable' bash -c "echo hello"
vulnerable
hello
host1:~$
怪啊?
答案 0 :(得分:12)
Bash将环境变量识别为函数,如果它恰好以四个字符() {
开头,包括空格。所以env x='(){ :;}; echo vulnerable'
并不算数。
这与用于在bash
中定义函数的语法完全一致;在内部,bash
将以规范化的形式存储函数的字符串表示。如果导出函数(使用export -f function_name
),则将规范化表单添加到环境中,子bash
进程将其识别为函数定义。
" shellshock" bug来自bash
处理已识别函数的方式; bash
的错误版本(可以追溯到很长一段路)只是将环境中的字符串作为函数定义进行评估(通过将变量的名称作为函数名称添加),这会受到注入攻击的影响。在漏洞测试中证明了这一点。
为了在子bash
进程中定义函数,手动创建看起来像bash
函数定义的字符串是一种已知技术。导出功能并重新导入它们非常常见,用户通常甚至都注意不到。 (例如,此技术用于将bash函数传递到由xargs bash -c
和find ... -exec bash -c
启动的子shell中。)
答案 1 :(得分:2)
bash
对于它认为环境中的嵌入式函数定义有点挑剔。在第一个
env x='(){ :;}; echo vulnerable' bash -c "echo hello"}
()
和{
之间缺少空格足以阻止bash
将其识别为导出函数,因此它仍然是一个简单的shell变量;看,试试看
env x='(){ :;}; echo vulnerable' bash -c 'echo $x'
在第二个示例中,x
, 空格的值被正确制作以模仿导出的函数,因此子bash
计算整个值x
来“导入”该函数,但也执行函数定义之后的代码。