【PHP系统命令执行】eval、passthru、exec、shell_exec、system各大命令的区别

本文最后更新于:2021年9月6日晚上7点53分

总结

按道理总结是在最后的,不过为了日后翻看方便,还是将总结放在了前面。

eval system exec shell_exec 反引号 passthru
执行的内容 PHP代码 系统命令 系统命令 系统命令 系统命令 系统命令
是否需要echo回显 不确定

eval

对于eval函数,官方手册的介绍如下:

image-20210906183330542

说白了就是在eval函数中,传入的必须是PHP代码,例如phpinfo

1
2
3
<?php
eval("phpinfo();");
?>

当然除了这种正常的姿势,也可以在eval函数中继续套娃。

1
2
3
<?php
eval("eval(phpinfo());");
?>

甚至还可以再套一层:

1
2
3
<?php
eval("eval(eval(phpinfo()));");
?>

这三种方式都是可以显示出phpinfo的页面的。

需要注意的是,eval其实应该称作为代码执行,而并非命令执行。因为eval所需的参数是PHP代码的字符串。

system

首先还是看官方文档。

image-20210906185228517

可以看到system函数在执行过后会直接将结果输出,并且还会刷新web服务器的输出缓存(没测试出来),相当于除了命令执行,system还自带了echo的特性。

1
2
3
<?php
system("ping baidu.com");
?>

image-20210906194336289

其中system是有返回值的,返回的是命令执行的最后一行。

1
2
3
<?php
echo system("ping baidu.com");
?>

多出了红色的那一行

image-20210906194520588

在PHP官方文档中有说web服务器会刷新输出缓存,我个人以为是会实时刷新,但是当我利用system函数执行ping命令的时候,设置-c参数为100,即ping100次,但是web服务器并不像我预期的那样ping出结果返回一次,而是整个页面卡住,直到100次都ping完了才返回结果。不知道是什么原因= =、

exec

同样的还是先看exec命令的官方介绍:

image-20210906191605524

其中exec最简单的用法就是配合echo命令输出执行结果:

1
2
3
<?php
echo exec("whoami");
?>

除此之外,exec也可以将结果进行存储,也可以记录命令执行后的返回状态

1
2
3
4
5
6
<?php
$cmd = $_GET["cmd"];
exec($cmd,$res,$res_code);
print_r($res);
print_r($res_code);
?>

得到的结果如下:

image-20210906192803613

其中0就是命令执行返回的代码

shell_exec

老规矩,先看官方文档。

image-20210906192916435

shell_exec函数和system、exec一样,执行的都是系统命令,与system命令不一样的是,shell_exec可以直接返回命令执行的结果,但是是以函数的返回值返回的,并不会直接将结果输出在屏幕上。

1
2
3
<?php
echo shell_exec("whoami");
?>

其实就是一个低配版的exec,之所以是低配,是因为exec有进程检测值返回,而shell_exec没有。

不过我们可以在官方文档上看到,该函数和执行操作符是一样的。

执行操作符(反引号)

同样还是先看官方文档:

image-20210906193451162

这个反引号最简单的用法如下:

1
2
3
<?php
echo `dir`;
?>

image-20210906193637060

passthru

首先还是看一下passthru的官方文档介绍。

image-20210906185013475

其中passthru最简单的用法如下:

1
2
3
<?php
passthru("whoami");
?>

其实,passthru除了返回值与system不同之外,其余功能都与system差不多,可以说是system的替代品吧,当做CTF赛题的时候,如果system被过滤了,可以考虑使用passthru函数代替。多一种选择……