0x01 前言
> 跟着@Joseph 大牛学习代码审计系列(J牛审计文章见:https://forum.90sec.org/forum.php?mod=viewthread&tid=10630)
> author:小草
BEESCMS企业网站管理系统拥有简单方便的模板标签,能够快速做出模板;自定义表单,自定义模型,内置新闻、下载、产品、招聘、单页模型;SEO功 能,每个页面都可以单独SEO优化;多语言,多风格,每种语言每个页面都可以定义风格;html静态页面生成功能;BEES还可以自定义flash引导页。
审计的是最新版本:v4
0x02 大牛的步伐
@Joseph 大牛审计漏洞出现在了 /member/member.php 文件上,
if($action=='ajajx_out'){ $sql="update ".DB_PRE."member set member_time='{$_SESSION['m_time']}',member_ip='{$_SESSION['m_ip']}' where id={$_SESSION['member_id']}";这段代码中由于 $_SESSION['m_ip'] 的值没有过滤,由get_ip()函数获取,而get_ip()函数值可以通过 x-forwarded-for来伪造造成了注入
但是漏洞过程比较繁琐,因为出现在了会员系统上,所以还需要注册一个新用户才能触发漏洞
0x03 跟随大牛的步伐
目的:J牛的利用方法有点复杂,想找个简单点的利用方法 因为beescms系统有着全局防注入,所有get post cookies请求都会被转换,所以需要找到一个未被转换的点。 全局搜索了下get_ip()出现的地方,在mx_form\order_save.php文件出现了 这是一个订单提交处理文件,说明可以之间在前台进行利用

但是这个一开始就被验证码挡住了,虽然验证码没什么大问题,但想着如果能写个批量化脚本验证的话,绕过验证码岂不是要好点。虽然弄个验证码的识别很容易。
然后看了下源码,在init.php中
@extract($_POST); @extract($_GET); @extract($_COOKIE);这不就是变量覆盖漏洞吗?
所以可以这样提交来绕过验证码
POST http://127.0.0.1/beescms/mx_form/order_save.php DATA feed_code=a&_SESSION=a
还是到后面这里就不知道怎么绕过了
if(!empty($fields)){ foreach($fields as $key=>$value){ if(!is_array($value)){ if(!in_array($key,$fd)){die("223333");} } $sql_field.=','.$key; if(is_array($value)){ foreach($value as $k=>$v){ $value_str.=$v.','; } $value=$value_str; } $sql_value.=",'".fl_html($value)."'"; } }else{ die($language['order_msg2']); }可以伪造$fields变量,但怎么伪造$fields变量的值是个数组呢? 。。
进行到这一步戛然而止 = -
然后找了下资料,发现曾经的dedecms变量覆盖漏洞有类似的利用方法,根据它的经验
修改如下的post data
feed_code=a&_SESSION[code]=a&form_id=5&fields[aaa][nnn]=1111
成功造成了注入
0x04 后台任意登陆
既然存在变量覆盖漏洞,那么就有很多可以利用的点
在这款CMS后台中,是如何检测登陆的呢?
//检查登陆 if(!is_login()){header('location:login.php');exit;}
is_login() 原型方法
function is_login(){ if($_SESSION['login_in']==1&&$_SESSION['admin']){ if(time()-$_SESSION['login_time']>3600){ login_out(); }else{ $_SESSION['login_time']=time(); @session_regenerate_id(); } return 1; }else{ $_SESSION['admin']=''; $_SESSION['admin_purview']=''; $_SESSION['admin_id']=''; $_SESSION['admin_time']=''; $_SESSION['login_in']=''; $_SESSION['login_time']=''; $_SESSION['admin_ip']=''; return 0; } }由于前面的变量覆盖漏洞,$_session可以伪造,is_login()只要判断成功,后面再无判断
0x05 后台sql注入
出现在了后台 /admin/login.php 文件中,因为没有加载init.php这个文件(init.php包含了全局防注入代码)
//判断登录 elseif($action=='ck_login'){ global $submit,$user,$password,$_sys,$code; $submit=$_POST['submit']; $user=fl_html(fl_value($_POST['user'])); $password=fl_html(fl_value($_POST['password'])); $code=$_POST['code']; if(!isset($submit)){ msg('请从登陆页面进入'); } if(empty($user)||empty($password)){ msg("密码或用户名不能为空"); } if(!empty($_sys['safe_open'])){ foreach($_sys['safe_open'] as $k=>$v){ if($v=='3'){ if($code!=$s_code){msg("验证码不正确!");} } } } check_login($user,$password); }
所以这个文件注入就很简单了,
function fl_value($str){ if(empty($str)){return;} return preg_replace('/select|insert | update | and | in | on | left | joins | delete |\%|\=|\/\*|\*|\.\.\/|\.\/| union | from | where | group | into |load_file |outfile/i','',$str); } define('INC_BEES','B'.'EE'.'SCMS'); function fl_html($str){ return htmlspecialchars($str); }
fl_html是html过滤,对sql影响不大
fl_value的原型是替换掉那些关键词,但是可以构造如 anandd 等等之类的绕过
发表评论