ourphp 前台注册登入前台某用戶

代码审计 2019-11-10

本文作者:myndtt(信安之路读者首次投稿)

一.漏洞前提

1.下载地址页面(截至2018/7/6 目前最新版)

https://pan.baidu.com/s/1D9HWq#list/path=%2F

2.前台可通过邮箱注册用户

3.注册邮箱形式可以如下

1'/**/or/**/1=1#@qq.com` `2'/**/or/**/1=1/**/limit/**/1/**/offset/**/2#@q.c

4.正因为要注册这些古怪的邮箱,并且利用起来略有复杂,所以比较鸡肋。

二.漏洞分析

function\api\ourphpuser\ourphp_system.php该文件存在用户login函数

functionuser_login($useremail,$password){
global$db;
if($useremail==""||$password==""){

return"-1"; //不能为空
exit;

}else{

$ourphp_rs=$db->select("`id`,`OP_Userstatus`,`OP_Userclass`","`ourphp_user`","where (`OP_Useremail` = '".dowith_sql($useremail)."' || `OP_Usertel` = '".dowith_sql($useremail)."') && `OP_Userpass` = '".dowith_sql(substr(md5(md5($password)),0,16))."'");
$userclass=$db->select("OP_Useropen","ourphp_userleve","where id = ".intval($ourphp_rs[2]));

if(!$ourphp_rs){

return"-4"; //账户不存在或密码错误
exit;

}elseif($ourphp_rs[1] ==2||$userclass[0] ==1){

return"-5"; //账户被锁定
exit;

}else{

$_SESSION['username'] =$useremail;
return"200";

}
}
}

在登入过程中$_SESSION['username'] = $useremail; 用户注册的邮箱也即用户名被赋值给$_SESSION['username'].

client\user\index.php文件中有大量存在直接使用$_SESSION['username']带入数据库查询的操作

if($type=='car'){

$ourphp_rs=$db->listgo("count(id) as tiaoshu","`ourphp_shoppingcart`","where `OP_Shopusername` = '".$_SESSION['username']."'");

}elseif($type=='shopping'){

$ourphp_rs=$db->listgo("count(id) as tiaoshu","`ourphp_orders`","where `OP_Ordersemail` = '".$_SESSION['username']."' && `OP_Orderspay` = 1");

}elseif($type=='msgemail'){

$ourphp_rs=$db->listgo("count(id) as tiaoshu","`ourphp_usermessage`","where `OP_Usercollect` = '".$_SESSION['username']."' && `OP_Userclass` = 1");

即然$_SESSION['username']没有被做任何操作,又与用户注册的邮箱有关系,那么去用户注册处查看相关情况。

client\user\ourphp_play.class.php文件中的有用户注册相关的函数

if($ourphp_rs[6] =='email'){
$userloginemail=$_POST["OP_Useremail"];
$userlogintel=$_POST["OP_Useremail"];
if($userloginemail==''||$_POST["OP_Userpass"] ==''||$_POST["OP_Userpass2"] ==''){
exit("<script language=javascript> alert('".$inputno."');history.go(-1);</script>");
}elseif(strlen($userloginemail) >50){
exit("<script language=javascript> alert('".$usernameyes."');history.go(-1);</script>");
}
$emailvar=filter_var($userloginemail, FILTER_VALIDATE_EMAIL);
if(!$emailvar){
exit("<script language=javascript> alert('".$accessno."');history.go(-1);</script>");
}
}elseif($ourphp_rs[6] =='tel'){

邮箱需要通过该代码$emailvar = filter_var($userloginemail, FILTER_VALIDATE_EMAIL);,根据网络文档所示

img

没有找到比较直观的东西,但是这个FILTER_SANITIZE_EMAIL却可以作为一个参考。最后测试出该过滤器可允许!#$%&'*+-/=?^_{|}~@.[]等大量恶意字符(括号和逗号似乎不可以),那么漏洞就可由此产生(当然该函数不仅仅是字符那样简单,比如xx@q.c类邮箱可以通过,xx@q.不可以)。

三.漏洞演示流程

一.本地建好网站,为了演示,注册一些正常用户。

二.随后注册一个恶意用户1'/**/or/**/1=1#@qq.com,因为前台有js检测防护,所以需要在注册时关闭浏览器执行js

(由于该cms的验证码也是在js中,所以这样也是可以进行绕过验证码进行爆破)

img

三.将刚刚的邮箱进行登入

img

四.当然如果想要任意用户登入的话还需要借助limit,offset等进行偏移,可以注册如下此类邮箱,从而偏移

2'/**/or/**/1=1/**/limit/**/1/**/offset/**/2#@q.c

img

这里涉及到一个邮箱字段长度限制问题,于client\user\ourphp_play.class.php文件中

if($ourphp_rs[6] =='email'){
$userloginemail=$_POST["OP_Useremail"];
$userlogintel=$_POST["OP_Useremail"];
if($userloginemail==''||$_POST["OP_Userpass"] ==''||$_POST["OP_Userpass2"] ==''){
exit("<script language=javascript> alert('');history.go(-1);</script>");
}elseif(strlen($userloginemail) >50){

exit("<script language=javascript> alert('".$usernameyes."');history.go(-1);</script>");
}

可以通过抓包方式抓取,否则因为Url编码的问题字符就会超长

img

当然这里注册的邮箱引号和or之间的/**/是可以不要的。

四.唠唠嗑

1.由于能力有限,只能这样利用漏洞,不知大家有没有其他想法。

2.据观察,有不少cms都有这样利用filter_var($userloginemail, FILTER_VALIDATE_EMAIL);来过滤检测邮箱,这会有潜在的风险,审计时大家可以留意。

3.回到该cms上,该防过滤函数(没大问题),但在过滤andor时左右加个空格完全是没必要的。

img

4.最后最新版已经进行了修改,似乎不能做出其他操作来了。

img

5.这是一个很简单的漏洞,即便如此,也祝愿大家能有所收获,共勉!


本文由 信安之路 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

楼主残忍的关闭了评论