something about Pikachu - RCE

pikachu

pikachu => 备份地址

RCE(remote command/code execute)

概述

REC(远程命令执行漏洞),一般由于应用系统从设计上需要给用户提供指定的远程命令操作的接口。 比如常见的路由器,防火墙,入侵检测等设备的web管理界面。
一般给用户提供一个ping 操作的web界面,用户输入目标IP,提交后,系统后台执行ping命令, 如果没有对目标IP进行严格的安全控制,有可能会造成RCE漏洞

例如:

1
2
# ping 命令执行失败,执行`ifconfig`
ping 127.0.0.a || ifconfig

exec “ping”

  • 手动注入

    PHPshell_exec(cmd)函数,将调用系统shell执行cmd
    因此对参数进行构造,使得执行恶意命令。

    1
    2
    3
    # %7C => |
    # ipaddress=127.0.1.a || ipconfig
    ipaddress=127.0.1.a+%7C%7C+ipconfig&submit=ping

exec “eval”

  • 手动注入

    PHPeval(statement)函数,将statement解析为php语句进行执行。这 非常危险 。 因此构造参数,执行恶意命令。

    1
    echo shell_exec('ipconfig');

    将会执行eval("echo shell_exec('ipconfig');"),因此可以执行系统命令。


something about DVWA - command injection

DVWA

DVWA => 备份地址

Command Injection(命令注入)

Low

  • 手动注入

    命令参数尾部手动拼接&,&&,|,||,;等,与其它命令。

    • 命令连接符

      1. &

        使得命令在后台运行。

        1
        2
        # 在后台更新软件包索引
        apt update &
      2. ;

        按顺序执行分隔的每条命令。

        1
        2
        # 先更新索引 再更新软件包
        apt update ; apt upgrade
      3. &&

        短路与
        前一条命令执行成功时,执行后一条命令;
        前一条命令执行失败,不会执行后一条命令。

        1
        2
        # 更新软件包索引,成功后更新软件包
        apt update && apt upgrade
      4. ||

        短路或
        前一条命令执行失败时,执行后一条命令;
        前一条命令执行成功,不会执行后一条命令。

        1
        2
        # 更新软件包索引失败时,打印信息
        apt update || echo "update failure"
      5. !

        排除命令执行对象。

        1
        2
        # 删除当前目录下,除html文件的所有文件
        rm -r !(*.html)
      6. &&||

        &&||搭配可以形成if-else选择分支。

        1
        2
        # 先更新软件包索引,成功就更新软件包,失败就打印信息
        apt update && apt upgrade || echo "update failure"
      7. |

        管道运算符,前一条命令的输出作为后一条命令的输入。

        1
        2
        # 列出当前文件夹下所有文件,并筛选文件名包含`example`的内容打印
        ls | grep example
      8. {}

        合并多条命令,使得分隔在一起的命令中,后面的命令依赖于前面的命令。

        1
        2
        # ping web服务器,连接不上,就重启网络服务并打印信息
        ping www.example.com || {service networking restart ; echo "start networking ..."}
      9. ()

        给命令分组,用以改变优先级。

        1
        2
        # 倘若`echo "1"`执行失败,`echo "3" && echo "4"`依然会执行
        (echo "1" && echo "2") || (echo "3" && echo "4")
      10. \

        用以将长命令换行。

        1
        2
        3
        # 打印"hello world"
        echo "hello \
        world"

      Windows下命令连接符不同意义:

      1. &&

        短路与
        前一条命令执行成功时,执行后一条命令;
        前一条命令执行失败,不会执行后一条命令。

      2. &

        真与
        无论情况如何,被分隔的命令都会执行。

      3. ||

        短路或
        前一条命令执行失败时,执行后一条命令;
        前一条命令执行成功,不会执行后一条命令。

      4. |

        真或
        无论情况如何,被分隔的命令都会被执行。

      5. ;

        Windows 不支持 ;分隔符。

  • 源码分析

    • 直接从request中获取参数

      1
      2
      // Get input
      $target = $_REQUEST[ 'ip' ];
    • 直接将参数以字符串的方式拼接入command

      使用shell_exec函数调用函数。

      1
      2
      // *nix
      $cmd = shell_exec( 'ping -c 4 ' . $target );

Medium

  • 手动注入

    不使用黑名单字符,使用其它命令连接符

  • 源码分析

    • 直接从request中获取参数

      Low级别相同。

    • 设置 黑名单

      1
      2
      3
      4
      5
      // Set blacklist
      $substitutions = array(
      '&&' => '',
      ';' => '',
      );
    • 过滤黑名单字符

      使用str_replace函数过滤字符。

      1
      2
      // Remove any of the charactars in the array (blacklist).
      $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
    • 将过滤后的命令以字符串的方式拼接入command

      1
      2
      // *nix
      $cmd = shell_exec( 'ping -c 4 ' . $target );

High

  • 手动注入

    使用|进行注入,注意|后不跟随空格。

  • 源码分析

    • 直接从request中获取参数,过滤首尾空白字符

      1
      2
      // Get input
      $target = trim($_REQUEST[ 'ip' ]);
    • 设置黑名单

      黑名单 不完善

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      // 注意'| ',有 `空格`,因此不完善
      // Set blacklist
      $substitutions = array(
      '&' => '',
      ';' => '',
      '| ' => '',
      '-' => '',
      '$' => '',
      '(' => '',
      ')' => '',
      '`' => '',
      '||' => '',
      );
    • 过滤黑名单字符

      Medium相同。

    • 将过滤后的命令以字符串的方式拼接入command

      Medium相同。

Impossible

针对命令注入:

  1. 首先在获取参数时使用stripslashes函数去除参数中的反斜杠(\)

  2. 其次针对特定命令参数分解判断

    ping ip.ip.ip.ip中针对ip地址,分别判断。

    1
    2
    3
    4
    5
    6
    7
    // Split the IP into 4 octects
    $octet = explode( ".", $target );

    // Check IF each octet is an integer
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
    // ...
    }