19-PHP代码审计——jizhicms逻辑漏洞分析(由越权引发的sql注入)
Posted songly_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19-PHP代码审计——jizhicms逻辑漏洞分析(由越权引发的sql注入)相关的知识,希望对你有一定的参考价值。
影响版本:
jizhicms_Beta1.7
漏洞环境:
jizhicms_Beta1.7
php5.6.27
越权修改积分是前台用户界面的用户资料功能导致的
为什么用户资料功能存在越权漏洞?首先分析用户资料功能的userinfo函数:
function userinfo(){
$this->checklogin();
if($_POST){
//首先对提交的内容进行过滤
$w = $this->frparam();
$w['tel'] = $this->frparam('tel',1);
$w['pass'] = $this->frparam('password',1);
$w['sex'] = $this->frparam('sex',0,0);
$w['repass'] = $this->frparam('repassword',1);
$w['username'] = $this->frparam('username',1);
$w['email'] = $this->frparam('email',1);
$w['litpic'] = $this->frparam('litpic',1);
$w['signature'] = $this->frparam('signature',1);
$w = get_fields_data($w,'member',0);
if($w['tel']!=''){
if(preg_match("/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\\\d{8}$/",$w['tel'])){
}else{
if($this->frparam('ajax')){
JsonReturn(['code'=>1,'msg'=>'手机号码格式错误!']);
}
Error('手机号码格式错误!');
}
//檢查是否已經註冊
$r = M('member')->find(['tel'=>$w['tel']]);
if($r){
if($r['id']!=$this->member['id']){
if($this->frparam('ajax')){
JsonReturn(['code'=>1,'msg'=>'手机号已被注册!']);
}
Error('手机号已被注册!');
}
}
}
if($w['username']==''){
if($this->frparam('ajax')){
JsonReturn(['code'=>1,'msg'=>'账户不能为空!']);
}
Error('账户不能为空!');
}
if($w['pass']!=$w['repass'] && $w['pass']!=''){
if($this->frparam('ajax')){
JsonReturn(['code'=>1,'msg'=>'两次密码不同!']);
}
Error('两次密码不同!');
}
if($w['email']){
$r = M('member')->find(['email'=>$w['email']]);
if($r){
if($r['id']!=$this->member['id']){
if($this->frparam('ajax')){
JsonReturn(['code'=>1,'msg'=>'邮箱已被使用!']);
}
Error('邮箱已被使用!');
}
}
}
$r = M('member')->find(['username'=>$w['username']]);
if($r){
if($r['id']!=$this->member['id']){
if($this->frparam('ajax')){
JsonReturn(['code'=>1,'msg'=>'昵称已被使用!']);
}
Error('昵称已被使用!');
}
}
if($w['pass']!=''){
$w['pass'] = md5(md5($w['pass']).md5($w['pass']));
}else{
unset($w['pass']);
unset($w['repass']);
}
//前面的基本都是对提交的内容进行过滤
//更新用户资料
$re = M('member')->update(['id'=>$this->member['id']],$w);
$member = M('member')->find(['id'=>$this->member['id']]);
unset($member['pass']);
$_SESSION['member'] = array_merge($_SESSION['member'],$member);
if($this->frparam('ajax')){
JsonReturn(['code'=>0,'msg'=>'修改成功!']);
}
Error('修改成功!');
}
$this->display($this->template.'/user/userinfo');
}
userinfo函数的功能很简单,首先userinfo函数调用了核心过滤函数进行过滤,校验完毕后直接更新了用户的信息。
userinfo函数内部有一行代码比较关键,这行代码接收了所有提交的数据:
$w = $this->frparam();
由于这里this对象调用frparam函数没有传参,因此这里frparam函数的str参数默认为null就会直接返回了data,这一步操作没有任何过滤。
update是根据查询到的用户id进行更新用户信息,数组w中要更新的内容就是我们提交的数据
看起来代码逻辑是不是很正常,没有问题?没有漏洞那还分析个什么劲...... 这里的问题在于,userinfo函数在接收数据时没有进行限制,啥意思?
我们先来看一个正常流程,当填完修改的用户信息点击提交后,burpsuite工具中抓到的这段数据就是我们提交用户资料的内容
正常情况下userinfo函数接收到数据后先过滤校验,然后再更新用户信息,也就是说我们提交什么数据都会被数组w接收,数据库中对应的数据就会被更新,当然前提是该数据再数据库中有记录。
如果我们想要修改用户的积分,就可以在burpsuite工具中提交的请求消息中再添加一个参数jifen=123,如下所示
可以看到最终页面返回修改成功,刷新页面用户的积分变成了123。
正常的流程积分是通过充值获取的,但是攻击者通常都是不按常理出牌的,由于积分也是属于用户的信息,也就是说修改用户信息功能和积分功能操作的是同一数据库表,并且修改用户资料的时候也没有对修改的内容限定范围,导致用户资料修改的时候越权修改了积分。
看起来越权修改积分漏洞好像危害也不是特别大,现在仔细思考一下,我们利用这个漏洞是不是还可以做其他事情?是的,我们可以通过jifen参数绕过过滤实现sql注入
可以看到成功把当前数据库信息爆出来,接着依次可以爆出所有表名,字段名和数据,这样漏洞的危害一下子就放大了,漏洞分析完毕。
越权漏洞分析和挖掘思路:分析功能点如何接收处理前端传入的数据,分析update函数更新了哪些数据,是否可以修改其他功能的数据,是否存在多个功能操作了同一数据库表。
总结:越权修改积分本质上是一个逻辑漏洞,但是在此基础上又触发了sql注入漏洞,原因在于代码逻辑不够严谨,考虑的不够全面,没有对修改的内容限制。通过这个漏洞可以知道,即使有预编译和过滤函数也不存在绝对的安全,还是可能会存在sql注入,我们在进行漏洞挖掘的时候不要被当前的信息限制思路。通过这个案例让我们有了一种新的思维方式:在现有的基础上,尽可能的尝试更多的挖洞方式,多思考一下,我还能在这个漏洞的基础上做什么?而不是仅仅满足现状。
最后再总结一下手工挖掘sql注入的:首先确定可控变量,再定位过滤函数。接着分析过滤函数是否可绕过,如果可绕过就构造sql注入语句,如果不可绕过则从功能代码逻辑入手,进一步分析业务逻辑的具体流程对可控变量的每一步处理,分析是否间接修改可控变量,是否可利用,因为有的sql注入可能是业务操作触发的。在以上思路都行不通的情况下,手工sql注入挖掘的另一种思路就是,通过其他漏洞触发sql注入,具体思路参考:由越权修改引发的sql注入案例。
以上是关于19-PHP代码审计——jizhicms逻辑漏洞分析(由越权引发的sql注入)的主要内容,如果未能解决你的问题,请参考以下文章
21-PHP代码审计——jizhicms1.9.5文件上传漏洞
21-PHP代码审计——jizhicms1.9.5文件上传漏洞
17-PHP代码审计——jizhicms1.6.7 sql注入漏洞分析
17-PHP代码审计——jizhicms1.6.7 sql注入漏洞分析