杏林同学录(五)

发布日期:2002-04-3 漏洞类别:PHP,远程WEB接口,拒绝服务 bugtraq ID
4432、4434 存在问题的版本: phpBB 1.44,更低的版本及 phpBB 2.0 未测试。
描述:
phpBB是一个被广泛应用的基于PHP的论坛。发现其BBcode中对于“源代码”类的引用处
理存在漏洞,通过发送特殊格式的转义字符串可导致数据库的损坏以及服务器的
CPU、内存 资源大量消耗。 详细:
phpBB在对“源代码”类的引用处理不当,主要是为了要支持镶套的标记
而造成的。有问题的代码是functions.php中的bbencode_code函数。
当我们提交一个这样的贴子: 实际向数据库中存储的数据是这样: [1code]
/0/0/0/0/0/0/0 [/code1][1code] /0/0/0/0/0/0/0 [/code1][澳门新浦京娱乐游戏 ,1code]
/0/0/0/0/0/0/0 [/code1][1code] /0/0/0/0/0/0/0 [/code1][1code]
/0/0/0/0/0/0/0 [/code1][1code] /0/0/0/0/0/0/0 [/code1][1code]
/0/0/0/0/0/0/0 [/code1]
即实际系统要负担的数据量是输入的“/0”的数量的平方,如果发送 1
MByte的数据,系统 实际处理的数据将接近 1 TByte。
这是我们在实验机器上发送一个包含”*800的帖子时的资源占用情况:
PIDUSERPRINISIZERSS SHARE STAT %CPU %MEM TIME COMMAND 8643 nobody13 0
212M81M 13604 D 8.0 65.7 0:07 提交贴子后会提示出错: Could not enter
post text!
但实际上贴子的标题和提交者这两个数据已存到数据库中,但内容和其他一些数据没有,所
以打开的时候会出现错误页面。而且这样的帖子无法用正常的方法删掉,只能用直接连接到
数据库来删除。以下是提交不同数据量的结果: ”* =583正常贴上,可以删除
”* 584正常贴上,可以编辑,但不能删除 ”* 585提示 Could not enter post
text! 但贴子也没有 ”* 586正常贴上,可以删除 ”* 587提示 Could not
enter post text! 但贴子也没有 ”* 588正常贴上,可以删除 ”* 589提示
Could not enter post text! 但贴子也没有 ”* =590提示 Could not enter
post text! 出现删不掉的帖子
如果发送镶套的标记则占用资源更多,我们在实验机器上发送这样的帖子:
代码如下:[code]/0/0[/code]
虽然只有49Byte的数据,但资源占用非常可观: PID USER PRINISIZERSS SHARE
STAT %CPU %MEM TIME COMMAND 25741 nobody14 0 11828 9996 416 R99.97.8
2:38 几秒钟后产生了大量的数据,内存大量消耗: PID USER PRINISIZERSS
SHARE STAT %CPU %MEM TIME COMMAND 3 root10 0 00 0 SW2.50.0 4:13 kswapd
25742 nobody17 0265M90M 52104 R25.1 73.0 1:45
这样的镶套帖子是不会存储到数据库中的,但随着镶套的增加资源的占用会按照几何级数递
增。如果一次发送更多数据,或者不断的发送,可以导致系统资源大量占用,最终拒绝服务。
实验环境:linux 2.4.10 Apache/1.3.23 PHP 4.12 解决方案:
1、暂时禁用BBcode。
2、alert7给出了functions.php的如下修改方法,暂时停用对镶套标记的支持:
把773行开始的bbencode_code函数改为: function bbencode_code($message,
$is_html_disabled) { $message =
preg_replace(“//[code/](.*?)/[//code/]/si”, “!– BBCode Start
–TABLE BORDER=0 WIDTH=85%TRTDfont size=-1Code:/fontHR/TD/TRTRTDFONT
SIZE=-1PRE//1/PRE/FONT/TD/TRTRTDHR/TD/TR/TABLE!– BBCode End –“,
$message); return $message; } // bbencode_code()
对于无法正常删除的帖子,需要手工连接数据库删除。假设有这样一个帖子:
可以这样: $ mysql -uuser -ppasswd mysql use databasename; mysql select
*from topics where topic_id = 1162; //得到post_id mysql delete from
posts where post_id = 6280; mysql delete from posts_text where
post_id = 6280; mysql deletefrom topics where topic_id = 1162;
关于我们: WSS (Whitecell Security
Systems),一个非营利性民间技术组织,致力于各种系统安
全技术的研究。坚持传统的hacker精神,追求技术的精纯。 WSS 主页: WSS
论坛:
补充:后来的测试发现相当多的BBS都有类似问题,包括基于php、cgi、asp的,希望大家自己对自己的论坛进行测试,如有问题,参考本文酌情解决。

密码查询:class/querypsw.php HTML HEAD meta content=text/html;
charset=gb2312 TITLE询问密码/TITLE /HEAD BODY BGCOLOR=#FFFFFF ?php
include config.php; //询问班级注册问题密码 if ($class){ $headers .=
Content-Type: text/html; charset=gb2312n; // Mime type
$subject=询问班级注册问题密码 ;//主题 $message=nl2br($message);
$message=查询人:.$name.BR留言:BR.$message;//内容
mail($superemail,$subject,$message,$headers); echo
恭喜您,您的请求已经向管理员发出,近期内请注意查收email。; exit; }
//询问个人注册密码 if ($member){$result = mysql_query(SELECT * FROM
user where user=’$username’,$db); if
(mysql_num_rows($result)==0){//若返回列的数目为0,说明无此资料 echo
我们的数据库中无此用户,请确认。注意大小写。a
href=’javascript:history.back()’返回/a; exit;}
$myemail=mysql_result($result,0,email);//读取user数据库中的email if
(!$myemail){//如果还没有email,则返回 echo
我们的数据库中没有您的email,请再次填写。a
href=’javascript:history.back()’返回/a; exit; }
$psw=mysql_result($result,0,psw);//密码
$name=mysql_result($result,0,name);//姓名 $subject=询问个人注册密码;
$message=$name.,您好。您的用户名是.$username.,密码是.$psw.。BR———————–BRa
href=’.$url.’.$sitename./a;//信件内容 $headers .= Content-Type:
text/html; charset=gb2312n; // Mime type
mail($myemail,$subject,$message,$headers); echo
恭喜您,系统已经向您的信箱中发出了答复信件,请注意查收email。; exit; }
?table width=93% border=0 cellspacing=0 cellpadding=0 align=center
height=286 trtd height=75 colspan=2div align=center询问密码br /div /td
/tr trtd height=75 width=47% form name=form1 method=post action=? echo
$PHP_SELF;?div align=center询问班级注册问题答案br 您的姓名input
type=text name=name br您的留言(写上能证实您身份的简短留言及email地址)
textarea name=message rows=3 cols=50/textarea br
系统将向班级管理员发送您的请求,是否确认?br input type=submit name=class
value=确认 input type=reset name=cancel value=重填 br /div/form /td td
height=75 width=53% div align=center form name=form2 method=post
action=? echo $PHP_SELF;? 询问个人注册密码br br 您的用户名(不是姓名)br
br input type=text name=username br br br
系统将会向您注册的信箱中发发送密码,是否确认?br input type=submit
name=member value=确认 input type=reset name=cancel2 value=重填 /form
/div /td /tr /table/BODY /HTML 悄悄话:privatenote.php ?
session_start(); // 开始session
if(!session_is_registered(userregister)||($userregister==))//检查是否注册,如userregister未注册或session为空值,重新注册.
{ echo a href=’../index.php’请重新注册BR; exit; } //删除留言 include
config.php; if ($del==1){ mysql_query(delete from privatenote where
id=’$id’,$db); //以id为删除标志 echo 删除成功!; } //添加留言 if
($Submit){ $id=time();//以时间戳为记录号 $time=date(Y年m月d日 h:i:s
A);//留言时间 $result = mysql_query(SELECT * FROM user where
user=’$userregister’,$db);
$fromuser=mysql_result($result,0,’name’);//发消息人姓名 $result =
mysql_query(SELECT * FROM user where name=’$yname’,$db);
$touser=mysql_result($result,0,’user’); ;//接受人用户名
$message=nl2br(strip_tags($ynote));//留言内容 mysql_query(INSERT INTO
privatenote (id,fromuser,touser,time,message) values
(‘$id’,’$fromuser’,’$touser’,’$time’,’$message’),$db); //写入数据库 echo
留言成功!; } ? HTML HEAD meta content=text/html; charset=gb2312
TITLE悄悄话/TITLE style type=text/css !– .blue9 {font-size: 10pt;
color: #9999FF; text-decoration: none} .black10 {font-size: 10pt} —
/style /HEAD BODY BGCOLOR=#FFFFFF table width=64% border=1
cellspacing=1 cellpadding=1 align=center trtd colspan=2 height=63div
align=centerimg src=image/classlogo.gif width=224 height=60/div /td /tr
tr td class=blue9 colspan=2div align=center ? $result =
mysql_query(SELECT * FROM user where user=’$userregister’,$db);
$name=mysql_result($result,0,name);//姓名 echo $name; ? 的悄悄话/div
/td /tr trtd class=blue9 colspan=2?php $result = mysql_query(SELECT *
FROM privatenote where touser=’$userregister’ ORDER BY time DESC,$db);
$row=mysql_num_rows($result);//悄悄话总数 $unlook=0;if (!$row==0){ for
($i=0;$i$row;$i++){ $id=mysql_result($result,$i,’id’);//留言id
$fromuser=mysql_result($result,$i,’fromuser’);//留言人姓名
$time=mysql_result($result,$i,’time’);//留言时间
$message=mysql_result($result,$i,’message’);//留言内容
$look_s=已看过;//注释 $look=mysql_result($result,$i,’look’);//是否看过
if ($look==0){$unlook++;$look_s=尚未看过;}
//计算未看过的悄悄话数目,并改变注释 mysql_query(UPDATE privatenote SET
look=’1′ where id=’$id’,$db);//将悄悄话看过状态改为1 echo 第,$i+1,条
发出人:,$fromuser, 留言时间:,$time,BR; echo
留言内容:,$message,BR——,$look_s; echo a
href=’$PHP_SELF?del=1&id=$id’删除/aHR; } } echo
悄悄话总数:,$row,.,$unlook,条新悄悄话.; ? /td /tr trtd class=black10
colspan=2form method=post action=?php echo $PHP_SELF;? p
align=center您要给谁发悄悄话?select name=yname ? $result =
mysql_query(SELECT * FROM user,$db);
$row=mysql_num_rows($result);//成员人数 for ($i=0;$i=($row-1);$i++){
$name=mysql_result($result,$i,’name’);//姓名 echo option,$name,/option;
} mysql_close($db); ? /select br 留言内容:br textarea name=ynote
cols=60 rows=6/textarea br binput type=submit name=Submit value=确认
/binput type=reset name=cancel value=重写 /p /form /td /tr /table /BODY
/HTML

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图