浅谈OS命令注入漏洞(Shell注入漏洞)

一、什么是OS命令注入?

1. 基本概念

    OS(Operating system)命令注入(也称为 Shell 注入)是一个 Web 安全漏洞,允许攻击者在运行应用程序的服务器上执行任意操作系统 (OS) 命令,这会破坏应用程序及其所有数据。

2. Shell的概念:

    Shell翻译过来就是” 壳”, 操作系统的外壳。Shell接收用户指令, 调用相应的应用程序, 是一种用C语言编写的程序设计语言, 同时也是“为使用者提供操作界面”的命令解析器。

3. Shell的执行过程:

    当用户输入Shell命令时,Shell负责将命令解释给内核,内核去运行,最后将处理完的结果反馈给用户;所以说Shell既是一种程序设计语言,又是命令解释程序。
而我们常用的CMD和Windows Power Shell是两种不同的Windows命令行工具, 其中PowerShell要更强大, 是微软发布的目前最新的一代命令行和脚本语言一体化工具。 

二、利用OS命令注入漏洞能做什么?

1. 攻击示意图

Shell注入攻击示意图
        Curl是一种支持各种协议的传输工具, 经常在Linux系统中使用;
        通过curl命令调用受害网站的的backdoor.sh脚本文件;这样就可以控制受害者主机, 访问我不该访问的服务, 获取我不该获取的数据,连接我不该连接的网络,篡改我不该篡改的权限。

2. DDOS攻击:

    比如说DDOS攻击: 我可以通过Shell注入控制你的电脑, 这台电脑就是我们常说的肉鸡/傀儡机, 我控制了你的电脑, 就可以用你的电脑, 你的IP对目标网站发起请求, 进行DDOS攻击;我控制几百台几千台不断的发起请求, 这就会影响目标服务器的正常访问。(Powershell -Command Invoke-WebRequest -Uri https://wwww.baidu.com -Method POST -Body @{username=‘admin’; password='abc’})

3. 上传非法脚本执行Shell命令

    结合文件上传漏洞:继承Web服务器程序权限,执行系统命令,控制整个服务器。
    结合路径遍历漏洞:访问文件存储路径, 清空所有数据文件。

4. 反弹shell

    假设现在我们有两台主机一台主机A、一台主机B,我们想通过A主机控制B主机。那么如果用正向Shell,其实就是在A主机上输入B主机的连接地址用户名和密码,连接到B,连接成功之后,我们就可以在A主机通过命令控制B主机了, 通过Shell注入可以绕过输入用户密码的步骤。
    但如果现在主机A是公网, 主机B是内网, 而由于防火墙等限制,主机A无法访问到主机B,这时候怎么办?这时候我们就可以利用反弹Shell攻击技术,在公网主机上先开启一个监听端口,然后再通过Shell注入让内网主机去连接公网主机的这个端口,连接成功之后,公网主机这边就能通过命令控制内网主机了。
    问:既然已经可以Shell注入进内网主机了,为什么还要让内网主机去连接控制端主机开启的端口,再由控制端主机发命令去控制内网主机?
    答:便捷;扩大权限;持久化(利用注入点可能会产生系统日志,可以防止后续注入点被修复无法再控制的情况;目标端IP动态变化) 

三、如何检测OS命令注入漏洞?

1. 检查代码

public void shellInjectionSimple(String command) {
    try {
        // 用于调用外部可执行程序或系统命令,这允许攻击者执行任意的外部命令。
        Process process = Runtime.getRuntime().exec(command);

        BufferedReader reader = new BufferedReader(new         InputStreamReader(process.getInputStream()));
        String line;

        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        reader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2. Shell盲注

与SQL盲注相同,SQL盲注都有哪些方式:
· SQL语句执行结果True/False,触发不同的响应;
· SQL语句注入服务器是否报错;
· 延迟执行,判断执行时间的长短;
· OAST带外技术盲注; 

四、如何防止OS命令注入?

1. 永远不要从应用层代码中调用操作系统命令 。
2. 参数化执行

public void shellInjectionParametrize(String[] args) {
    try {
        String command = ""; // Hard code

        // ProcessBuilder类是Java中用于执行外部命令的工具类,它提供了一种安全的方式来执行命令
        ProcessBuilder builder = new ProcessBuilder(command);
        List parameters = Arrays.asList(args);
        builder.command().addAll(parameters); // 使用command()方法将其添加到ProcessBuilder对象中
        Process process = builder.start(); // 调用start()方法来启动进程

        BufferdReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); // 使用BufferedReader读取输出流中的数据
        String line;

        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }


        int exitCode = process.waitFor();
        System.out.println("Exit code: " + exitCode);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3. 如果不可避免地使用用户提供的输入调用操作系统命令,则必须执行强输入验证:
    a. 添加白名单验证;
    b. 控制输入字符(仅包含字母数字字符,不包含其他语法/空格/特殊字符等)
4. 不建议仅通过转义来控制输入,容易出错,并且很容易被熟练的攻击者绕过。

    对参数进行Base64编码,Base64编码可以作为一种简单的安全措施来保护不受信任的参数,只能保证攻击者无法在传输过程中直接执行。

posted @ 2023-07-13 19:37  丶Overfly  阅读(274)  评论(0编辑  收藏  举报