php扩展,eval钩子如何挂载?如何阻止eval函数?
发布于 作者:苏南大叔 来源:程序如此灵动~最近一直在致力于phpsrc
内核的编译工作,其实主要目的是调试安装实验一下几个相关扩展。其中一个扩展是:evalhook
。顾名思义,就是挂载eval
函数的钩子。那么,这款钩子扩展的效果如何呢?是不是真的能够阻止eval
函数呢?
大家好,这里是苏南大叔的“程序如此灵动”博客,这里记录苏南大叔和计算机代码的故事。本文描述php
扩展如何拦截eval
函数。在实际应用中,经常需要禁用eval
函数的执行。那么,在以前的文章里面,苏南大叔使用了suhosin
这一款扩展。本文中,苏南大叔实验的这款php
扩展名叫evalhook
。本文测试环境:centos@7.7.1908
,php@7.4.28
,evalhook
。
源码下载
这款evalhook
代码的下载地址是:
evalhook
代码依然非常简单,逻辑几分钟内就可以看完。原本是基于php5
写的,不过苏南大叔试了一下,php7
下依然可以完美运行。以前苏南大叔测试过另外一款韩国人出品的扩展suhosin
,功能比较类似。详情请参考:
扩展编译
扩展编译的话,中规中矩。唯一需要注意的是:如果第二次编译的话,一定记得make clean
。否则就可能会看到这样的类似报错信息:
PHP Warning: PHP Startup: evalhook: Unable to initialize module
Module compiled with module API=20121212
PHP compiled with module API=20190902
These options need to match in Unknown on line 0
扩展的编译,是和php
自身有较大关系的,两者必须保持一致。所以,在扩展的编译过程中,需要指定phpize
和php-cofig
文件的位置。对于苏南大叔的php@7
来说,位置是:
/home/php7/bin/phpize
/home/php7/bin/php-config
命令参考如下:
make clean
/home/php7/bin/phpize
./configure --with-php-config=/home/php7/bin/php-config
make
make install
这里不用关心evelhook.so
文件的位置,只要正确的配置了php-config
的位置,扩展就会自动出现在对应的目录里面。如果没有,那么就必然是php-config
参数配置错误。make install
都是自动复制文件到对应扩展路径的。
效果测试
正常情况下来说,是需要修改php.ini
来加载扩展的。但是,苏南大叔非常懒得去配置php.ini
,这里使用了php
的-d
参数来加载evalhook.so
。
这里准备了一个eval.php
文件,内部就放了个eval
函数的简单调用范例。
$string = "beautiful";
$time = "winter";
$str = 'This is a $string $time morning!';
eval("\$str = \"$str\";");
echo $str;
命令执行:
php -d extension=evalhook.so eval.php
这里需要注意php
的路径问题,使用绝对路径是最好的选择。比如:
/home/php7/bin/php -d extension=evalhook.so /home/www/eval.php
因为这个evalhook
扩展的效果是:询问你是否执行eval
,然后输入y
才会继续执行,否则异常退出。所以,必须在命令行下面才能看出效果来,普通的网页情况下,只能陷入无限等待。
Do you want to allow execution? [y/N]
y
This is a beautiful winter morning!
Do you want to allow execution? [y/N]
n
Fatal error: evalhook: script abort due to disallowed eval() in /home/www/eval.php on line 8
关键源码
这里面的关键源码如下:
static zend_op_array *evalhook_compile_string(zval *source_string, char *filename TSRMLS_DC)
{
int c, len, yes;
char *copy;
/* Ignore non string eval() */
if (Z_TYPE_P(source_string) != IS_STRING) {
return orig_compile_string(source_string, filename TSRMLS_CC);
}
len = Z_STRLEN_P(source_string);
copy = estrndup(Z_STRVAL_P(source_string), len);
if (len > strlen(copy)) {
for (c=0; c<len; c++) if (copy[c] == 0) copy[c] == '?';
}
printf("Script tries to evaluate the following string.\n");
printf("----\n");
printf("%s\n", copy);
printf("----\nDo you want to allow execution? [y/N]\n");
yes = 0;
while (1) {
c = getchar();
if (c == '\n') break;
if (c == 'y' || c == 'Y') {
yes = 1;
}
}
if (yes) {
return orig_compile_string(source_string, filename TSRMLS_CC);
}
zend_error(E_ERROR, "evalhook: script abort due to disallowed eval()");
}
稍稍改动一下,就可以做到无条件禁止eval
函数的执行。对吧?
参考文献
- https://newsn.net/say/ctf-thinkcmf-eval.html
- https://newsn.net/say/ctf-thinkphp-eval.html
- https://newsn.net/say/php-disable-eval.html
总结
对于黑客来说,eval
是执行木马的关键性函数。而对于php
代码解密来说,这个eval
也是个关键性的函数。所以,仔细研究一下,无论是攻还是防,都是非常重大的功能了。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。