# SSH劫持

SSH 是一个可以用于远程访问网络设备的网络协议，广泛运用于 Linux 主机，并且如今 SSH 在 Windows 主机上的使用也越来越广泛。对于我们网络安全人士，直观地概括就是 SSH 会话能给予我们**完全交互式的 Shell**。SSH 还可以与 FTP 服务集成，以加强文件安全性。因为 SSH 能访问主机的特性，也被一些**集中式管理工具**集成，以对受管理的主机进行**命令执行**、**分发 IT 任务**等，

SSH 不仅支持**密码登陆**，还支持**密钥登陆**。如果使用密钥认证的话，需要用户通过 **ssh-keygen** 命令先生成一对**私钥与公钥**。从 IT 管理员的角度来看，应当尽可能**禁用密码认证**，只允许密钥认证。尽管基于密钥的认证更加安全，但如果密钥相关的重要文件被**窃取**或者**攥改**了，也会导致主机被入侵。对于攻击者，这可以帮助我们实现横向移动。因为如今 Windows 也支持 SSH 服务，针对 SSH 的成功攻击不仅可以让我们入侵更多的 Linux 主机，也可以让我们拿下 Windows 主机以及实现对特权用户的模仿。

### **SSH 重要文件**

##### **id\_rsa**

id \_rsa 是用户的 SSH 私钥，私钥文件应该被保护好，只有所有者用户才允许拥有读写权限。因为对于攻击者而言，这是最有吸引力的了，SSH 私钥可以授予我们访问**任何信任该密钥的主机** (私钥配套的公钥在目标主机的 **authorized\_keys** 中)，在横向移动方面尤其有效。我们不仅可以在入侵了一台配置有 SSH 服务的主机后**生成或搜集各个用户的 SSH 私钥**以实现**持久化访问**，如果我们发现了可能是用于**连接其他主机的私钥**，那么我们便可以连接到其他主机。这在开发与生产环境是比较常见的，因为员工可能需要通过 SSH 连接到多台主机上作业，因此索性在用户目录下保存了多个主机的 SSH 私钥，这样的图省事带来的是多个主机一并被入侵。

默认情况下，私钥文件存储为 **~/.ssh/id\_rsa** 目录中，需要通过 **ssh-keygen** 命令生成或者覆盖现有的，用户还可以指定 Passphrase 来保护密钥，但对于贪图方便的用户，可能就一路回车跳过了这个环节。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/kGB8X81Dfrt2b0As-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/kGB8X81Dfrt2b0As-image.png)

而对于设置了 Passphrase 的私钥，在使用私钥进行认证的时候，我们需要输入私钥的 Passphrase 方可认证。我们可以对其进行离线字典破解恢复出 Passphrase。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/fDWNO9usTi4fWZwS-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/fDWNO9usTi4fWZwS-image.png)

使用 ssh2john 将私钥的 Passphrase 提取出来成哈希格式

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/GqdILpS4JvAa1eJJ-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/GqdILpS4JvAa1eJJ-image.png)

再使用 john 来字典破解该哈希，得到 Passphrase 为 **dev01**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/hoISN3PvGuAQp5Zr-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/hoISN3PvGuAQp5Zr-image.png)

##### **id\_rsa.pub 与 authorized\_keys**

id\_rsa.pub 为 id\_rsa 所对应的公钥，位置为 **~/.ssh/id\_rsa.pub**，可以自由分发。当用户尝试连接到远程系统时，系统使用此公钥加密**质询**消息，如果能成功使用私钥解密该消息，即证明用户拥有相应的私钥，那么将获得访问权限。

authorized\_keys 存在于 **~/.ssh/authorized\_keys**，包含允许对此帐户进行身份验证的用户的公钥列表。 当客户端连接到服务器时，服务器会检查此文件以查看是否列出了客户端提供的公钥。 如果是，并且如果客户端可以证明它拥有相应的私钥（如上所述），则允许客户端登录。

**公钥认证**，即将用户的公钥添加到目标主机的 authorized\_keys 中。例如，用户 Alice 持有一 VPS，为了能实现免密码 SSH 登陆，Alice 将自己在个人用主机上的 SSH 公钥添加到 VPS 上一用户的 authorized\_keys 中。如图所示，主机 ts 为我的个人 VPS，在该文件中有 3 个公钥，前 2 个为我其他个人主机。我将这些设备上的 SSH 公钥添加在这个文件中，就可以在这 2 个设备上以 root 身份访问 ts 了。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/YMSw4M9Sck3XeSxG-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/YMSw4M9Sck3XeSxG-image.png)

**私钥认证**，在 id\_rsa 部分说过了，私钥以凭证的方式被用于向 SSH 服务器认证，带来的问题就是如果私钥被攻击者窃取了，那么私钥可以访问到的主机都会沦陷。如下图所示，我们看到在 dev01 上，dev01 用户的公钥也存在于 authorized\_keys 中，这样的话，持有 dev01 私钥的用户，当然也包括了窃取了私钥的攻击者，可以通过私钥向 dev01 的 SSH 服务器认证。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/FuLf1UYxHw0QA8pk-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/FuLf1UYxHw0QA8pk-image.png)

回顾该图的上一张图，第 3 个公钥是 dev01 的，什么意思呢？我在 ts 上的 authorized\_keys 中添加了 dev01 的公钥，那么持有 dev01 私钥的用户可以以 root 身份访问 ts 这台主机了。因此，私钥的窃取可能导致多台主机的沦陷，这取决于有多少台主机信任该密钥。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/o8JalXaNmkZsLueV-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/o8JalXaNmkZsLueV-image.png)

##### **known\_hosts**

known\_hosts 文件位于 **~/.ssh/known\_hosts**，保留着客户端曾经连接过的所有远程主机的密钥列表。 该文件用于验证用户是否正在连接到期望的服务器，如果尝试连接的远程服务器的密钥与存储在 known\_hosts 文件中的密钥不匹配，SSH 将警告用户目标服务器的身份已更改。作为攻击者，我们可以查看该文件来判断该用户的连接历史，该用户可能对这些连接过的主机具有访问权，是我们横向移动的目标。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/JfVnnEIxzkZy4X1p-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/JfVnnEIxzkZy4X1p-image.png)

总之，我们来总结一下针对 SSH 密钥的枚举步骤：  
1：查看所有用户的私钥，无论是本地用户的私钥，还是可以访问其他主机的。私钥可能会被改名，因为需要配合内容判断。  
2：检查私钥是否有 Passphrase，如果有，尝试破解出 Passphrase。  
3：查看 authorized\_keys 文件，判断哪些用户/主机可以连接到当前主机。从后利用角度，我们也可以将自己的 SSH 公钥添加到该文件末尾，实现持久化访问。  
4：查看 **known\_hosts**，配合**命令历史**判断该用户连接过哪些主机。不过 known\_hosts 中的内容可能被**哈希**过。  
5：尝试连接其他主机

### **SSH Control Master**

SSH 有一个特性叫 Control Master，可以通过单个网络连接共享多个会话。这意味着只要用户建立起第一个 SSH 会话，那么后续的 SSH 连接不再需要密码，从而实现尾随在第一个会话身后。以靶场里的 **Dev01** 为例，**账户 dev01** 正在以 **med-deal\\october** 用户身份通过 SSH 访问 **Srv02**，而我们已经入侵了 Dev01，因此我们可以**尾随**这个 SSH 会话实现无须密码便能移动到 Srv02。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/cxYlK7sLw9zqtQFo-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/cxYlK7sLw9zqtQFo-image.png)

利用方式与条件如下：  
1：该主机已经开启 Control Master了，在 .ssh 文件夹中会存在 config 文件，内容如下

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/ZzJZQUNIyXGZd3Yu-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/ZzJZQUNIyXGZd3Yu-image.png)

```nginx
Host *
 ControlPath ~/.ssh/controlmaster/%r@%h:%p
 ControlMaster auto
 ControlPersist yes
```

  
2：进入 .ssh 文件夹下的 **contromaster** 子文件夹，我们会发现 socket 文件，文件名格式为 **user@host:22**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/L6zQE3nk9bDlXuPd-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/L6zQE3nk9bDlXuPd-image.png)

  
3：这时候，我们通过命令 **ssh user@host** 无密码移动到要劫持的会话所访问的远程主机上。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/iUk8GMskGYdi3HOr-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/iUk8GMskGYdi3HOr-image.png)

如果我们已经是 root 用户了，通过 **-S** 选项指定 **socket 文件**即可。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/xTgDaNEK19xcmWoW-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/xTgDaNEK19xcmWoW-image.png)

即便当前用户尚未开启 ControlMaster，我们可以替他开启，这样在用户**下次访问**其他主机的时候，我们就能实现劫持。总结一下，我们在 A 主机上发现用户正在通过 SSH 访问 B 主机，我们可以劫持该会话，尾随在其后面，无密码移动到主机 B。

### **SSH 代理转发**

**SSH 代理**是一个在后台运行并将用户的**私钥**存储于**内存中**的程序，因此用户不必在每次使用 SSH 命令时都输入 Passphrase。该代理充当**用户的私钥**和 **SSH 客户端软件** (例如 ssh 或 scp) 之间的**中间人**。每当进程 (如 SSH 会话) 需要使用其中一个密钥向服务器进行身份验证时，代理会处理服务器发送的挑战的解密和签名，因此不需要传递私钥本身，Passphrase 也不用再次输入。这不仅提供了便利，而且还增加了安全性。由于代理将用户的私钥保存在内存中而不是磁盘上，因此它降低了私钥被攻击者窃取的风险。

而**代理转发**是 SSH 的一个特性，可以通过多个服务器建立连接链，并且可以在最远程的服务器上使用在本地主机上运行的 SSH 代理。 简单来说，它允许用户从远程服务器使用本地 SSH 密钥。当用户需要从一台**跳板主机**通过 SSH 连接到另一台服务器，而不需要 **SSH 密钥**传输到本地主机以外的任何其他服务器时，这会很方便。SSH 代理转发提高了安全性，因为我们的 SSH 私钥永远不会暴露给任何远程服务器。但是，如果连接链中的其中一台服务器被入侵，那么密钥可能会被滥用来建立新的连接。

假设**我们自己的主机**为一个**要登陆多个主机的用户的设备**，靶场中的 Web01 为跳板主机，Dev01 为远程主机，情景与前置需求如下：  
  
1：该用户的公钥已经被添加到了 Web01 与 Dev01 上了，并且通过配置 ssh 文件夹中的 **config** 文件来启用代理转发。

```shell
ssh-copy-i -i ~/.ssh/id_rsa.pub <用户名>@<跳板主机>
ssh-copy-i -i ~/.ssh/id_rsa.pub <用户名>@<远程主机>
```

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/3bq8ieuP8eA3voVC-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/3bq8ieuP8eA3voVC-image.png)

启动了 SSH 代理

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/WjT07HaRC1heJ4Le-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/WjT07HaRC1heJ4Le-image.png)

密钥也已经添加到了 SSH 代理中

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/q9bGmw837F0UytI8-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/q9bGmw837F0UytI8-image.png)

2：跳板主机的 **sshd\_config** 文件中开启了代理转发

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/20lHJ8qByQ5fGUF4-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/20lHJ8qByQ5fGUF4-image.png)

3：该用户已经通过 SSH 连接到了跳板主机 Web01 上了

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/Qklg4Fy0ts66zMdr-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/Qklg4Fy0ts66zMdr-image.png)

4：在跳板主机 Web01 上也能进而访问到 Dev01。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-06/scaled-1680-/UhJEG3azdd0Rg5Cw-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-06/UhJEG3azdd0Rg5Cw-image.png)

5：下图视角为**攻击者的视角**，假设攻击者在跳转主机上已经拿到了 root 特权。我们首先列举一下当前主机所存在的 SSH 连接，并且得到 SSH 进程的 PID。

如下图所示，PID **83556** 意味着 SSH 连接后的 bash 会话，我们读取该 PID 的环境变量，发现了套接字文件的地址。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2024-02/scaled-1680-/K3KsqYrWL3yPCR78-image.png)](https://raven-medicine.com/uploads/images/gallery/2024-02/K3KsqYrWL3yPCR78-image.png)

我们当前是 root 用户，使用找到的 SSH 套接字从而劫持 SSH 会话，免密横向移动到 dev01。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2024-02/scaled-1680-/0FcXNJCaG7Yp0r36-image.png)](https://raven-medicine.com/uploads/images/gallery/2024-02/0FcXNJCaG7Yp0r36-image.png)