Discuz!论坛install.php书写错误漏洞

书写错误,导致恶意用户构造语句可以写入webshell,进而控制整个服务器。

前几个晚上,把前台文件,只要是数据库调用中的变量都看了一遍。看看是不是有过滤不严的地方,看完后觉得,过滤不严的地方的确不少,但是都已经被单引号保护起来了。在php中,如果magic_qoute_gpc=on(默认的)编译器会自动把单引号等特殊字符转义,而这个时候我们想改变程序的执行流程是非常困难的。这样大大的增加了入侵的难度,在某种程度上,也的确保证了其安全。这也是为什么朋友提出一定要在magic_qoute_gpc为on的时候依然可以利用的要求。如果需要单引号介入才能利用的漏洞,在Discuz!论坛中基本上是没什么用处的。

在把所有文件中数据库连接的地方读了一个遍后,没找到任何有价值的东西。这个时候思路开始有一点乱了,我在犹豫自己是否应该试着从程序员的思维逻辑漏洞下手看看,这就意味着我要去通读所有代码,找到程序员在写程序时考虑不周全的地方,这种漏洞多半是上下文逻辑关系错误,或者是限定不唯一,还有就是一些本来应该注意,但管理员却偏偏忽略的地方。

想到这里,看来没什么能偷懒的了,只能通读代码。因为既然目标是逻辑错误,那么就一定要细看上下文的关系,所以选择从入口点开始读起。入口点就应该是logging.php,因为这是登陆的地方,所有人都会从这里登陆进入论坛。上吧!

老规矩,我们先来看一段代码:

=========codz begin==========

50 $errorlog = "$username\t".substr($password, 0, 2);

......

54 $errorlog .= substr($password, -1)."\t$onlineip\t$timestamp\n";

55 $password = md5($password);

56 $query = $db->query("SELECT m.username as discuz_user, m.password as discuz_pw, m.status, m.styleid AS styleidmem, m.lastvisit,

u.groupid, u.isadmin, u.specifiedusers LIKE '%\t$username\t%' AS specifieduser

FROM $table_members m LEFT JOIN $table_usergroups u ON u.specifiedusers LIKE '%\t$username\t%' OR (u.status=m.status AND ((u.creditshigher='0' AND u.creditslower='0' AND u.specifiedusers='') OR (m.credit>=u.creditshigher AND m.creditWHERE username='$username' AND password='$password' ORDER BY specifieduser DESC");

......

69 if(!$discuz_user)

{

70 @$fp = fopen($discuz_root.'./forumdata/illegallog.php', 'a');

71 @flock($fp, 3);

72 @fwrite($fp, $errorlog);

73 @fclose($fp);

74 showmessage('login_invalid', 'index.php');

}

=========codz endz==============

这段代码我们来一句一句看看,他先纪录输入的用户名和密码,密码只取前两位,然后取密码后一位,并且将ip和时间一起赋过来。然后去密码的md5值,放到数据库中去。如果你认为我们可以改变数据库执行语句的操作流程那就错了,面对单引号我们没有什么可以做的(至少是我做不了什么,除非加密)。后面如果用户名和密码不对则将纪录下错误用户名和密码到illegallog.php中。整个这个记录错误密码的过程中,变量没有经过任何验证,也就是说如果我成心输入错误的用户名,他也不会作检查然后直接记录下来。那么如果我的错误的用户名是一个可执行的代码,他也会记录下来。在他记录下来之后我们去调用这个文件就可以形成一个shell。

到这里你是不是已经兴奋了?对不起,你的兴奋无效。我是一点都兴奋不起来,因为我在前面读第一遍的时候,特别注意过Discuz!对文件句柄的操作,他的确对个别变量没有过滤,但是他在install.php中得初始化的时候,已经给所有用到的以.php结尾的数据文件开始的地方添加了一句:。这是初始化的时候写入的,我们都应该明白这句话的作用。你无法去调用你写入的东西,因为一开始就已经结束了.这样显然是无法成功的。有点烦了,心想不就是5根羊棒么?输就输了!一赌气扔下代码,自己跑到姥姥的那屋,搂着姥姥撒起娇来,(在姥姥面前撒娇、耍赖、捣乱是我最喜欢的事情之一)我在姥姥面前反复咒骂着Discuz!的变态,说我自己如何如何认真的读代码。姥姥并不知道我在说什么,也不在乎我给她捣乱,继续看着自己的电视。过了一会儿,姥姥应了一句:"你这孩子啊,就是粗心,一点都不心细,你看你这什么码(估计是说代码)又坏了吧"。我嘎嘎大声的笑着爬回了自己的屋子。坐在电脑前,喝了杯白开水,冷静了一下。

做安全的人细心,毅力,自学,善于总结是非常必要的。回过头又把logging.php文件重新读一编,看看有没有什么自己忽略的地方。文件并不长,又看了一遍觉得还是没什么问题。既然这里没什么问题,思路就放到那句上,这句话是如何写入的呢?

于是在install.php中翻到了这段代码:

==========codz begin==========

29 function loginit($log) {

30 echo '初始化记录 '.$log;

31 $fp = @fopen('./forumdata/illegallog.php');

32 @fwrite($fp, "\n");

33 @fclose($fp);

34 result();

35 }

......

1389 loginit('karmalog');

1390 loginit('illegallog');

1391 loginit('modslog');

1392 loginit('cplog');

1393 dir_clear('./forumdata/templates');

1394 dir_clear('./forumdata/cache');

==========codz endz==========

很显然,loginit这个函数就是在往illegallog.php中写入这句话。这样我们就算写入了代码也会因为那句话的存在而无法调用执行。我们已经完全进入了一个死胡同。但我似乎觉得这段代码哪里有些问题,再仔细看了一下,那个fopen看着怎么那么不顺眼啊。如果没记错的话fopen的语法格式应该是这样的:

resource fopen ( string filename, string mode [, int use_include_path [, resource zcontext]])

前面两个参数,一个是文件句柄,或者指定打开哪个文件。第二个参数是指定打开的方式,比如读还是写。这里要提醒大家的是这个两个参数是必选的。比如我们写入目录下的Jambalaya.php,我们的语句是这么写的:fopen('./Jambalya.php','w'),后面那个打开方式必须选的,否则就会报错。可是我们注意到,他的代码中只有一个参数,这样程序怎么可能正确执行呢?

我们来做一个试验,创建一个1.php,写入如下代码:

===========codz begin==========

$fp = @fopen('./2.php');

@fwrite($fp, "\n");

@fclose($fp);

echo "success!";

===========codz endz============

在这里做一个和Discuz!中的一样的环境,如果这个程序执行成功,那么会在根目录下产生一个2.php,而2.php的开头一行应该是,并且屏幕上显示success,其实这里的success就是用来让我们了解程序执行所到的位置。我们在url中提交:http://127.0.0.1/myhome/1.php,屏幕上显示了success,这说明已经执行到程序的尾部。但是检查目录时发现并没有生成名为2.php的文件,也就是说我们写入失败了。也许大家会奇怪,写入失败应该有出错信息啊。的确应该有,但是因为在fopen前加上了@,而@在php中是用来抑制所有调用函数产生的错误信息的。换句话说就是即使出错了,也不会报错。

姥姥教训的没错,我太粗心了!

假设一切都是按我的思路走过的话,也就说在安装初始化的时候,因为那个fopen的错误使用,所以discuz/forumdata目录下绝对不会产生一个含有代码的illegallog.php文件,但是因为抑制出错信息,所安装的时候会依然显示初始化成功,其实却并没有初始化,更没有产生illegallog.php。而如果这里没有初始化,也就意味着illegallog.php的产生和初始化将在logging.php中完成。logging.php的初始化并没有对文件写入任何保护语句或者过滤措施来避免用户调用。到这里,一切都明朗了。说得直白一点,也就是因为install.php文件错误的初始化的缘故,我们可以通过logging.php写入恶意代码,然后调用那个文件来产生一个shell控制整个网站。

Exploit代码如下

以下内容可能带有攻击性,仅供安全研究与教学之用。使用者风险自负

不用注册任何账户,到登陆页面,在登陆用户名的地方先输入123456,回车。这里大家可能明白了,密码前两位是显示的,这样illegallog.php里面保存的就是:

*****6 127.0.0.1 1022383175

这就可以查看php的设置了,我们先看一下register_globals这个设置是否为on。(大部分的网站都是on)好,然后我们在登陆口输入,这里最好不用system(),我在做测试的时候很多网站把这个system()函数禁用了。

然后我们调用http://192.168.0.13/forumdata/illegallog.php?cmd=dir

前面出来一堆垃圾信息,往最下面看是不是可以看到目录被列出来了?但是这样写入有点麻烦,因为在实验的时候,大的网站注册用户有10万多人,那么这个文件会大的出奇,打开速度奇慢。

那么我们这里其实还可以这样写入,我们把php的shell改成jpg格式的图片,上传到主机。

在URL中调用:

http://192.168.0.13/forumdata/illegallog.p...chments/Jam.php

然后我们直接提交URL:

http://192.168.0.13/attachments/Jam.php就?...一个shell了吧!

(0)

相关推荐

  • Discuz!论坛install.php书写错误漏洞

    书写错误,导致恶意用户构造语句可以写入webshell,进而控制整个服务器. 前几个晚上,把前台文件,只要是数据库调用中的变量都看了一遍.看看是不是有过滤不严的地方,看完后觉得,过滤不严的地方的确不少,但是都已经被单引号保护起来了.在php中,如果magic_qoute_gpc=on(默认的)编译器会自动把单引号等特殊字符转义,而这个时候我们想改变程序的执行流程是非常困难的.这样大大的增加了入侵的难度,在某种程度上,也的确保证了其安全.这也是为什么朋友提出一定要在magic_qoute_gpc为

  • MySQL优化配置文件my.ini(discuz论坛)

    在Apache, PHP, MySQL的体系架构中,MySQL对于性能的影响最大,也是关键的核心部分.对于Discuz!论坛程序也是如此,MySQL的设置是否合理优化,直接影响到论坛的速度和承载量!同时,MySQL也是优化难度最大的一个部分,不但需要理解一些MySQL专业知识,同时还需要长时间的观察统计并且根据经验进行判断,然后设置合理的参数. 下面我们了解一下MySQL优化的一些基础,MySQL的优化我分为两个部分,一是服务器物理硬件的优化,二是MySQL自身(my.cnf)的优化. 一.服务

  • DISCUZ论坛的UBB编辑器(增加灵活调用,支持ASP UBB解析)打包下载

    复制代码 代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">  <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=gbk">  <title>Discuz编辑器</title>  <m

  • destoon调用discuz论坛中带图片帖子的实现方法

    在destoon开发中有时候我们需要调用论坛的帖子,但是带有图片的帖子该怎么调用出来呢,本文就来实例展示一个可以调用discuz论坛带图片的帖子的方法: 标签代码如下: <!--{php $tags=tag("table=pre_forum_thread i,pre_forum_threadimage t&prefix=&condition=i.tid=t.tid&length=36&order=i.tid desc&pagesize=9&t

  • Discuz论坛密码与密保加密规则

    Discuz密码加密规则: md5(md5('字符串').'固定字串'): 固定字符串是在注册用户的时候随机生成的,且保存在数据表pre_ucenter_members的salt字段中. 举例:假如密码为 123456789 ,固定字符串为jb51,  那么加密规则为:md5(md5('123456789').'jb51'); 得出的结果就是:96122ff0dd306c912aab15adccf21df1 Discuz密保加密规则: 加密过程是value的值先加密一次,比如我的提问是"驾驶执照

  • php中通过curl模拟登陆discuz论坛的实现代码

    libcurl同时也支持HTTPS认证.HTTP POST.HTTP PUT. FTP 上传(这个也能通过PHP的FTP扩展完成).HTTP 基于表单的上传.代理.cookies和用户名+密码的认证. php的curl真的是相当好用,网上一搜索相关文章都是关于curl模拟登陆的,很少人提供模拟discuz发贴的源码. 复制代码 代码如下: <?php $discuz_url = 'http://127.0.0.1/discuz/';//论坛地址 $login_url = $discuz_url

  • 千万级记录的Discuz论坛导致MySQL CPU 100%的优化笔记

    发现此主机运行了几个 Discuz 的论坛程序, Discuz论坛的好几个表也存在着这个问题.于是顺手一并解决,cpu占用再次降下来了. 前几天,一位朋友通过这篇文章找到了我,说他就是运行最新的 discuz 版本,MySQL 占用 CPU 100%,导致系统假死,每天都要重启好几次,花了一个多月的时间一直没有解决,希望我帮忙一下.经过检查,他的这个论坛最重要的几个表中,目前 cdb_members 表,有记录 6.2 万:cdb_threads 表,有记录 11万:cdb_posts表,有记录

  • MySQL针对Discuz论坛程序的基本优化教程

    过了这么久,discuz论坛的问题还是困扰着很多网友,其实从各论坛里看到的问题总结出来,很关键的一点都是因为没有将数据表引擎转成InnoDB导致的,discuz在并发稍微高一点的环境下就表现的非常糟糕,产生大量的锁等待,这时候如果把数据表引擎改成InnoDB的话,我相信会好很多.这次就写个扫盲贴吧. 1. 启用innodb引擎,并配置相关参数 #skip-innodb innodb_additional_mem_pool_size = 16M #一般16M也够了,可以适当调整下 innodb_b

  • DISCUZ 论坛管理员密码忘记的解决方法

    DISCUZ论坛管理员密码忘记了怎么办? 今天,一个朋友在QQ上问我,"如果DISCUZ论坛管理员密码忘记了 从MYSQL 哪里找啊?", 他用的是HostMonster的虚拟主机. yun~~~, 自己也没用过DISCUZ,只好说,"这个不是很清楚,可以直接去改一下数据库的记录试一下, 但是不知道DISCUZ是否对密码加密了 " 后来他登录cPanel,用phpMyAdmin进去查看, 又晕了,一堆表不知道是哪个,在google一下查到了"Discuz

  • 由于mysql运行权限导致无法找到 Discuz! 论坛数据表! 的解决方法

    无法找到 Discuz! 论坛数据表! 在5.5升级到6.0时,上传完后,运行http://*****.com/upgrade9.php 时出下下列问题: 无法找到 Discuz! 论坛数据表! 请修改 config.inc.php 当中关于数据库的设置,然后上传到论坛目录,重新开始升级 config.inc.php 这个文件我用的是以前的,应该没有问题的. 解决方法:刷新N次,就好了.真是不明白为什么. 发现了,原理mysql的权限是普通用户权限,我们可以先将权限设为系统帐户,问题就可以解决了

随机推荐