安全-Pass14之文件头绕过(upload-labs)

Posted 小狐狸FM

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安全-Pass14之文件头绕过(upload-labs)相关的知识,希望对你有一定的参考价值。

前言

  • 前面13关的笔记已经对php的源码分析过了,之后的关卡代码类似,就不再一步步分析了
  • phpHypertext Preprocessor超文本预处理器,多用于web后端
  • BUUCTF的upload-labs在线靶场和本地的靶场有点差别,如果用文章的方法没法绕过时,注意看一下源码是否一致

相关介绍

PHP 百度百科

PHP: PHP 手册 - Manual

文件头 百度百科

PHP: fopen - Manual

PHP:fread - Manual

PHP:fclose - Manual

PHP:intval - Manual

PHP unpack()函数 | 菜鸟教程

其他介绍

文件上传绕过思路集合

upload-labs靶场下载

upload-labs在线靶场-BUUCTF

蚁剑AntSword

菜刀Cknife

Seay

一、题目

php后端代码

function getReailFileType($filename){
    $file = fopen($filename, "rb");
    $bin = fread($file, 2); //只读2字节
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    
    $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    
    $fileType = '';    
    switch($typeCode){      
        case 255216:            
            $fileType = 'jpg';
            break;
        case 13780:            
            $fileType = 'png';
            break;        
        case 7173:            
            $fileType = 'gif';
            break;
        default:            
            $fileType = 'unknown';
        }    
        return $fileType;
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_type = getReailFileType($temp_file);

    if($file_type == 'unknown'){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}

二、WriteUp

[1]. 函数介绍

getReailFileType是靶场自己设置的函数
@是错误控制运算符,在函数前面添加@符号表示屏蔽错误提示

PHP函数介绍
date(格式)以固定的时间格式获取当前系统的时间
fopen(文件路径,模式)以指定的模式打开文件,返回文件指针
fread(文件指针,字节个数)获取文件中指定字节个数的内容
fclose(文件指针)关闭一个文件指针
intval(变量)获取变量的整数值
move_uploaded_file(文件路径,文件夹路径)将文件移动到指定文件夹下
rand(数字1,数字2)从数字1到数字2的范围内生成随机数,两个数字都有包含在内
@unpack(模式,二进制数据)以指定模式,从二进制字符串对数据进行解包

[2]. 源码审计

创建upload.phpshow.php文件,将题目中重要的代码贴进去,show.php用于显示变量的内容


<form enctype="multipart/form-data" method="post" action="show.php">
    <p>上传图片</p>
    <input class="input_file" type="file" name="upload_file"/>
    <input class="button" type="submit" name="submit" value="提交"/>
</form>

<?php
$filename = $_FILES['upload_file']['tmp_name'];
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只读2字节
fclose($file);
$strInfo = @unpack("C2chars",$bin);
$typeCode = intval($strInfo["chars1"].$strInfo["chars2"]);

echo $filename;//显示上传的路径
echo "<br>";
echo $bin;//显示文本前两个字节内容
echo "<br>";
echo $strInfo;//数组
echo "<br>";
echo $strInfo["chars1"];//第一个字节
echo "<br>";
echo $strInfo["chars2"];//第二个字节
echo "<br>";
echo $typeCode;//显示前两个字节的十六进制数
?>
  • 使用winhex010editor创建一个文件,在ascii位置任意输入内容
  • 1 byte(字节) = 8 bit(比特)
    1 hex(十六进制) = 4 bit(比特)

再上传文件,测试php代码中各个变量的内容
变量$filename被赋值成了上传文件的tmp_name临时保存路径,这个值每上传一次都会变化,不会影响最终结果

变量
$filenameC:\\Windows\\php95C6.tmp
$binni
$strInfoArray
$strInfo[“chars1”]110
$strInfo[“chars2”]105
$typeCode110105


110105分别是字符niASCII码值
所以我们需要绕过的话就只需要修改前两个字节(前四位十六进制数)的内容

字符ASCII十六进制数
n1106E
i10569

getReailFileType函数中有一个switch用来判断文件的前两个字节的内容
如果文本的前两个字节不为255216137807173时,函数返回的变量值就是unknown

[3]. 绕过

使用winhex010editor创建一个十六进制文件,先将前两个字节替换成下方图片类型对应的十六进制数

十进制十六进制类型
255 216FF D8jpg
137 8089 50png
71 7347 49gif

再添加一句话木马进去

成功绕过限制上传了木马文件,因为图片马需要结合文件包含的漏洞才能连接shell,所以能够绕过限制上传完整的木马文件就达成了目的


以上是关于安全-Pass14之文件头绕过(upload-labs)的主要内容,如果未能解决你的问题,请参考以下文章

安全-Pass08之黑名单点绕过(upload-labs)

安全-Pass07之黑名单空格绕过(upload-labs)

安全-Pass03之黑名单绕过(upload-labs)

安全-Pass10之黑名单点空点绕过(upload-labs)

安全-Pass09之黑名单::$DATA绕过(upload-labs)

安全-Pass05之黑名单.user.ini绕过(upload-labs)