PHP文件上传漏洞原理以及防御姿势

这篇具有很好参考价值的文章主要介绍了PHP文件上传漏洞原理以及防御姿势。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

0x00 漏洞描述
​ 在实际开发过程中文件上传的功能时十分常见的,比如博客系统用户需要文件上传功能来上传自己的头像,写博客时需要上传图片来丰富自己的文章,购物系统在识图搜索时也需要上传图片等,文件上传功能固然重要,但是如果在实现相应功能时没有注意安全保护措施,造成的损失可能十分巨大,为了学习和研究文件上传功能的安全实现方法,我将在下文分析一些常见的文件上传安全措施和一些绕过方法。

​ 我按照最常见的上传功能–上传图片来分析这个漏洞。为了使漏洞的危害性呈现的清晰明了,我将漏洞防御措施划分为几个不同的等级来作比较

0x01 前端HTML页面代码

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>
    file_upload_test
</title>
<body>
<form enctype="multipart/form-data" action="upload_1.php" method="POST" />
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
选择你要上传的图片:
<br />
<input name="uploaded" type="file" /><br />
<br />
<input type="submit" name="Upload" value="上传" />
</form>
</body>
</html>

前端的实现代码均为以上。界面如下图:

$uploaded_size < 100000解释,安全,php,服务器,网络安全

0x01 零防御的PHP上传代码

源代码 upload_0.php

<?php
if (isset($_POST['Upload'])) {
    $target_path = "uploads/";
    $target_path = $target_path . basename( $_FILES['uploaded']['name']);
    if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
        echo '<pre>';
        echo '您的图片上传失败.';
        echo '</pre>';
    } else {
        echo '<pre>';
        echo $target_path . '文件已经成功上传!';
        echo '</pre>';
    }
}
?>

这段PHP代码对上传的文件没有任何的过滤,只是将上传的文件直接存储到了网站uploads文件夹下,此时如果我们上传一个一句话木马并通过浏览器访问加上参数的地址或者使用中国菜刀直接连接,就可以为所欲为了。

//一句话木马
<?php eval($_GET['cmd']);?>

0x01 初级防护-验证文件类型

源代码 upload_1.php

<?php
if( isset( $_POST[ 'Upload' ] ) ) {
    $target_path  = "uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    //识别文件类型
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
        ( $uploaded_size < 100000 ) ) {
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            echo "<pre>图片上传失败</pre>";
        }
        else {
            echo "<pre>{$target_path} 图片上传成功!</pre>";
        }
    }
    else {
        echo "<pre>只允许上传jpg或者png格式的图片文件,且文件大小不能超过100k</pre>";
    }
}
?>

防御方法

初级防御的代码在审查用户上传的文件时加入了“Content-Type”验证,代码会自动识别文件类型并将文件类型以表单的形式进行验证,如果“Content-Type”是image/jpeg或者image/png时文件可以上传 成功,算是初级防御。

绕过方法

用BurpSuite截断代理修改数据包的相关字段即可完成绕过,本例上传的文件时shell.php,代码会将此文件的Content-Type识别为application/x-php,直接将application/x-php改为mage/jpeg即可绕过验证,而且对于文件大小的限制也是可以直接修改”MAX_FILE_SIZE”的方式突破限制从而上传更大的文件。

 文章来源地址https://www.toymoban.com/news/detail-786399.html

$uploaded_size < 100000解释,安全,php,服务器,网络安全

修改前

修改后

 

$uploaded_size < 100000解释,安全,php,服务器,网络安全

 

$uploaded_size < 100000解释,安全,php,服务器,网络安全

0x02 一般防护-验证文件后缀

源代码 upoad_2.php

<?php
if( isset( $_POST[ 'Upload' ] ) ) {
    $target_path  = "uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    //记录文件信息
    $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' ];
    //识别文件后缀
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) ) {
        if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
            echo "<pre>图片上传识别.</pre>";
        }
        else {
            echo "<pre>{$target_path} 图片上传成功!</pre>";
        }
    }
    else {
        echo "<pre>只能上传格式为jpg和png的图片.</pre>";
    }
}
?>

$uploaded_size < 100000解释,安全,php,服务器,网络安全

相比较于前一种比价简单的验证content-type的防护方式,一般级别的防护措施换成了验证文件后缀的方式,顺便多说一句,在为了安全性设置一些限制时,使用白名单永远比设置黑名单要安全的多,因为总会有=各种方式绕过黑名单的方式或者是一些针对不同服务器系统或着服务器的特殊解析原理而造成的一些安全隐患。以下是获取文件后缀的代码:
 

$uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1)

通过本语句获取文件名中最后一个“.”后的字符识别上传的文件名的后缀,并将后缀存储在一个变量中。

if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) )

而在if的逻辑判断中,需要上一条语句截取到的文件后缀为“jpg”,“jpeg”或者“png”,切且上传的文件大小不得大于10000b,如果只有这个限制方法的话,可以直接使用burpsuite进行00截断,从而使得在文件后缀验证时通过但是在文件转储的时候忽略掉00之后的内容从而实现后缀欺骗,具体方式如下:

假设网站只能上传图片文件并在后台欧了后缀的限制
此时你要上传一个shell.php的一句话木马
将”shell.php”改为”shell.php 1.png”
使用burpsuite截断代理,拦截数据包
将”shell.php 1.png”发送至decoder模块,从text模式转换为hex编辑模式,找到”shell.php 1.png”中空格对应的hex值“20”,将20改为00
从hex模式恢复为text并将修改过的字符串替换原来报文中的”shell.php 1.png”
发送报文,操作成功后会显示文件上传成功
操作成功后会显示文件上传成功,在php版本小于5.3.4的版本中,当Magic_quote_gpc选项为off时,可以在文件名中使用%00截断,所以可以把上传文件命名a1.php%00.png进行绕过,我们用bp抓包检测一下文件类型。 可以发现文件类型是png成功绕过前端,并且到服务器文件会被解析成php文件,因为00后面的被截断了,服务器不解析。

但是在本例中,00截断的方法不再有效,因为if条件中还有一个getimagesize()函数,此函数会自动识别上传的图片的文件头,长宽,mime类型等信息,因此如果上传的文件不是图片将无法上传。绕过这个限制的方法是制作图片马,我是在win环境下制作的,只需准备一个图片大小较小的jpg或者png格式的图片,打开cmd使用命令:

copy 1.jpg/b+shell.php 2.jpg
1
来合成一张图片马,如果用二进制编辑器打开此文件会发现一句话木马写到了文件的后面,把这样的文件上传时,由于文件头仍然是jpg的文件头,getimagesize()函数也会正确的返回图片的大小和文类型,因此通这种方式可以绕过getimagesize()函数的限制,再结合00截断即可上传木马并在服务器端将文件解析为php脚本,从而正确执行。

但是如果服务器的PHP版本较高,则无法通过此方法进行漏洞的利用,需要结合文件包含漏洞进行利用。

0x03 无解的防护-全方面限制
当然安全只是相对的,没有绝对的安全,一下代码对输入的文件进行了多种方式的审查并进行了重新编码,是目前比较完善了安全防御措施。

源代码 upload_2.php
 

<?php
if( isset( $_POST[ 'Upload' ] ) ) {
    // 检查token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    $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' ];
    $target_path   = 'uploads/';
    $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;
    //判断是否是一张图片
    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 );
        //文件转储
        if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
            $html .= "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
        }
        else {
            $html .= '<pre>Your image was not uploaded.</pre>';
        }
        //删除所有暂时文件
        if( file_exists( $temp_file ) )
            unlink( $temp_file );
    }
    else {
        //无效文件
        $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}
// 添加抗csrf验证
generateSessionToken();
?>

添加了sessionToken,验证会话身份,用于防止csrf攻击
使用md5( uniqid() . $uploaded_name )函数,uniqid()函数是根据当前的时间,生成一个唯一的id,跟大多数随机函数一样,基于时间的随机函数在一定条件下也是可以差生碰撞的,因此本例中采用了md5()函数来保证生成id的唯一性,而且由于md5()函数对上传的文件名进行了重命名,因此无法使用00截断的方式来上传php或者其他恶意脚本文件。
以白名单的方式限制上传的文件后缀
限定上传的文件大小不得超过10000
通过imagecreatefromjpeg()和imagecreatefrompng()函数将上传的图片文件重新写入到一个新的图片文件中,这两个函数会自动将图片中的有害元数据抹除,因此即使黑客上传了一张图片马也会被这个函数过滤成一个纯正的图片。
imagedestroy( $img )将用户上传的源文件删除
unlink( $temp_file )删除过滤过程中产生的任何临时文件
0x04 个人总结
web漏洞种类繁多,利用方法奇葩而有趣,值得研究和学习

学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

$uploaded_size < 100000解释,安全,php,服务器,网络安全

同时每个成长路线对应的板块都有配套的视频提供:

 $uploaded_size < 100000解释,安全,php,服务器,网络安全

 

到了这里,关于PHP文件上传漏洞原理以及防御姿势的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 文件上传漏洞(1), 文件上传绕过原理

    一, 前端校验上传文件 添加 Javascript 代码,然后在 form 表单中 添加 onsubmit=\\\"returb checkFile()\\\" 绕过前端: 1. 在浏览器设置中禁用js 通常不建议使用这种方式, 因为前端js中可能存在很多其他js的功能, 例如ajax请求. 2. 用burpsuite等工具修改请求. 因为前端js对文件类型做了限制, 那么将

    2024年02月08日
    浏览(9)
  • 锐捷NBR路由器fileupload.php任意文件上传漏洞

    锐捷NBR路由器fileupload.php任意文件上传漏洞

    锐捷NBR路由器是锐捷网络科技有限公司推出的一款高性能企业级路由器。NBR是\\\"Next-Generation Broadband Router\\\"的缩写,意为\\\"下一代宽带路由器\\\"。该路由器具有强大的处理能力和丰富的功能,适用于中小型企业、校园网络和数据中心等场景。锐捷 NBR 路由器 存在任意文件上传漏洞,

    2024年02月08日
    浏览(14)
  • 文件上传漏洞-原理篇

    文件上传漏洞-原理篇

    目录 第1章 文件上传漏洞基础 1.1 漏洞概述 1.2 漏洞成因 1.3 漏洞危害 1.4 漏洞利用姿势 第2章 文件上传漏洞检测与绕过 2.1 前端检测和绕过 2.2 服务器端检测和绕过 第3章 文件上传漏洞防御 文件上传是很多站点常用的功能,比如上传图片、视频、文档等,常在评论功能区、头像

    2024年02月10日
    浏览(8)
  • 【网络安全 --- 任意文件上传漏洞靶场闯关 6-15关】任意文件上传漏洞靶场闯关,让你更深入了解文件上传漏洞以及绕过方式方法,思路技巧

    【网络安全 --- 任意文件上传漏洞靶场闯关 6-15关】任意文件上传漏洞靶场闯关,让你更深入了解文件上传漏洞以及绕过方式方法,思路技巧

      首先分享一个自己做的很不错的网路安全笔记,内容详细介绍了许多知识 超详细的网络安全笔记 分享一个非常详细的网络安全笔记,是我学习网安过程中用心写的,可以点开以下链接获取: 超详细的网络安全笔记​编辑https://m.tb.cn/h.5JdFcih?tk=OuVrWRl9vMx%20CZ3457 https://m.tb.cn/

    2024年02月07日
    浏览(13)
  • dedecms后台文件media_add.php任意上传漏洞的解决方法

    dedecms早期版本后台存在大量的富文本编辑器,该控件提供了一些文件上传接口,同时dedecms对上传文件的后缀类型未进行严格的限制,这导致了黑客可以上传WEBSHELL,获取网站后台权限 media_add.php dedecms后台文件任意上传漏洞修复方法,主要是文件/dede/media_add.php或者/你的后台名

    2024年02月03日
    浏览(10)
  • 如何利用文件上传漏洞-以及如何修复它们

    如何利用文件上传漏洞-以及如何修复它们

    𝓲’𝓶 𝓪 𝓵𝓾𝓷𝓪𝓽𝓲𝓬, 𝓱𝓪𝓱𝓪𝓱𝓪𝓱𝓪, 𝓪𝓷𝔂𝔀𝓪𝔂, 𝓲𝓯 𝔂𝓸𝓾 𝓭𝓸𝓷’𝓽 𝔀𝓾𝓷𝓭𝓮𝓻𝓼𝓽𝓪𝓷𝓭, 𝓘 𝓳𝓾𝓼𝓽 𝔀𝓻𝓲𝓽𝓮 𝓲𝓽 𝓬𝓪𝓼𝓾𝓪𝓵𝓵𝔂, 𝓘’𝓶 𝓪 𝓵𝓾𝓷𝓪𝓽𝓲𝓬 当服务器允许用户在不验证

    2024年02月05日
    浏览(7)
  • 世邦通信 SPON IP网络对讲广播系统addscenedata.php任意文件上传漏洞

    世邦通信 SPON IP网络对讲广播系统addscenedata.php任意文件上传漏洞

    产品介绍 世邦通信SPON IP网络对讲广播系统采用领先的IPAudio™技术,将音频信号以数据包形式在局域网和广域网上进行传送,是一套纯数字传输系统。 漏洞描述 spon IP网络对讲广播系统存在任意文件上传漏洞,攻击者可以通过构造特殊请求包上传恶意后门文件,从而获取服务器

    2024年01月16日
    浏览(13)
  • web安全-文件上传漏洞-图片马制作-相关php函数讲解-upload靶场通关详细教学(3)

    web安全-文件上传漏洞-图片马制作-相关php函数讲解-upload靶场通关详细教学(3)

    制作图片马有两种方法,一种是文本方式打开,末尾粘贴一句话木马,令一种是使用命令进行合成。 方法1 首先准备好一个图片(这里是1.png)。 将一个图片以文本格式打开(这里用的Notepad++,以记事本方式打开修改也能连接成功,不过修改后图片无法正常显示了)。 后面粘

    2024年02月06日
    浏览(11)
  • [网络安全] Windows Server 设置文件屏蔽防止黑客利用漏洞上传特定类型的非法文件(.asp .aspx .jsp .php)

    [网络安全] Windows Server 设置文件屏蔽防止黑客利用漏洞上传特定类型的非法文件(.asp .aspx .jsp .php)

    [网络安全] Windows Server 设置文件屏蔽防止黑客利用文件上传漏洞上传特定类型的非法文件(.asp .aspx .jsp .php) 我在负责网站运维期间,遇到过一次黑客利用公司网站内使用的开源文件上传工具漏洞上传非法文件(可执行脚本) 我是通过设置文件屏蔽来防止此类事件的再次发生。

    2024年02月12日
    浏览(13)
  • threehit漏洞复现以及防御

    threehit漏洞复现以及防御

    说白了跟sql-liql靶场二次注入一样,也是一个转义函数而这次是,入库的时候不转义,出库的时候会转义导致这个漏洞出现 开始测试: 这是我注册完test刚登录的情况   找注入点更新数据的update,很容易找到在age段 这次我注册的时候用户还是test,但是年龄我对后面进行了省

    2024年02月21日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包