跳转至

代码执行

代码执行-概述

「任意代码执行(Arbitrary Code Execution,ACE)」 是指攻击者在目标计算机或目标进程中运行攻击者选择的任何命令或代码的能力,这是一个广泛的概念,它涵盖了任何类型的代码运行过程,不仅包括系统层面的脚本或程序,也包括应用程序内部的函数或方法调用。

在此基础上我们将通过网络触发任意代码执行的能力通常称为 远程代码执行 「远程代码执行(RCE,Remote Code Execution,RCE)」

「命令执行(Command Execution)」 通常指的是在操作系统层面上执行预定义的指令或脚本。这些命令最终的指向通常是系统命令,如Windows中的CMD命令或Linux中的Shell命令,这在语言中可以体现为一些特定的函数或者方法调用,如PHP中的shell_exec()函数或Python中的os.system()函数。

「代码执行(Code Execution)」 同我们最开始说到的任意代码执行,在语言中可以体现为一些函数或者方法调用,如PHP中的eval()函数或Python中的exec()函数。

虽然在很多教学场景,命令执行 和 代码执行 经常被用同一个缩写 RCE (Remote Code/Command Execution) 来指代,但显而易见的是,代码执行是更为广泛的概念。

在本章节的内容,我们将以 PHP 为例,从审计的角度来讲解代码执行,在阅读前,请完成前置知识 - PHP基础。

代码执行-成因

在某些特殊场景,我们可能需要让我们的脚本去调用一段特定的模板代码,甚至是一些外部程序。

尤其是在Web层面的局限的情况,需要突破代码层面到系统命令去执行特定的命令或者二进制文件,这时我们可能会使用类似 PHP 中 shell_exec() 函数来调用系统命令,而碰巧的是,命令所带的参数是由用户输入的,如果我们没有对输入进行检查,那么通过特殊的拼接构造,就能做到一些非预期的执行结果,这就导致了代码执行。

在 CTF 考题中,代码执行通常以功能性题目出现,比如最著名的 ping 命令的 "存活检测":

<?php
    $ip = $_GET['ip'];
    $result = shell_exec("ping -c 4 $ip");
    echo "<pre>$result</pre>";
?>

在这个例子中,我们的输入会被当做参数传递给 ping 命令,而大多数的终端都是支持连续执行多个命令的,这里假设题目在 Linux 的容器中运行,那么我们可以通过 ; 来执行多个命令,比如 127.0.0.1;ls,这样就能够执行 ping 命令和 ls 命令。

代码执行-函数

在 Web 应用程序中,我们通过脚本去执行特定代码或者系统命令,本质上是一种函数调用,比如我们看下面两个函数例子:

  • eval() 函数: 将字符串作为PHP代码执行。 —— 像这类函数都属于代码执行的函数。
    eval("echo 'Hello CTF';");
    - - - - -
    <?php
        $code = 'echo "Hello CTF";';
        eval($code);
    ?>
    
  • system() 函数: 执行外部程序并且显示输出。 —— 对比代码执行函数,这一类函数是指定用于外部程序调用(也就是命令执行)的代码函数。
    system('ls');
    - - - - -
    <?php
        $cmd = 'ls';
        system($cmd);
    ?>
    

其他函数见下图,具体用法可参考 PHP 官方文档。

代码执行-语法准则

在题目可能遇到的代码执行的情况,根据遇到的语言类型,运行平台,无非三种:代码层面上的代码执行,这与涉及的语言语法有关;系统层面上的命令执行,这取决于代码运行的平台 —— 是WIndows还是Linux,是 CMD 还是 Bash / Dash ...

代码执行

比如这段代码$result = eval("Template_code $parameters"); ,显而易见的PHP代码对吧,如果我们想要利用这个漏洞,就要从PHP的语法出发去构造$parameters

同理如果是其他语言类似的代码,如 Java,$result = Runtime.getRuntime().exec("Template_code $parameters"); ,这时便需要从Java的语法出发去构造$parameters

这类漏洞本质上是考察对目标语言的熟悉程度,以及对语言语法和特性的理解。

Linux / Windows

接着看这段代码$result = shell_exec("Template_command $parameters"); ,在这里我们调用的是外部程序,这便与编程语言无关,而是取决于代码运行的平台。

评论