PHP代码审计,安全漏洞挖掘简要记录
1 全局变量
PHP中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中
都可用。在函数或方法中无需执行 global $variable; 就可以访问它们。
超全局变量都如下:
$GLOBALS
$GLOBALS 超级全局变量数组可以认为是超级全局变量的超集,包含全局作用域
内的所有变量。$GLOBALS这种全局变量用于在PHP脚本中的任意位置访问全局变
量(从函数或方法中均可),PHP在名为$GLOBALS[index] 的数组中存储了所有
全局变量。变量的名字就是数组的键。执行下面的代码可以查看$GLOBALS中所有
的变量。
print ‘ <pre>’ ;
print_r ($GLOBALS);
print ‘ </pre>’ ;
$_SERVER
$_SERVER 这种超全局变量保存关于报头、路径和脚本位置的信息。比如:
$_SERVER[‘PHP_SELF’] 返回当前执行脚本的文件名。
$_SERVER[‘GATEWAY_INTERFACE’] 返回服务器使用的 CGI 规范的版本。
$_SERVER[‘SERVER_ADDR’] 返回当前运行脚本所在的服务器的 IP 地址。
$_SERVER[‘SERVER_NAME’] 返回当前运行脚本所在的服务器的主机名(比如 www.xxx.com)。
$_SERVER[‘SERVER_SOFTWARE’] 返回服务器标识字符串(比如 Apache/2.2.24)。
$_SERVER[‘SERVER_PROTOCOL’] 返回请求页面时通信协议的名称和版本(例如,“HTTP/1.0”)。
$_SERVER[‘REQUEST_METHOD’] 返回访问页面使用的请求方法(例如 POST)。
$_GET
$_GET 也可用于收集提交 HTML 表单 (method=”get”) 之后的表单数据。
$_GET 也可以收集 URL 中的发送的数据。
$_POST
$_POST 广泛用于收集提交 method=”post” 的 HTML 表单后的表单数据。
$_POST 也常用于传递变量。
$_FILES
$_FILES超级全局变量包含通过POST方法向服务器上传的数据的有关信息。
$_COOKIE
$_COOKIE超级全局变量存储了通过HTTP cookie传递到脚本的信息。
$_SESSION
$_SESSION 超级全局变量包含与所有会话有关的信息。注册会话信息能为
你提供便利,这样就能在整个网站中引用这些会话信息,而无需通过GET
或POST显示的传递数据。
$_REQUEST
$_REQUEST 用于收集 HTML 表单提交的数据。
$_ENV
$_ENV超级全局变量提供PHP解析所在服务器环境的有关信息。此数组中的变
量包括:
$_ENV[ ‘HOSTNAME’ ] 服务器的主机名
$_ENV[ ‘SHELL’ ] 系统 shell
regeister_globals=off
register_globals 是php中的一个控制选项,可以设置成off或者on ,默认为off
决定是否将 EGPCS(Environment,GET,POST,Cookie,Server)变量注册为全局变量。
如果 register_globals打开的话, 客户端提交的数据中含有GLOBALS变量名,就会覆盖服务器上的
$GLOBALS变量.所以这段代码, 就是判断, 如果提交的数据中有GLOBALS变量名, 就终止程序。
由此引起的安全问题成为PHP的“自动全局变量漏洞”,所以我们要坚决把register_globals关掉。
并且使用 $_GET, $_POST, $_COOKIE 而非 $_REQUEST 。
gpc[$_GET,$_POST,$_COOKIE]
magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:
post、get、cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程
序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误
2 危险函数
extract()
extract(array,extract_rules,prefix)
extract函数用来将一个数字分解成多个变量直接使用。PHP extract() 函数从
数组中把变量导入到当前的符号表中。对于数组中的每个元素,键名用于变量
名,键值用于变量值。第二个参数type用于指定当某个变量已经存在,而数组
中又有同名元素时,extract() 函数如何对待这样的冲突。EXTR_OVERWRITE 默认。
如果有冲突,则覆盖已有的变量。
如何防止这种漏洞,可以在使用的时候加上参数EXTR_SKIP,这个参数表示如果有
冲突,不覆盖已有的变量或者还有EXTR_PREFIX_SAME – 如果有冲突,在变量名
前加上前缀 prefix。
parse_str()
parse_str() 函数把查询字符串解析到变量中,主要用于页面之间传值,参数。
它在注册之前不进行验证当前变量是否已经存在,因此将会出现变量覆盖漏洞。
import_request_variables()
import_request_variables 函数可以在register_global = off 时,把 GET/POST/
Cookie变量导入全局作用域中。不管当前变量是否已经存在,因此可能出现变量
覆盖漏洞。
stripslashes()
stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
函数可用于清理从数据库中或者从 HTML 表单中取回的数据。
iconv()/mb_convert_encoding()
这两个函数都能够完成各种字符集间的转换,是php编程中不可缺少的基础函数库。
编码转换之后,如果还有没有过滤的字符可能会存在注入,执行,泄露等漏洞。
magic_quotes_gpc=on
PHP中一个特殊的函数魔术函数,它在引用的过程中只有在传递$_GET,$_POST,
$_COOKIE时才会发生作用。可以不对输入和输出数据库的字符串数据作
addslashes()和stripslashes()的操作,数据也会正常显示。
如果此时你对输入的数据作了addslashes()处理,
那么在输出的时候就必须使用stripslashes()去掉多余的反斜杠。
magic_quotes_gpc=off
必须使用addslashes()对输入数据进行处理,但并不需要使用stripslashes()
格式化输出.因为addslashes函数并未将反斜杠一起写入数据库,只是帮助
MySQL完成了sql语句的执行。
eval()
val() 函数把字符串按照 PHP 代码来计算。
该字符串必须是合法的 PHP 代码,且必须以分号结尾。
如果没有在代码字符串中调用 return 语句,则返回 NULL。
如果代码中存在解析错误,则 eval() 函数返回 false。
preg_replace()
该函数代码执行,需要参数/e函数主要用于处理字符串,因此出现最多的漏洞就是
在字符串处理中。参数过滤不严容易出现漏洞。
assert()
函数本身就是把字符串参数当做代码动态解析执行。参数过滤不严容易出现漏洞。
call_user_func()
该函数的功能是调用函数,多用于框架里面调用函数。所以小的程序
出现的几率小,大框架程序出现的多一些。参数过滤不严容易出现漏洞。
call_user_func_array()
函数本身就是把字符串参数当做代码动态解析执行。参数过滤不严容易出现漏洞。
create_function()
在php中,函数create_function主要用来创建匿名函数,有时候匿名函数可以发挥它
的作用。如果没有严格对参数传递进行过滤,攻击者可以构造特殊字符串传递给
create_function()执行任意命令。
session_destroy()
删除当前用户对应的session文件以及释放sessionid,内存中的$_SESSION变量内容
依然保留。session的生命周期从用户连上服务器后开始,在用户关掉浏览器或是
注销时用户session_destroy函数删除session数据时结束。主要预防session劫持漏洞。
rand() vs mt_rand()
rand() 函数默认使用 libc随机数发生器。在某些平台下(例如 Windows)RAND_MAX只有 32768。
如果需要的范围大于 32768,那么指定 min 和 max 参数就可以生成大于 RAND_MAX 的数了,或者
考虑用 mt_rand() 来替代它。mt_rand()函数是非正式用来替换它的。该函数用了Mersenne Twister
中已知的特性作为随机数发生器,mt_rand() 可以产生随机数值的平均速度比 libc 提供的 rand() 快四倍。
unset()
PHP unset()函数是用来销毁变量的,但很多时候,这个函数只把变量给销毁了,
内存中存放的该变量的值仍然没有销毁,也就是没能达到我们想要的释放内存
的效果。可以用$变量=null 的方法来释放其内存 或者 将两个变量都 unset();
3 数据检查
命令参数
对于用户可能存在的命令执行代码或者函数进行参数检查,严格过滤。
配置文件
检查php环境搭建时候的相关配置文件是否正确和安全,清理删除。
数据索引
数据范围是否越界,代码安全编写校验。
环境变量
php环境下面的大量全局变量进行检测。
临时文件
php搭建后得配置文件和系统记录的关键文件,防止泄露。
4 工具检查
1.CodeScan
http://www.codescan.com
这个比较老牌了。市面上流出的版本好像就是1.6和1.9的crack,
商业软件。不过GUI界面操作起来很方便。这里也不多说什么,
主要是Include的提示设置,装过软件自己看看就知道了。
2.RIPS
http://rips-scanner.sourceforge.net/
PHP写的,需要环境,直接解压到wwwroot就好了。不适合扫描整个文件夹项目,或者要
修改PHP配置,把代码执行超时的时间设置大一点。总体来说还是很不错。
3.PHPXref
http://phpxref.com
严格的说PHPxref也是做开发的好帮手,它能将某一个程序(如Wordpress)中所有的函数、
变量、常量等分类记录,生成一个HTML网页列表,你可以轻松地在这个列表中找到某个
函数在什么位置被定义,在什么位置被引用。所以说非常适合大型项目。
同时还是最主要的,It’s free.
4. RATS
http://www.fortify.com/security-resources/rats.jsp
工具采用的就是词法分析技术。通过词法分析的工作原理,会发现该技术存在较为
严重的缺陷。第一,它只能检测较少的已知问题,仅仅对 API 中的一些潜在的危险
函数进行检查,并不检测其他的安全问题。第二,它仅仅是对己知问题函数进行匹配,
没有对这些问题进行进一步的确认。
5. xssdetect
http://tel1.hackol.com/2010/hackol.com-4910-XSSDetectSetup.rar
一款微软公司为开发人员提供针对跨站脚本攻击的静态分析工具SSDetect是
精简版的.NET代码分析工具,原本供微软内部人员寻找应用软件的安全漏洞
之用,大概是受开源思想影响,现在已经可以免费下载了。
6. yasca
http://www.scovetta.com/yasca.html
用来寻找安全漏洞,在程序的源代码中检测代码质量、性能以及一致性的软件。
它集成了其它开源项目,其中包括FindBugs,PMD的,JLint,JavaScript的林特
PHPLint,Cppcheck,并扫描某些文件类型,以及自定义扫描书面的Yasca。这是
一个命令行工具,与报告中生成的HTML,CSV格式,XML的,的SQLite和其他格式。