PHP中的命令执行

前言

在 PHP 中, exec()system()popen()passthru()proc_open()pcntl_exec()shell_exec(),还有反引号 ``包裹的内容,都可以用来执行系统命令。

如果执行的命令参数是用户可控的,那么就会造成命令执行漏洞。

下面是常见的函数描述:

  • system()

    输出并返回最后一行shell结果。

  • exec()

    不输出结果,返回最后一行shell结果,所有结果可以保存到一个返回的数组里面。

  • passthru()

    只调用命令,把命令的运行结果原样地直接输出到标准输出设备上。

  • popen()、proc_open()

    不会直接返回执行结果,而是返回一个文件指针。

  • 反引号

    调用 shell_exec() 函数


各平台的漏洞利用

在实际场景中,要利用命令执行漏洞,通常需要借助管道符,拼接到正常的命令参数中来实现。

各个平台支持的管道符都有所不同,下面是 WindowsLinux 支持的管道符。

Windows

  • |

    直接执行后面的语句。

    ping | whoami

  • ||

    如果前面的语句执行出错,则执行后面的语句。

    p || whoami

  • \&

    如果前面的语句为假,直接执行后面的语句。

    为真,也会执行后面的语句。

    ping 127.0.0.1 & whoami

  • \&\&

    如果前面的语句为假直接出错,不会执行后面的。前面的语句必须为真。

    ping 127.0.0.1 && whoami

Linux

  • \;

    执行完前面的语句,再执行后面的。

    ping 127.0.0.1;whoami

  • |

    直接执行后面的语句。

    ping | whoami

  • ||

    如果前面的语句执行出错,则执行后面的语句。

    p || whoami

  • \&

    如果前面的语句为假,直接执行后面的语句。

    为真,也会执行后面的语句。

    ping 127.0.0.1 & whoami

  • \&\&

    如果前面的语句为假直接出错,不会执行后面的。前面的语句必须为真。

    ping 127.0.0.1 && whoami


防御方法

PHP 内置了两个函数,escapeshellarg()escapeshellcmd()可以防止命令执行。

  1. escapeshellarg()

    把字符串转码为可以在 shell 命令里使用的参数。

  2. escapeshellcmd()

    shell 元字符转义。

    对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec()system() 函数,或者 执行操作符 之前进行转义。

    反斜线(\)会在以下字符之前插入: &#;`|*?~<>^()[]{}$\, \x0A 和 \xFF。 ‘ 和 “ 仅在不配对儿的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。

文章目录
  1. 1. 前言
  2. 2. 各平台的漏洞利用
    1. 2.1. Windows
    2. 2.2. Linux
  3. 3. 防御方法
|