php代码审计-文件上传

文件上传漏洞

在现代的web网站中,文件上传功是一种常见的功能。比如一些博客网站,允许用户上传,图片,视频,头像,等许多其他类型的文件。但是向用户接受的文件越多,所面临的信息安全风险也就越大。如果web网站存在文件上传漏洞,那么恶意用户就可以利用文件上传漏洞将可执行上传到服务器中,最后获取到网站的权限。

一个漏洞百出的文件上传代码

<?php
$file=$_FILES['tx'];
if(is_uploaded_file($file["tmp_name"]))
{
    if(move_uploaded_file($file["tmp_name"],"file/".$file['name']))
    {echo "成功";}
    else
    {echo "失败";}
}
else
{
    echo "上传失败";
}

这段代码提供了文件上传的功能,但是他很危险没有任何安全防护,被上传的文件也按原名保存在目录里。

用if函数判断是否有文件上传,有的话以原名复制到file的目录下。

js前端检测的文件上传代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script type="text/javascript">
    function wenjscgl(sc){
        var wenjian= sc.value;
        var hz = wenjian.toLowerCase().substr(wenjian.lastIndexOf("."));
        if(hz!=".jpg")
        {
            alert("请选择jpg格式的照片上传");
            sc.outerHTML=sc.outerHTML;
        }
    }
</script>
<form action="dck.php" method="POST" enctype="multipart/form-data">
    上传文件
        <input type='file' name="tx" id="file" οnchange="wenjscgl(this)">
    <input type="submit" name="tj" value="提交">
</form>
<?php
$file=$_FILES['tx'];
if(isset($_POST['tj']))
if(is_uploaded_file($file["tmp_name"]))
{
    if(move_uploaded_file($file["tmp_name"],"file/".$file['name']))
    {echo "成功";}
    else
    {echo "失败";}
}
else
{
    echo "请选择文件上传";
}?>
</body>
</html>

这是一段html+javascript+php的代码,javascript负责前端检测,拒绝不是.jpg的文件上传,javascript代码为获取文件上传的后缀并对后缀名进行判断如果不是jpg弹窗,是jpg就执行后面的php语句。php语句

判断是否有提交文件,有文件上传就用move_uploaded_file函数用本名上传至file目录下。

js检测绕过

由于上面的代码只做了前端的过滤,并没有在后端用php过滤,所以我们只要绕过前端就可以上传jpg格式的文件了。这里使用burpsuite来实施绕过。

把要上传的文件先改成jpg格式,通过前端验证以后用burp抓包再修改回可执行的格式。

1634721297_616fde113fe58e2619137.png!small?1634721296430

1634721545_616fdf09c5c65ee446975.png!small?1634721544848

可以看到上传成功。

文件后缀绕过

我们在网站上提交文件时,有些web网站会通过文件后缀过滤的方法来阻止恶意文件上传的事件。那么有过滤就有绕过

文件后缀源代码分析

header('Content-type:text/html;charset=utf-8');
$file=$_FILES['tx'];
if(isset($_POST['tj'])){
if(is_uploaded_file($file["tmp_name"]))
{
    $qwe=pathinfo($_FILES["tx"]["name"]);
   $kzm=$qwe['extension'];
   if(strtolower($kzm)=='php'){
       echo "<script>alert('不允许的文件上传')</script>";
   }else{
       move_uploaded_file($_FILES['tx']['tmp_name'],"file/".$_FILES['tx']['name']);
       echo "<script>alert('文件上传成功')</script>";
   }


}
else
{
    echo "请选择文件上传";
}}?>

老规矩上来先分析一下源码,用$_FILES获取提交的文件,传入变量$file中,接着用if控制获取到提交才执行下面的语句,再用if判断提交中是否有文件。用pathinfo截取文件的后缀名,用strtolower函数将获取的后缀名转为小写。判断$kzm字段中也就是我们上传的文件后缀名是否是.php,如果是则弹出前端代码不“允许的文件上传”,反之 move_uploaded_file函数以原文件名上传至f同级目录file中。

需要注意的是虽然警告语句是用前端代码弹出的,但是我们对文件的判定是后端php执行的,所以上文提到的前端过滤代码在这里并不适用.

文件后缀绕过分析

文件后缀绕过的姿势也有非常多。

上面代码使用黑名单只过滤了.php文件的上传。

1,例如在httpd.conf中, 如果配置有如下代码,则能够解析php和phtm|文件。
AddType application/x-httpd php.php.phtml
所以,可以上传一个后缀为phtml的WebShell, 在Apache的解析顺序中,是从右到左开始解析文件后缀的,如果最右侧的扩展名不可识别,就继续往左判断,直到遇到可以解析的文件后缀为止,所以如果上传的文件名类似1.php.xxxx,因为后缀xxxx不可以解析,所以向左解析后缀php。

2,apache不仅会解析.php的后缀名还会解析如php1,php2,php3之类的后缀。我们可以上传这样的文件绕过。

文件类型绕过

通过文件类型过滤,如果服务端是通过content-type的值来判断文件类型而不是通过后缀名。

文件类型源代码分析

<?php
header('Content-type:text/html;charset=utf-8');
$file=$_FILES['tx'];

if(is_uploaded_file($file['tmp_name'])){
    $qwe = $_FILES["tx"]["type"];
    if ($qwe == 'application/octet-stream') {
        echo "<script>alert('不允许的文件上传')</script>";
    } else {
        move_uploaded_file($_FILES['tx']['tmp_name'], "file/" . $_FILES['tx']['name']);
        echo "<script>alert('文件上传成功')</script>";
    }


}

?>

代码中判定是否有文件提交,有文件提交就用qwe变量获取文件的content-type然后判断content-type值是否为application/octet-stream,application/octet-stream是php文件的类型。接着把文件上传至服务器file目录下。

文件类型绕过

content-type值虽然看不见,但是我们使用burpsuite是可以修改的。使用burpsuite抓取文件上传数据包。

1634917695_6172dd3f58014d8a21ef8.png!small?1634917695491

修改content-type值为jpeg的类型 image/jpeg

1634917763_6172dd83b21f46d603c65.png!small?1634917763796

上传成功,其实可以修改成任意的字符串因为只过滤了php类型的,并没有对上传的类型做其他限制,只要不是php类型的就可以了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值