代码审计入门-BEESCMS4.0

简介

BEESCMS企业网站管理系统是一款PHP+MYSQL的多语言系统,内容模块易扩展,模板风格多样化,模板制作简单功能强大,专业SEO优化,后台操作方便,完全可以满足企业网站、外贸网站、事业单位、教育机构、个人网站使用。
该CMS适合入门代码审计。

后台登陆SQL注入漏洞

admin\Login.php中有如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//判断登录
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和password经过fl_value函数和fl_html处理
而fl_value函数如下:

1
2
3
4
5
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);
}

该函数仅使用preg_replace函数对关键词进行处理,因此可以双写绕过。
fl_html函数使用主要是为了防止xss漏洞,无关紧要。
往下使用check_login函数进行判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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");
}

该函数先向数据库查询$user,然后将输入的$password的MD5值与查询得到的$rel[‘admin_password’]进行比较,相同则能成功登陆。可以构造:
user:0’ un/**ion se/**lect 1,1,’202cb962ac59075b964b07152d234b70’,1,0;#
password :123(’202cb962ac59075b964b07152d234b70’是’123’的MD5值)
成功的绕过登陆:

任意文件上传漏洞

在admin/upload.php中有如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
if(isset($_FILES['up'])){
if(is_uploaded_file($_FILES['up']['tmp_name'])){
if($up_type=='pic'){
$is_thumb=empty($_POST['thumb'])?0:$_POST['thumb'];
$thumb_width=empty($_POST['thumb_width'])?$_sys['thump_width']:intval($_POST['thumb_width']);
$thumb_height=empty($_POST['thumb_height'])?$_sys['thump_height']:intval($_POST['thumb_height']);
$logo=0;
$is_up_size = $_sys['upload_size']*1000*1000;
$value_arr=up_img($_FILES['up'],$is_up_size,array('image/gif','image/jpeg','image/png','image/jpg','image/bmp','image/pjpeg'),$is_thumb,$thumb_width,$thumb_height,$logo);
$pic=$value_arr['pic'];
if(!empty($value_arr['thumb'])){
$pic=$value_arr['thumb'];
}
$str="<script type=\"text/javascript\">$(self.parent.document).find('#{$get}').val('{$pic}');self.parent.tb_remove();</script>";
echo $str;
exit;
}//图片上传
}else{
die('没有上传文件或文件大小超过服务器限制大小<a href="javascript:history.back(1);">返回重新上传</a>');
}
}
?>

上传的文件被传入函数up_img中,同时还传入了允许文件上传类型的白名单。up_img函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function up_img($file,$size,$type,$thumb=0,$thumb_width='',$thumb_height='',$logo=1,$pic_alt=''){
if(file_exists(DATA_PATH.'sys_info.php')){include(DATA_PATH.'sys_info.php');}
if(is_uploaded_file($file['tmp_name'])){
if($file['size']>$size){
msg('图片超过'.$size.'大小');
}
$pic_name=pathinfo($file['name']);//图片信息

$file_type=$file['type'];
if(!in_array(strtolower($file_type),$type)){
msg('上传图片格式不正确');
}
$path_name="upload/img/";
$path=CMS_PATH.$path_name;
if(!file_exists($path)){
@mkdir($path);
}
$up_file_name=empty($pic_alt)?date('YmdHis').rand(1,10000):$pic_alt;
$up_file_name2=iconv('UTF-8','GBK',$up_file_name);
$file_name=$path.$up_file_name2.'.'.$pic_name['extension'];

if(file_exists($file_name)){
msg('已经存在该图片,请更改图片名称!');//判断是否重名
}

$return_name['up_pic_size']=$file['size'];//上传图片大小
$return_name['up_pic_ext']=$pic_name['extension'];//上传文件扩展名
$return_name['up_pic_name']=$up_file_name;//上传图片名
$return_name['up_pic_path']=$path_name;//上传图片路径
$return_name['up_pic_time']=time();//上传时间
unset($pic_name);
//开始上传
if(!move_uploaded_file($file['tmp_name'],$file_name)){
msg('图片上传失败','',0);
}
...//省略后边的无关代码
}

问题出在这里:

1
2
3
4
$file_type=$file['type'];
if(!in_array(strtolower($file_type),$type)){
msg('上传图片格式不正确');
}

对文件类型进行判断时取的是mime类型,可以通过burpsuit抓包更改。
文件名称的处理为:

1
2
3
$up_file_name=empty($pic_alt)?date('YmdHis').rand(1,10000):$pic_alt;
$up_file_name2=iconv('UTF-8','GBK',$up_file_name);
$file_name=$path.$up_file_name2.'.'.$pic_name['extension'];

文件后缀取的是$pic_name[‘extension’]!!!
文件名称虽然被更改并且随机化,但可以枚举的办法获得。此外可以在后台网站基本设置logo图片处上传php文件抓包更改mime类型后,可以看到文件名。


获得地址:http://127.0.0.1/upload/img/201812031932133189.php