PHP Taint – 一个用来检测XSS/SQL/Shell注入漏洞的扩展

 作者: Laruence( 鸟哥  )

之前, 小顿和我提过一个想法, 就是从PHP语言层面去分析,找出一些可能的注入漏洞代码. 当时我一来没时间, 而来也确实不知道从何处下手..

直到上周的时候, 我看到了这个RFC: RFC:Taint.

但是这个RFC的问题在于, 它需要为PHP打Patch, 修改了PHP本身的数据结构, 这对于以后维护, 升级PHP来说, 很不方便, 也会有一些隐患.

虽然这样, 但这个RFC却给了我一个启发, 于是我就完成了这样的一个扩展:Taint Extension

这个扩展使用起来, 很简单(目前只支持5.2.6 ~ 5.3.10,以及7.0以上):

下载源代码以后, 编译, 安装. 然后在php.ini中要开启这个扩展(建议不要在生产环境开启这个扩展):

  1. extension=taint.so
  2. taint.enable=1

启用这个扩展以后, 如果在一些关键函数(或者语句: echo, print, system, exec, 等等), 或者输出的地方*直接*(没有经过转义, 安全过滤处理)

使用了来自$_GET, $_POST或者$_COOKIE的数据, 则Taint就会提示你:

<?php
$a = $_GET['a'];

$file_name = '/tmp' . $a;
$output = "Welcome, {$a} !!!";
$var = "output";
$sql = "Select * from " . $a;
$sql .= "ooxx";

echo $output;
//Warning: main(): Attempt to echo a string which might be tainted in xxx.php on line x

print $$var;
//Warning: main(): Attempt to print a string which might be tainted in xxx.php on line x

include($file_name);
//Warning: include() [function.include]: File path contains data that might be tainted in xxx.php on x

mysql_query($sql);
//Warning: mysql_query() [function.mysql-query]: First argument contains data that might be tainted in xxx.php on line x

?>

能够进行识别的XSS漏洞就是直接输出了一段外部输入的内容,即以下形式的代码

<?php
$id = $_GET['id'];
//...
?>
<a><?php echo $id;?></a>

如果输入的内容包含html标签,就可以向页面中注入一段自定义的内容,虽然这段内容不能够进入数据库,但攻击者可以制造一个这种连接,

并引导让用户点击后就可以读取到一些用户信息之类的内容(对于这类问题可以将用户关键的Cookie信息设置为Http Only)或让用户自动进行一些行为(如给好友发带有这种连接的消息进行传播),

在安装了Taint的情况下,如果执行以上代码就有相应的警告提示如下

 Warning: main() [echo]: Attempt to echo a string that might be tainted in /srv/http/index.php on line 4

而如果做了相关的过滤处理则就不会有相应的警告了,例如使用strip_tags或是intval等方法。

<?php
$id = strip_tags($_GET['id']);
//...
?>
<a><?php echo $id;?></a>

###附录

A. 验证的字符串
所有来自GET,GET,_POST, $_COOKIE的变量, 都被认为是Tainted String

B. taint检测的函数/语句列表, 当这些函数使用tainted string参数的时候, taint会给出警告:

1. 输出函数/语句系列
echo
print
printf
file_put_contents
2. 文件系统函数
fopen
opendir
basename
dirname
file
pathinfo
3. 数据库系列函数/方法
mysql_query
mysqli_query
sqlite_query
sqlite_single_query
oci_parse
Mysqli::query
SqliteDataBase::query
SqliteDataBase::SingleQuery
PDO::query
PDO::prepare
4. 命令行系列
system
exec
proc_open
passthru
shell_exec
5. 语法结构
eval
include(_once)
require(_once)
C. 消除tainted信息的函数, 调用这些函数以后, tainted string就会变成合法的string:

escapeshellcmd
htmlspecialchars
escapeshellcmd
addcslashes
addslashes
mysqli_escape_string
mysql_real_escape_string
mysql_escape_string
sqlite_escape_string
PDO::quote
Mysqli::escape_string
Mysql::real_escape_string
D. 调用中保持tainted信息的函数/语句, 调用这些函数/语句时, 如果输入是tainted string, 则输出也为tainted string:

=
.
"{$var}
.=
strval
explode
implode
sprintf
vsprintf
trim
rtrim
ltrim

php 扩展地址: http://pecl.php.net/package/taint

注意:默认Taint不会被开启,需要在PHP配置中增加以下配置,并且注意不要在正式的环境中使用Taint,其会一定程度影响代码的执行效率

原文地址:https://www.cnblogs.com/wjq310/p/8868033.html