GSMA SGP.22 的 OTA 下载会话劫持

摘要 eSIM 通过 GSMA SGP.22 规范定义的 RSP 平台实现远程配置文件下载,其安全性依赖于 SM-DP+ 服务器与 eUICC 之间的端到端 TLS 通道以及一次性会话令牌。然而,该协议在会话令牌绑定、推送通知验证和用户确认三个环节存在结构性缺陷:部分运营商实现的 AC Token 未绑定目标设备的 EID,推送通知中的路径信息可被明文嗅探,且 SM-DS 的地址解析缺乏强制证书验证。攻击者可利用这些缺陷,劫持合法用户的配置文件下载会话,在攻击者控制的设备上复制目标配置文件,从而实施 SIM 交换欺诈——无需接触受害者设备或发起社会工程攻击。 eSIM RSP 平台 eSIM 生态的关键角色 GSMA SGP.22 定义的 RSP 消费者解决方案包含四个核心实体: eUICC:嵌入式通用集成电路卡,即 eSIM 芯片,可存储多个运营商配置文件。 LPA:本地配置文件助手,运行在终端设备上,负责与 SM-DP+ 通信、下载和安装配置文件。 SM-DP+:订阅管理数据准备+,运营商侧服务器,负责生成、加密和下发配置文件。 SM-DS:订阅管理发现服务器,可选的中间代理,帮助设备发现待下载的配置文件。 一次完整的 OTA 下载流程如下:运营商准备好配置文件,向用户发送 AC Token 或推送通知。设备上的 LPA 通过 AC Token 或扫描 QR 码获取 SM-DP+ 地址和匹配…

USB-C 模拟攻击

摘要 USB Power Delivery 3.1 通过 Configuration Channel 引脚协商高达 240W 的电力与 Alternate Mode 数据,但其协议栈在处理供应商自定义消息(VDM)时缺乏严格的长度验证。攻击者可利用 FPGA 或 STM32 微控制器模拟 PD PHY,发送畸形的 VDM 数据包,触发接收端解析器的堆溢出,进而在 USB4 主控或电源管理芯片的固件中执行任意代码。同时,通过伪造 e-Marker 电缆身份,攻击者能让主机误信其连接了高规格线缆,从而开放超过物理承载能力的电流,引发物理烧毁;或伪装成 DisplayPort Alt Mode 设备,在无用户授权的情况下建立视频输出通道,实现隐蔽监控。 PD协议栈 CC 引脚的半双工通信与 BMC 编码 USB-C 接口的 Configuration Channel(CC)引脚是 PD 协议通信的物理介质。与 USB 数据线不同,CC 采用单线半双工模式,使用双相标记编码(BMC)以 300 kbps 速率传输数据。消息以 64 比特的前导码开头,后接 SOP(Start of Packet)定界符,再跟 16 比特的消息头和可变长度的有效载荷,最后是 32…

AI 模型「溶枪」

摘要 开放神经网络交换格式(ONNX)通过 Protobuf 结构描述计算图,其灵活的自定义操作机制允许绑定任意外部动态库。这一设计便利了硬件厂商的算子优化,却也使得模型文件成为可注入恶意代码的“特洛伊木马”。攻击者可将后门逻辑伪装成合法的预处理或量化算子,在模型中嵌入定制的动态库加载指令。当模型被 ONNX Runtime 等服务加载时,隐藏的代码便会悄无声息地启动反向 Shell、窃取推理数据或篡改预测结果。由于计算图结构极其复杂,大多数静态扫描工具难以识别这类寄生在算子语义中的“溶枪式”后门。 ONNX 的自定义算子和外部数据信任链路 自定义算子的能力边界 ONNX 的自定义算子通过 op_type 和 domain 标识,由推理引擎注册的内核实现。ONNX Runtime 提供 RegisterCustomOp 接口,允许开发者动态添加算子,内核可以调用任意系统 API。这一能力原本是为硬件加速器(如 TPU)预留的,却也为攻击者打开了执行任意代码的通道。攻击者只需将恶意内核封装为动态库(libCustomOp.so),并在模型加载时通过配置文件或环境变量指定该库的路径,即可在推理进程上下文中执行任意操作。 更隐蔽的方式是,攻击者直接修改模型文件中的 external_data 字段,将恶意动态库打包为张量的“权重数据”。在 ONNX 规范中,大张量可通过 external_data 引用外部文件,但也可以将整个库嵌入模型内部。当模型首次推理时,自定义内核的初始化函数会解包该文件到临时目录并调用 dlopen,从而完成自我加载——整个过程无需用户额外配置任何库文件。 模型加载流程中的可注入点 ONNX Runtime 的模型加载流程主要包括:解析模型文件 → 构建计算图 → 注册内置和自定义算子 → 分配内存 → 执行图。 攻击者可劫持以下环节: 图构建阶段:通过修改 GraphProto 中的 node 条目,插入一个高优先级的自定义算子,声称用于“权重解密”或“校验和验证”。该算子会在模型加载后立即执行,先于正常推理。 算子注册阶段:若推理服务允许通过环境变量 ORT_CUSTOM_OP_LIBRARY 指定自定义库,攻击者可通过模型附带的启动脚本设置该变量,实现环境投毒。 外部数据解析阶段:利用 external_data 的 offset 和 length 字段,将一个看似正常的张量指向模型文件末尾的恶意 Shellcode,再由自定义算子读取并执行。 多阶段溶枪攻击链 环境准备与侦察 攻击者植入的第一个自定义算子名为 EnvProbe,域为 ai.utils。它在 ONNX 图中被标记为 Constant 节点的“消费者”,宣称负责“设备能力探测”。实际上,该算子执行以下操作: 检查当前进程权限和操作系统版本; 读取环境变量,确认是否在目标推理服务器上运行; 若判定为生产环境,则释放第二阶段载荷;否则保持静默。 这种选择性激活的策略有效规避了在开发或测试环境中被提前发现的风险。 动态库落地与持久化 EnvProbe 通过 external_data 获取一个压缩的共享库 libsyslog.so(伪装成日志库)。算子将其解压到 ~/.cache/ort_custom/libsyslog.so,并调用 dlopen 加载。该库的构造函数会: 修改 ~/.bashrc,追加一条自动拉取远程脚本的命令; 在 /etc/cron.d/ort_health 中写入一个每 10 分钟执行的定时任务,用于维持反向 Shell; 注册一个新的自定义算子 DataSink,用于后续数据窃取。 数据窃取与回传…

剪贴板即信道

摘要 异步剪贴板 API 为 Web 应用提供了读、写系统剪贴板的能力,但 navigator.clipboard.write() 的异步执行与用户 paste 事件的同步触发之间,存在一个容易被忽略的原子性缺陷。攻击者可利用同一用户手势先后调用 write() 和 read(),通过 Promise.race 构造竞态条件,在浏览器实际写入新内容之前读取到剪贴板中尚未被覆盖的残留数据——而这些数据可能来自另一个域,包含密码管理器自动填充的凭据、2FA 种子或私钥。更危险的是,结合密码管理器的“复制密码”功能和 WebAuthn 条件 UI 的自动填充行为,窃取甚至不需要用户额外的粘贴操作。 异步剪贴板 API 的安全模型 从 execCommand 到 navigator.clipboard 在 navigator.clipboard 出现之前,页面只能通过 document.execCommand(‘copy’) 和 document.execCommand(‘paste’) 操作剪贴板,且后者仅在浏览器扩展或用户主动粘贴时可用。异步剪贴板 API 允许页面使用 readText() 和 writeText() 直接读取和写入文本,前提是获得用户许可(对于 read,通常要求页面可见且由用户手势触发)并且传输数据遵循安全上下文(HTTPS)。 关键设计:write() 返回一个 Promise,在数据被系统剪贴板确认后解析;read() 同样返回一个 Promise,在读取到当前剪贴板内容时解析。二者都是在“任务队列”中异步执行的,但在一次用户手势(如 click 事件)中,可以同时调用两个方法而不相互阻塞。 同一个点击下的 write 与 read 考虑以下代码: button.addEventListener('click', async () => { navigator.clipboard.writeText('A'.repeat(100)); const data = await navigator.clipboard.readText(); console.log(data); }); 开发者预期 readText() 会返回刚才写入的 ‘AAA…’,但实际结果取决于 UA 的事件循环调度:如果 writeText() 的内部实现是“先调度写入任务,再解析 Promise”,而 readText() 在写入任务实际执行之前就已经从系统剪贴板读取了内容,那么 data 将是调用 writeText()之前 剪贴板中的旧数据。这个顺序差异构成了可被利用的竞态窗口。 竞态条件的微观时序 任务队列的调度间隙 浏览器主线程执行模型: 用户点击,click 事件处理开始。 调用 writeText(),UA 创建一个“写剪贴板”任务并将其排入任务队列,同时返回一个 Promise。 继续执行,调用 readText(),UA 创建一个“读剪贴板”任务排入队列,返回…

虚悬页表

摘要 内核页表隔离 (KPTI) 是防御 Meltdown 类攻击的关键机制,通过分离用户态与内核态页表,确保用户态代码无法直接窥探内核地址空间。在 ARM64 上,KPTI 由 CONFIG_UNMAP_KERNEL_AT_EL0 和 kpti 引导参数控制,利用 TTBR0_EL1 与 TTBR1_EL1 的切换将内核映射仅在异常入口时临时暴露。然而,ARM 体系结构的维护操作(Maintenance Operations)存在一个隐蔽缺陷:部分 SoC 的 TLBI(TLB Invalidate)指令和 IC IALLU 序列仅刷新 TLB 而不冲刷页表缓存(PTC, Page Table Cache),导致在异常返回(ERET)后,TTBR1 中残留的中间页表项仍可通过推测执行或预取被用户态感知。攻击者利用性能监控单元(PMU)的精确计数器,在用户态测量内核地址访问的延迟差异,即使 KPTI 已重新隔离页表,仍可通过这些“虚悬的页表”还原内核基址,从而击碎 KASLR。 双重身份页表 两个TTBR ARM64 的虚拟地址空间分为两个区域:0x0000_0000_0000_0000 到 0x0000_FFFF_FFFF_FFFF 为用户空间,0xFFFF_0000_0000_0000 以上为内核空间。当 MMU 进行地址翻译时,根据虚拟地址的最高位自动选择页表基址寄存器:用户地址使用 TTBR0_EL1,内核地址使用 TTBR1_EL1。在未启用 KPTI 的情况下,两个寄存器都指向同一个页表(通常包含内核映射),用户态代码虽不能直接访问内核内存(受页表权限 U/S 位控制),但可以通过侧信道探测 TLB 存在性。 ======================= 正常态:用户空间 (EL0) ======================= CPU 视角: +——————–+ +——————–+ | TTBR0_EL1 (受限表) | —-> | 仅映射:用户空间 | (只读内核映射表) +——————–+ +——————–+…

WNF 的幽灵状态

摘要 Windows 通知设施(Windows Notification Facility)是内核向用户态分发系统事件的异步通道,负责传递诸如电池状态、网络连接变化、Shell 执行触发等大量低延迟通知。WNF 的状态数据以键值对形式存储在内核池中,并按临时或永久两种生命周期管理。然而,这一设计隐藏了一个鲜为人知的反取证库房:永久性 WNF 状态即使关联进程退出,其数据依然存活于内核内存中,且重启后仍可从注册表或其他持久化位置恢复。攻击者可通过 NtCreateWnfStateName 与 NtUpdateWnfStateData 在内核池中建立隐形存储,将 Shellcode、C2 配置或加密密钥藏匿于传统取证工具无法触及的角落,并在特定系统事件触发时通过 WNF_SHELLEXECUTE 等 Shell 触发器在用户态启动恶意进程。 WNF架构 轻量级通知引擎 Windows 内核需要向用户态组件推送大量异步事件,例如电源管理通知、Shell 文件关联变更、网络地址变化等。早期实现主要依赖 ETW 提供者和回调,但 ETW 的启用和解析较为笨重。Windows 8 引入 WNF 作为更轻量的替代方案,其设计目标是在内核与用户态之间提供高效、基于状态的订阅通知机制,且无需用户态主动轮询。 WNF 的整体组件架构与交互过程如下: +——————————————————-+ | 用户态层 | | +——————–+ +———————+ | | | Publisher (发布者) | | Subscriber (订阅者) | | | +———+———-+ +———-+———-+ | +————|—————————|————–+ | | NtUpdateWNFStateData| |NtSubscribeWNFStateChange…