[关闭]
@Dukebf 2017-07-11T16:02:18.000000Z 字数 3401 阅读 1507

PHP审计之常见的危险函数及特殊函数

代码审计 危险函数


目录

PHP代码执行函数

eval()

mixed eval(string $code) :把字符串$code作为PHP代码执行。

很多webshell都基于eval来执行,如一句话木马: <?php @eval($_POST['cmd']);?>

assert()

bool assert(mixed $assertion [,string $descrition]): 检查一个断言是否为FALSE.(把字符串$assertion作为PHP代码执行)。

preg_replace()

mixed preg_replace(mixed $pattern,mixed $replacement,mixed $subject[, int $limit = -1 [,int &$count]]) 其中 \e 修正符使preg_replace()将replacement参赛当做PHP代码执行。

preg_replace(/test/e",$_GET["h"],"just test");
如果提交 ?h=phpinfo(), phpinfo()将会被执行。

create_function()

string create_function(string $args,string $code): 创建一个匿名函数,并返回独一无二的函数名。

  1. $newfunc = create_function('$v','return system($v);');

其中,$newfunc('whoami'); 就相当于system('whoami');

call_user_func() && call_user_func_array()

mixed call_user_func(callable $callback [,mixed $parameter [, mixed $...]]): 第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

mixed call_user_func_array(callable $callback,array $param_arr): 把第一个参数作为回电函数调用,把参数数组作为回调函数的参数传入。

包含函数

包含函数一共有四个: require,include,require_once,include_once

include $file 中,如果变量 $file 可控,则就可以包含任意文件。
此外,根据不同的配置环境,可以包含不同的文件:远程文件和本地文件。
包含函数还可以通过 支持的协议和封装协议 以及 过滤器读取任意文件内容。
例子,如
利用php流filter读取任意文件

  1. include($_GET('file');
  2. // ?file=php://filter/convert.base64-encode/resource=index.php

上面的代码中,就通过filter读取index.php的内容,并将内容编码成base64再输出。
相关的CTF题目也可以参考: 2016xctf一道ctf题目

命令执行函数

常见的命令执行函数有:
* exec() -- 执行一个外部程序
* passthru() -- 执行外部程序并显示原始输出
* proc_exec() -- 通过shell环境执行命令,并且将完整的输出以字符串的方法返回
* system() -- 执行外部程序,并且显示输出
* popen() -- 通过popen()的参数传递一条命令,并对popen()所打开的文件进行执行。

文件操作函数

常见的任意文件读取,写入,删除往往是下面几个函数受到了控制.
* copy() -- 拷贝文件
* file_get_contents() -- 将整个文件读入一个字符串
* file_put_contents() -- 将一个字符串写入文件
* file() -- 将整个文件读入一个数组中
* fopen() -- 打开文件或者URL
* move_uploaded_file() -- 将上传的文件移动到新位置
* readfile() -- 读取文件
* rename() --重命名文件或者目录
* rmdir() -- 删除目录
* unlink() & delete() -- 删除文件

特殊函数

信息泄露 phpfinfo()

bool phpinfo() 这个就不多说,它的输出包含了PHP编译选项,启用的扩展,PHP版本,服务器信息和环境变量,PHP环境变量。操作系统版本信息,path变量,配置选项和本地值和主值,HTTP头和PHP授权信息。

软连接-读取文件内容

bool symlink(string $target,string $link): 对于已有的target建立一个名为link的符号连接
string readlink(string $path):返回符号连接的内容

环境变量

string getenv(string $varname): 获取环境变量的值
bool putenv(string $setting): 添加setting到服务器环境变量中。但环境变量近存活于当前请求会话。会话结束,环境会恢复到初始状态。

加载扩展

bool dl(string $library): 载入指定参数library的PHP扩展。

配置相关

string ini_get(string $var): 成功时返回配置选项的值

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

void ini_restore(string $var): 恢复指定的配置选项到默认值

数字判断

bool is_numeric(mixed $var)
如果 var 是数字和数字字符串则返回TRUE,否则返回FALSE.
但是当仅用 is_numeri 判断时,可能导致插入16进制的字符串到数据库,进而导致sql二次注入。比如有这么一个判断:

  1. <?php
  2. var_dump(is_numeric($_GET['v']));
  3. if (is_numeric($_GET['v'])){
  4. mysql.... //MySQL执行插入或更新语句,将 v 插入到数据库中
  5. }
  6. ?>

v = 123 时,会发现它被判断为数字
v = 0x123时, 它依然判断为数字

防御,使用 intval() 函数来过滤判断数字:
v = 0x123 时,它会将 'x' 及其以后的都视为字符,并删除,,输出 0

变量覆盖

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

例子

  1. <?php
  2. $str = "first=value&arr[]=foo+bar&arr[]=baz";
  3. parse_str($str);
  4. var_dump(isset($first)); // TRUE
  5. echo $first;
  6. echo $arr[0]; // foo bar
  7. echo $arr[1]; // baz
  8. ?>

从中可以看到,str 字符串中 first 等已经被解析为变量。

其他特殊函数
array glob(string $pattern[,int $flags=0]) : 查找与pattern 匹配的文件路径

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

array get_defined_constants(): 返回所有当前已定义的常量名和值。包括define()函数所创建的,也包含所有扩展创建的。

array get_defined_functions()
返回所有已经定义的函数列表

array get_included_files(void):返回所有被include,include_once,require,require_once的文件名。1

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注