buuxtf [HFCTF2020]BabyUpload

题目源码

 <?php
error_reporting(0);
session_save_path("/var/babyctf/");  //读取/设置当前会话的保存路径
session_start();//启动新会话或者重用现有会话
require_once "/flag";//文件包含flag
highlight_file(__FILE__);
if($_SESSION['username'] ==='admin')
{
    $filename='/var/babyctf/success.txt';
    if(file_exists($filename)){
            safe_delete($filename);
            die($flag);
    }
}
else{
    $_SESSION['username'] ='guest';
}

判断session的username是admin,并且/var/babyctf下是否有success.txt,如果存在,删除文件并输出$flag。
否则设置username为guest

$direction = filter_input(INPUT_POST, 'direction');
$attr = filter_input(INPUT_POST, 'attr');
$dir_path = "/var/babyctf/".$attr;
if($attr==="private"){
    $dir_path .= "/".$_SESSION['username'];
}

设置两个post参数direction、attr,
$dir_path拼接路径,若$attr为private,在$dir_path的基础上再拼接一个username

if($direction === "upload"){
    try{
        if(!is_uploaded_file($_FILES['up_file']['tmp_name'])){
            throw new RuntimeException('invalid upload');
        }
        $file_path = $dir_path."/".$_FILES['up_file']['name'];
        $file_path .= "_".hash_file("sha256",$_FILES['up_file']['tmp_name']);
        if(preg_match('/(\.\.\/|\.\.\\\\)/', $file_path)){
            throw new RuntimeException('invalid file path');
        }
        @mkdir($dir_path, 0700, TRUE);
        if(move_uploaded_file($_FILES['up_file']['tmp_name'],$file_path)){
            $upload_result = "uploaded";
        }else{
            throw new RuntimeException('error while saving');
        }
    } catch (RuntimeException $e) {
        $upload_result = $e->getMessage();
    }
}

如果direction设置为upload,
判断是否正常上传,不是则输出为invalid upload(无效的上传)
是则在$dir_path下拼接文件名$dir_path."/".$_FILES['up_file']['name'];
紧接着再拼接一个_,同时加上文件名的sha256值,
preg_match('/(\.\.\/|\.\.\\\\)/', $file_path)限制了目录穿越,
mkdir创建相应目录,把文件上传到目录下。

elseif ($direction === "download") {
    try{
        $filename = basename(filter_input(INPUT_POST, 'filename'));
        $file_path = $dir_path."/".$filename;
        if(preg_match('/(\.\.\/|\.\.\\\\)/', $file_path)){
            throw new RuntimeException('invalid file path');
        }
        if(!file_exists($file_path)) {
            throw new RuntimeException('file not exist');
        }
        header('Content-Type: application/force-download');
        header('Content-Length: '.filesize($file_path));
        header('Content-Disposition: attachment; filename="'.substr($filename, 0, -65).'"');
        if(readfile($file_path)){
            $download_result = "downloaded";
        }else{
            throw new RuntimeException('error while saving');
        }
    } catch (RuntimeException $e) {
        $download_result = $e->getMessage();
    }
    exit;
}
?>

设置两个post参数filename
若direction设置为download,
读取上传上来的filename文件名,拼接为$file_path,
同样限制了目录穿越,
判断文件是否存在,不存在返回file not exist存在则返回文件内容。

解题思路

flag输出

1、session的username是admin,
2、并且/var/babyctf下是否有success.txt,

伪造session

伪造session使session的username是admin,
php的session默认存储文件名是sess_+PHPSESSID的值,
构造direction=download&attr=&filename=sess_31d87a3d609f33744bd238dec7eaed00post传入
在这里插入图片描述
不同的引擎所对应的session的存储方式不相同。

php_binary:存储方式是,键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值
php:存储方式是,键名+竖线+经过serialize()函数序列处理的值
php_serialize(php>5.5.4):存储方式是,经过serialize()函数序列化处理的值

根据回显判断
在这里插入图片描述回显结果没有竖线,又有键名+经过serialize()函数序列化处理的值
所以因该为php_binary存储方式
可以在本地利用php_binary生成我们要伪造的session文件并计算sha256。

<?php
ini_set('session.serialize_handler', 'php_binary');
session_save_path("D:\\phpstudy_pro\\WWW\\testphp\\");
session_start();
$_SESSION['username'] = 'admin';

在这里插入图片描述法一
在线文件hash计算

在这里插入图片描述法二
卡里

php -r "echo hash_file("sha256","文件路径加文件名");"

使用postman上传文件

POST请求
根据$dir_path."/".$_FILES['up_file']['name'];
在这里插入图片描述
检查上传成功与否,

direction=download&attr=&filename=sess_432b8b09e30c4a75986b719d1312b63a69f1b833ab602c9ad5f0299d1d76a5a4

username是admin,伪造成功
在这里插入图片描述

创建success.txt并上传

需要创建一个success.txt上传来满足判断,
$filename是通过file_exists来判断的,
file_exists函数在php中检查文件或检查文件目录是否存在
所以,文件名设置不了,直接创建目录也符合条件,将attr设置为success.txt创建目录,再将sess上传到该目录下即可绕过判断
postman上传success.txt
在这里插入图片描述
测试上传是否成功
在这里插入图片描述

输出flag

条件已经满足,只需构造PHPSESSID=sess文件sha256值,刷新即可输出flag
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值