from:http://www.wooyun.org/bugs/wooyun-2013-044824
属于php漏洞挖掘。本来先搞套源码自己试试。。无奈没从网上找到源码。
code1:
function CS_Request($pi_strName)
{
set_magic_quotes_runtime(0); //明显要用addslashes
$magic= get_magic_quotes_gpc();
if ( isset($_GET[$pi_strName]) ){
$t_Val = $magic?trim($_GET[$pi_strName]):addslashes(trim($_GET[$pi_strName]));
}else if ( isset($_POST[$pi_strName])){
$t_Val = $magic?trim($_POST[$pi_strName]):addslashes(trim($_POST[$pi_strName]));
}else{
return '';
}
return uhtml($t_Val);
}
magic_quotes_gpc设置为0 一律采用addslashes来过滤输入 (其实就是过滤 ' " \)
一切gpc都经过了过滤、
code2:
/user/member/skin_msg.php line:128
if(!empty($id)){ //id不能为空
$row=$db->getrow("select * from ".Getdbname('xiaoxi')." where CS_ID='".$id."'");
//上面这一句里id带上了引号,加上addslashes完全无法注射
//上面这一句的目的是 防止 非法数据起作用,先判断能否避免注射并且正常执行
if($row){//如果$row为真,即上一SQL成功执行并返回,则通过判定
$db->query("update ".Getdbname('xiaoxi')." set CS_DID=1 where CS_ID=".$id." and cs_usera='".$cscms_name."'");
//上面这一句里id没有带引号,如果前面无限制(第一句判定通过的话)应该可以盲注
//与以下语句无关,继续
if($row['CS_Userb']=='系统消息'){
$logo=piclink('logo','');
$link='#';
}else{
$us=$db->getrow("select * from ".Getdbname('user')." where CS_Name='".$row['CS_Userb']."'");
$logo=piclink('logo',$us['CS_Logo']);
$link=userlink('index',$us['CS_ID']);
}
第一句select :
$row=$db->getrow("select * from ".Getdbname('xiaoxi')." where CS_ID='".$id."'");
执行的sql语句如 select * from c_xiaoxi where CS_ID='1' 有单引号过滤。还有addslashes过滤 几乎不存在注入
第二句 $db->query("update ".Getdbname('xiaoxi')." set CS_DID=1 where CS_ID=".$id." and cs_usera='".$cscms_name."'");
执行的sql语句如 update c_xiaoxi set CS_DID=1 where CS_ID= 2 and cs_usera='......'
参数CS_ID没有单引号过滤。这样可能会产生注入。
这两句的区别是 单引号。单引号的作用是 CAST VARCHAR TO INT,类似intval尽力从起始位置恢复一个整数,而不会报错终止。 这样只要尽量维护第一个是数字 ,$row变量就是返回true。 也是漏洞的检测出问题了、。
比如 带入参数 id = 2 and 1
依然可以正确执行。
因为代码在user中 所以要先注册一个用户。登陆。注射的时候记得load cookies
单引号的注射 是数字型的
sqlmap的参数是 参数:MYSQL-TIME-BASED INTEGER
注射完毕 得到 数据用中用户的 hash
加密的密码 不一定能破解。。。
想办法登陆吧。
每一个admin下面的文件都包含loginstate.php 用来验证身份。
/admin/loginstate.php 开头没几行
code3:
if(empty($_COOKIE['CS_AdminID'])){
//COOKIE我们能控制
die("<script>window.parent.location='".CS_WebPath.$CS_Admin."login.php'</script>");
}elseif($_COOKIE['CS_Login']!=md5($_COOKIE['CS_AdminID'].$_COOKIE['CS_AdminUserName'].$_COOKIE['CS_AdminPassWord'].$_COOKIE['CS_Quanx'])){
//COOKIE我们能控制
die("<script>window.parent.location='".CS_WebPath.$CS_Admin."login.php'</script>");
}else{
global $db;
$rowa=$db->getrow("SELECT * FROM ".Getdbname('admin')." Where CS_ID='".$_COOKIE['CS_AdminID']."'");
//根据COOKIE里的admin id取数据
if($rowa){
if($rowa['CS_AdminName']!=$_COOKIE['CS_AdminUserName'] || md5($rowa['CS_AdminPass'])!=$_COOKIE['CS_AdminPassWord']){
//将取出的数据与COOKIE中数据比较,注意这里pass反向又用了md5,看来安全意识还是蛮高的,只是追求安全还用COOKIE这有点儿奇怪,到这里我们由注射拿到了CS_AdminName和CS_AdminPass,因此可以伪造COOKIE进后台了
//与以下代码无关
die("<script>window.parent.location='".CS_WebPath.$CS_Admin."login.php'</script>");
}
}else{
die("<script>window.parent.location='".CS_WebPath.$CS_Admin."login.php'</script>");
}
}
cookie我们能控制。所以不是问题。直接看if验证
if($rowa['CS_AdminName']!=$_COOKIE['CS_AdminUserName'] || md5($rowa['CS_AdminPass'])!=$_COOKIE['CS_AdminPassWord']){
用户名相同不必说 后面是 cookie中的密码 和 数据库中取出的密码的MD5加密要相同。
也就是说 数据库中存的密码是 真实密码的md5 cookie中的密码存储的是 真实密码md5的md5.
因为注射得到了 MD5(pwd) 所以 可以绕过登陆。
至此改了cookie直接可以进入后台。
后台有个编辑模板的功能。然后它竟然可以改后缀名。。 哦凑。 一句话上。
拿下webshell
解决方案:
1. 注入部分记得加单引号过滤
2.登陆部分不要使用用户可控的cookie ,可以使用session
3.编辑模板在服务器上强制加html后缀。
最后 这个大牛提交的漏洞。。竟然被忽略了。。。 我为他默哀。。。。。