php代码安全审计:易出现脆弱点的函数

php代码审计中如果不用工具,自己手工检查的话,比较容易出现脆弱点的函数。

代码执行函数

eval() 函数

把字符串 code 作为PHP代码执行。由于eval函数是非常危险的,所以不要允许传入任何由用户 提供的、未经完整验证过的数据。

assert() 函数

检查一个断言是否为 FALSE。(把传入进的字符串作为PHP代码执行),检查一个断言是否为 FALSE。assert() 会检查指定的 assertion 并在结果为 FALSE 时采取适当的行动。
如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。因为大多数杀毒软件把 eval 列入黑名单了,所以用 assert 来替代eval 来执行具体操作的。

preg_replace() 函数

preg_replace 执行一个正则表达式的搜索和替换。e 修饰符使 preg_replace() 将 replacement 参数当作 PHP 代码。

假如:pre_replace(“/test/e”,$_GET[“h”],”just test”);如果我们提交 ?h=phpinfo(),/e就会将h参数当做PHP代码,phpinfo()将会被执行。

create_function()函数

create_function — 创建一个匿名函数。

call_user_func()函数

call_user_func — 把第一个参数作为回调函数调用。

call_user_func_array()函数

call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数,跟call_user_func()函数类似,不过是将参数放在了一个数组中。

包含函数&命令执行函数

包含文件函数

require、include、require_once、include_once

包含函数 一共有四个,主要作用为包含并运行指定文件。

require 和 include 几乎完全一样,除了处理失败的方式不同之外。简单来说就是require包含出错时会产生错误并停止运行,而include包含出错时只会发出警告,但程序会继续运行。二者后面跟上’_once’的意思是只包含一次,以避免函数重定义,变量重新赋值等问题。

利用:比如包含include $file;
在变量 $file 可控的情况下,我们就可以包含任意文件,从而达到 getshell 的目的。
另外,在不同的配置环境下,可以包含不同的文件。
因此又分为远程文件包含和本地文件包含。
包含函数也能够读取任意文件内容,这就需要用到【支持的协议和封装协议】和【过滤器】。

本地文件包含漏洞利用技巧

①包含用户上传的文件 (我们上传的一句话木马等等)

②包含data:// 或 php://input 等伪协议

③包含敏感文件

④包含日志文件      ( 通过构造语句让服务器报错并将一句话随报错信息写入日志;找到日志文件路径,包含此文件;用菜刀连接;拿下网站的Webshell )

远程包含的话,需要条件:就是中的allow_url_include和allow_url_fopen都要为on才行。条件满足的话,就可以包含url类的文件。

命令执行函数

exec() — 执行一个外部程序

passthru() — 执行外部程序并且显示原始输出

proc_open() — 执行一个命令,并且打开用来输入/输出的文件指针。

shell_exec() — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。

system() — 执行外部程序,并且显示输出

popen() — 通过 popen() 的参数传递一条命令,并对 popen() 所打开的文件进行执行

利用的话就是当执行的命令参数可以控制的话,就可以执行系统命令。

文件操作函数&无参数获取信息函数

文件操作函数

copy — 拷贝文件

file_get_contents — 将整个文件读入一个字符串
file_put_contents — 将一个字符串写入文件
file — 把整个文件读入一个数组中
fopen — 打开文件或者 URL

move_uploaded_file — 将上传的文件移动到新位置
readfile — 输出文件
rename — 重命名一个文件或目录
rmdir — 删除目录
unlink & delete — 删除文件

任意文件读取、写入、删除往往是上面几个函数受到了控制(当然还有其他的函数)。
不同的函数在不同的场景有不同的作用和不同的利用手法。
读取:可以读取配置等文件,拿到key
写入:可以写入shell代码相关的内容
删除:可以删除.lock文件而可以重新安装覆盖

无参数获取信息函数

array get_defined_vars ( void )
返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。

array get_defined_constants ([ bool $categorize = false ] )
返回当前所有已定义的常量名和值。这包含 define() 函数所创建的,也包含了所有扩展所创建的。

array get_defined_functions ( void )
返回一个包含所有已定义函数列表的多维数组

array get_included_files ( void )
返回所有被 include、 include_once、 require 和 require_once 的文件名。

注意:前面几个函数返回的都是数组。

其他函数

phpinfo()函数

输出 PHP 当前状态的大量信息,包含了 PHP 编译选项、启用的扩展、PHP 版本、服务器信息和环境变量(如果编译为一个模块的话)、PHP环境变量、操作系统版本信息、path 变量、配置选项的本地值和主值、HTTP 头和PHP授权信息(License)。

phpinfo() 同时是个很有价值的、包含所有 EGPCS(Environment, GET, POST, Cookie, Server) 数据的调试工具。

软连接-读取文件内容

bool symlink ( string $target , string $link )
symlink() 对于已有的 target 建立一个名为 link 的符号连接。

readlink — 返回符号连接指向的目标
string readlink ( string $path )
readlink() 和同名的 C 函数做同样的事,返回符号连接的内容。

环境变量

string getenv ( string $varname )
获取一个环境变量的值。

bool putenv ( string $setting )
添加 setting 到服务器环境变量。环境变量仅存活于当前请求期间。在请求结束时环境会恢复到初始状态。

加载扩展

bool dl ( string $library )
运行时载入一个 PHP 扩展,载入指定参数 library 的 PHP 扩展。

配置相关

string ini_set ( string $varname , string $newvalue )

成功时返回配置选项的值。

string ini_alter ( string $varname , string $newvalue )
设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。

void ini_restore ( string $varname )
恢复指定的配置选项到它的原始值。

数字判断

bool is_numeric ( mixed $var )
如果 var 是数字和数字字符串则返回 TRUE,否则返回 FALSE。
仅用is_numeric判断而不用intval转换就有可能插入16进制的字符串到数据库,进而可能导致sql二次注入。

数组相关

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
在 haystack 中搜索 needle,如果没有设置 strict 则使用宽松的比较。
该函数有一个特性,比较之前会进行自动类型转换。
$a = '1abc';
in_array($a,array(1,2,3))的返回值会是真。

变量覆盖

void parse_str ( string $str [, array &$arr ] )
如果 str 是 URL 传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域。

int extract ( array &$var_array [, int $extract_type = EXTR_OVERWRITE [, string $prefix = NULL ]] )
本函数用来将变量从数组中导入到当前的符号表中。检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突。

bool mb_parse_str ( string $encoded_string [, array &$result ] )
解析 GET/POST/COOKIE 数据并设置全局变量。由于 PHP 不提供原始 POST/COOKIE 数据,目前它仅能够用于 GET 数据。它解析了 URL 编码过的数据,检测其编码,并转换编码为内部编码,然后设置其值为 array 的 result 或者全局变量。

bool import_request_variables ( string $types [, string $prefix ] )
将 GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局变量,那么此函数就很有用。

THE END