@Dukebf
2017-07-12T00:02:18.000000Z
字数 3401
阅读 2496
代码审计
危险函数
mixed eval(string $code)
:把字符串$code作为PHP代码执行。
很多webshell都基于eval来执行,如一句话木马: <?php @eval($_POST['cmd']);?>
bool assert(mixed $assertion [,string $descrition])
: 检查一个断言是否为FALSE.(把字符串$assertion作为PHP代码执行)。
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()将会被执行。
string create_function(string $args,string $code)
: 创建一个匿名函数,并返回独一无二的函数名。
$newfunc = create_function('$v','return system($v);');
其中,$newfunc('whoami');
就相当于system('whoami');
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读取任意文件
include($_GET('file');
// ?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() -- 删除文件
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二次注入。比如有这么一个判断:
<?php
var_dump(is_numeric($_GET['v']));
if (is_numeric($_GET['v'])){
mysql.... //MySQL执行插入或更新语句,将 v 插入到数据库中
}
?>
v = 123 时,会发现它被判断为数字
v = 0x123时, 它依然判断为数字
防御,使用 intval() 函数来过滤判断数字:
v = 0x123 时,它会将 'x' 及其以后的都视为字符,并删除,,输出 0
void parse_str(string [,array &$arr])
: 如果str 是URL传递入的查询字符串,则将它解析为变量并设置到当前作用域。
例子
<?php
$str = "first=value&arr[]=foo+bar&arr[]=baz";
parse_str($str);
var_dump(isset($first)); // TRUE
echo $first;
echo $arr[0]; // foo bar
echo $arr[1]; // baz
?>
从中可以看到,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