CVE-2014-7169如何运作?测试代码的细分

use*_*130 12 bash exploit shellshock-bash-bug

有一个bash版本已被修补shellshock

$ bash --version
GNU bash, version 3.2.52(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
this is a test
Run Code Online (Sandbox Code Playgroud)

另一个类似的漏洞利用仍然有效,并已被分配到CVE-2014-7169

$ env X='() { (a)=>\' bash -c "echo date"; cat echo
bash: X: line 1: syntax error near unexpected token `='
bash: X: line 1: `'
bash: error importing function definition for `X'
Thu Sep 25 12:47:22 EDT 2014

$ ls echo
echo
Run Code Online (Sandbox Code Playgroud)

寻找这个的细分.

nin*_*alj 16

错误

CVE-2014-7169是bash解析器中的一个错误.Bash的解析器使用变量eol_ungetc_lookahead来跨行替换ungetc字符.该变量未从reset_parser函数中正确重置,例如在某些语法错误上调用该函数.使用该bug,可以将一个字符注入下一个bash输入行的开头.

因此,测试代码强制语法错误,使用(a)=或者function a a,将重定向字符添加到前一行>,并添加一个行继续\,这将导致测试代码的任一版本:

() { (a)=>\
() { function a a>\
Run Code Online (Sandbox Code Playgroud)

执行bash时,它会处理来自环境的变量,发现该变量X是导出的函数,并对其进行求值以导入该函数.但是评估失败并出现解析错误,将>字符留在eol_ungetc_lookahead变量中.然后,解析命令参数时echo date,它会预先考虑>性格,导致>echo date,运行date重定向到一个指定的文件echo.

它与之前的bug有关

上面的bug显然与原始的shellshock bug非常不同.实际上有几个问题:

  • Bash完全评估一个看起来像导出函数的变量(以四个字符开头() {).CVE-2014-6271.
  • 在某些情况下,可以将一个字符注入一个ungetc变量,该变量将被添加到下一个输入行.CVE-2014-7169.
  • Bash允许将每个环境变量视为导出函数,只要它以四个字符开头即可() {.CVE-2014-6271,CVE-2014-7169,所有其他CVE,其中在bash的解析器中触发了一个bug.
  • here-doc重定向的堆栈有限,并且没有检查溢出.CVE-2014-7186,导致内存损坏,可能可以用于任意代码执行.
  • 嵌套控制结构(select/ for/ while)的堆栈有限,检查溢出.该堆栈仍然已损坏.CVE-2014-7187.

修复

  • 一个补丁限制bash评估每个看起来像导出函数的变量中的单个函数定义.
  • 第二个补丁正确重置eol_ungetc_lookaheadreset_parser.
  • 第三个补丁修改功能如何导出:现在他们在命名变量导出BASH_FUNC_functionname%%.

攻击面

这里的一个大问题是每个环境变量都可以用作攻击的载体.通常情况下,攻击者无法控制任意环境变量,否则目前已经有其他已知的攻击(想想LD_PRELOAD,PATH,IFS,...).

sudo不会受到影响,因为它会从环境中剥离导出的bash函数,正如Gilles在security.SE中所提到的那样.

ssh被影响.典型的sshd安装仅允许按照AcceptEnv中的配置导出一组有限的环境变量sshd_config,例如:LANGLC_*.即使采用这种积极的白名单方法,在shellshock中任何变量都可能是攻击向量.

不仅每个环境变量都是潜在的攻击向量,它们暴露了> 6000行解析器.

经验教训

system,popen和其他人有潜在的危险.你不仅应该注意他们的论点:即使在编译时修改了参数,环境也是一个潜在的攻击向量.使用fork()/execve(),最好使用干净的环境(但至少将环境限制在列入白名单的变量中,最好是对其值进行完整性检查).请记住,一个高质量的系统可以完成应该做的事情,而一个安全的系统可以完成应该做的事情,仅此而已.调用一个完整的shell会让事情变得更加困难.

复杂性是安全的敌人.这些天你可以很容易地找到推荐更简单的贝壳的人.由于根本不支持导出的函数,因此大多数shell都没有shellshock.相反,bash多年来已经收到了很多安全功能(你需要调用它-p来避免它在启动时删除权限,它会清理IFS,...),所以不要以为我提倡切换shell,这是更多的一般建议.

David Wheeler古老的"Linux和UNIX HOWTO安全编程" 一章中关于环境变量的一些摘录仍然值得重读.

§5.2.31:

对于安全的setuid/setgid程序,应仔细提取作为输入所需的环境变量的简短列表(如果有).然后应擦除整个环境,然后将一小组必要的环境变量重置为安全值.如果你打电话给下属程序,真的没有更好的方法; 没有列出"所有危险价值"的实用方法.

§5.2.36:

如果确实需要用户提供的值,请首先检查值(以确保值与合法值的模式匹配,并且它们在某个合理的最大长度内).