概况

在pakachu的靶场里,有 exec “ping” 的远程命令执行演练。 但需要注意的是: 我们的演练环境是搭建在docker系统里面的,docker相对来说比较精简,可能是没有ping命令存在的。

在 docker里运行

apt install iputils-ping

image.png
完成ping命令的安装。

image.png
测试通过。

漏洞初探

来到页面

http://192.168.182.147/vul/rce/rce_ping.php

image.png
页面要求我们输入一个ip地址,然后代码会调用系统的ping命令来执行,最后反馈结果:
image.png

开脑洞

页面提供了ping命令的数据输入,也就是我们有了一个与系统交换数据的机会。在php的页面里,能够直接调用系统底仓执行命令的函数有哪些呢?

php命令执行函数

代码执行与命令执行执行命令的函数高危函数:system()、exec()、shell_exec()、passthru()、pctnl_exec()、popen()、proc_open()

  • system()—执行shell命令也就是向dos发送一条指令
  • shell_exec()—通过shell环境执行命令,并且将完整的输出以字符串的方式返回
  • exec()—执行外部程序
  • passthru()—执行外部程序并且显示原始输出

所以,我们推测,php后端使用的函数可能是shell_exec()或者passthru() 。

深挖shell_exec()和passthru()

image.png
shell_exec的返回值是:命令执行的输出
image.png

推测

推测码农在写代码的时候,是把外部传入的ip地址直接组合到了代码的内部。以shell_exec来举例子,可能的伪代码形式是:

$ping_data=$_POST[“ip”]; $ret = shell_exec(“ping “. $ping_data); print_r($ret);

投射到系统层,可以类似成:

ping 114.114.114.114

我们可以控制的变量为$ping_data,则是否可以通过修改ping 的数据来构造一个我想要执行的命令,并拿到返回结果。

组合命令

在命令行可以一次执行多个命令,有以下几种方法:
每个命令之间用;隔开
说明:各命令的执行结果,不会影响其它命令的执行。换句话说,各个命令都会执行,但不保证每个命令都执行成功。
命令: ll;ps
image.png
每个命令之间用&&隔开
说明:若前面的命令执行成功,才会去执行后面的命令。这样可以保证所有的命令执行完毕后,执行过程都是成功的。
命令:cd /etc/no_this_dir && ps 和 cd /usr/bin && ps
image.png
image.png
2图对比可以看到&&的执行效果
每个命令之间用||或者|隔开
说明:||是或者的意思,只有前面的命令执行失败后才去执行下一条命令,直到执行成功一条命令为止。

管道符号 | 可以将一个命令的输出导向另一个命令的输入,从而让两个(或者更多命令)像流水线一样连续工作,不断地处理文本流。

命令: cd /etc/no_this_dir || ps 和 cd /etc/no_this_dir | ps
image.png
image.png

| 管道命令有时候只是为了取得并行执行的效果,没有真正的想过要将一个命令的输出导向到另外一个命令的输入。此乃“不折手段”image.png

符号 说明
A;B A 不论正确与否都会执行 B 命令
A&B A 后台运行,A 和 B 同时执行
A&&B A 执行成功时候才会执行 B 命令
A|B A 执行的输出结果,作为 B 命令的参数,A 不论正确与否都会执行 B 命令
A||B A 执行失败后才会执行 B 命令

漏洞实战

通过3中组合形式来构造漏洞。

组合1

114.114.114.114 -c 1; cat /etc/passwd
image.png

组合2

127.0.0.1 -c 1 && cat /etc/passwd
image.png

组合3

1..1.1.1 || cat /etc/passwd
image.png
1..1.1.1 | cat /etc/passwd
image.png

讨论

windows下和linux下命令行 dos环境和bash环境在命令格式上的区别。
linux下面的ping命令,如果只给ip地址,在正确的情况下,它会一直ping下去。
同学们还能想到哪些?

string system ( string $command [, int &$return_var ] ) string exec ( string $command [, array &$output [, int &$return_var ]] ) void passthru ( string $command [, int &$return_var ] )

注意的是:这三个函数在默认的情况下,都是被禁止了的,如果要使用这几个函数,就要先修改php的配置文件php.ini,查找关键字disable_functions,将这一项中的这几个函数名删除掉,然后注意重启apache。