PHP中eval函数的代码注入问题分析与解惑
PHP代码注入漏洞分析与问题解答
免责声明
本文仅为学习PHP代码注入的示例,绝非生产环境使用代码。我完全清楚这并非良好的编码实践。
存在漏洞的PHP脚本
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Sample Script</title> </head> <body> <h1>Sample page</h1> <p>Now doing the maths. Please enter a formula to compute. Example: 1+1.</p> <form method="get"> <p>Formula: <input type="text" name="maths" /></p> <p><input type="submit" value="compute" /></p> </form> <? if (( isset($_REQUEST["maths"])) && ($_REQUEST["maths"] != "") ) { echo "<p>The result is: "; eval("echo (".$_REQUEST["maths"].");"); echo "</p>"; } ?> </body> </html>
注入尝试与疑问
该脚本存在PHP代码注入漏洞,通过试错找到可生效的注入语句:
$a='1');phpinfo();echo($a
但对原理不理解,原本认为可行的注入语句");phpinfo();echo("无效,因为phpinfo()被视为字符串的一部分无法被eval执行,尝试转义引号也无效果。
技术问题
- 针对该脚本,正确的代码注入方式是什么?
- 为何
$a='1');phpinfo();echo($a这条注入语句能够生效?
问题解答
1. 针对该脚本的正确代码注入方式
核心是要打破原有eval内的代码结构,让自定义代码被当作独立PHP语句执行,而非作为字符串或表达式的一部分。
原脚本中eval执行的固定模板是:echo (你的输入内容);。构造输入时需要满足三个关键点:
- 闭合前面的
echo (结构,结束当前echo语句 - 插入要执行的自定义代码(如
phpinfo()、system()等) - 处理原代码末尾的
),避免语法报错
常见的有效注入写法包括:
- 你试出的
$a='1');phpinfo();echo($a - 更简洁的写法:
1);phpinfo();//—— 用//注释掉后续的),PHP会忽略注释内容,不会触发语法错误 - 命令执行类写法:
1);system('whoami');echo(—— 闭合前一个echo,执行系统命令,再补echo(承接后面的)
2. $a='1');phpinfo();echo($a生效的原理
把输入内容代入eval的模板后,拼接出的完整执行代码是:
echo ($a='1');phpinfo();echo($a);
逐段拆解逻辑:
echo ($a='1'):这是合法PHP操作——先将'1'赋值给变量$a,echo会输出赋值结果(即1),同时刚好闭合了原代码中echo (的左括号。;phpinfo();:分号结束前面的echo语句,后续的phpinfo()成为独立的PHP语句,会被直接执行,这就是我们要实现的注入效果。echo($a);:原代码末尾还有一个),如果不处理会变成phpinfo();),触发语法错误。而我们添加的echo($a)刚好能接住这个),形成合法语句echo($a);,避免报错。
而你之前尝试的");phpinfo();echo("无效的原因是:
拼接后代码为:
echo (");phpinfo();echo(");
此时整个输入内容被包裹在echo (和)中,成为一个完整字符串");phpinfo();echo(",PHP只会原样输出该字符串,不会执行其中的phpinfo(),因为它只是字符串的一部分,并非独立执行的代码。
内容的提问来源于stack exchange,提问作者Fang
相关产品推荐
相关产品推荐

