
1. 从Log4Shell爆发说开去为什么需要一趟“全景扫描”1.1 一个日志库引发的全球排查2021年底的那次Log4Shell漏洞利用公开很多安全团队应该都还记得当时的紧张程度一个被几乎所有Java应用依赖的日志库一个只需要在请求头里塞一段特殊字符串就能触发的远程代码执行漏洞CVSS评分直接拉到满分。那段时间各家企业都在翻自己资产清单里有没有Java应用运营同学排查访问日志里有没有出现过${jndi:开头的不明请求安全群里整夜都在同步新的利用样本和绕过姿势。Log4ShellCVE-2021-44228的特殊性在于它不在某个特定产品里而在一个基础组件里。这意味着攻击者不需要知道目标系统的内部结构只要目标应用把用户可控的输入写进日志漏洞就会在日志记录的瞬间被触发。攻击者甚至不需要交武器一个HTTP请求头、一个用户名、一条消息字段都可能成为攻击通道。这样的漏洞形态决定了它的利用行为不可能只发生在有限的几个行业或几类系统里而会是一次覆盖整个公网可达空间的“大扫荡”。1.2 单点追踪看不到攻击者的全局我第一次接触这类漏洞排查时习惯性把注意力放在自己负责的资产上看我们的应用有没有暴露、日志里有没有可疑请求、边界上有没有拦截规则。这种“自家院子”视角当然没有问题但它回答不了几个关键问题外面到底有多少人在打这个漏洞他们在攻击什么端口、什么路径攻击节奏是爆发式的还是一直持续的有多少攻击源背后是自动化扫描工具又有多少是带着明确目标的定向入侵这些问题靠被动侧的单点数据是无法回答的。单个企业能看到的只有打到自己的那部分流量而且由于自身访问量、渠道分布、地理位置等因素攻击者是否“光顾”你本身就是一个偏差很大的采样。你看到的可能只是整场战役的一个角落。想要把攻击者的行为放在宏观尺度上观察就必须有一个覆盖足够广、位置足够中立的观测视角。1.3 网络望远镜要回答的核心问题这篇博文想复盘的项目就是一次基于主动式网络望远镜的Log4Shell纵向测量研究。所谓“纵向”指的是在一段持续的时间窗口内反复观测同一个测量空间把时间维度拉出来观察漏洞利用从爆发、爬升、波峰到衰减的完整生命周期。这种测量方式和传统“扫一遍出个报告”的横截面思路完全不同它关注的不是某个时间点的快照而是攻击行为随时间的演化规律。测量要回答的核心问题包括这么几类第一Log4Shell的利用流量在公网上到底持续了多久是几天、几周还是几个月第二攻击源IP有没有明显的生命周期即它们是一次性的扫描器还是会被反复复用的长期基础设施第三利用载荷本身是否在演进攻击者有没有针对防御方的检测规则做出绕过式调整。这些问题单看一两家企业日志给不出答案但把它们放进一个能稳定、持续、大规模观测的网络望远镜里答案就会从数据里自己浮现出来。2. 主动式网络望远镜的工程原理与系统搭建2.1 网络望远镜到底是什么把“网络望远镜”这个概念说透其实就是在公网部署一套大规模的探针系统持续主动地探测尽可能多的IP地址记录目标地址对这些探测请求的响应行为。跟被动流量镜像、蜜罐这类“守株待兔”的思路不同主动式网络望远镜的本质是“挨家挨户敲门”看哪扇门会开、哪扇门后面有什么反应。学术圈里有些大网段属于未分配的地址块流量打到那里本来就会“石沉大海”在那里架设被动望远镜可以观察到大量“背景辐射”流量这种方式确实有效但对Log4Shell这种主动扫描才能触发的漏洞利用被动接受流量就远远不够了。因为漏洞能否被触发取决于攻击者是否主动向目标发送恶意载荷而我们作为观测方如果只是被动接收就观察不到攻击者的主动行为。所以这个项目选择的是主动式方案自己主动向目标系统发起带有探测特征的请求然后记录哪些目标响应了、响应内容里是否包含可被利用的信号。2.2 探测面选择先扫哪几个端口为什么第一步要确定“敲谁的门”。全量扫描整个IPv4空间是不现实的无论是带宽、资源还是合法性上都不可能在一瞬间全部覆盖。可行的做法是压缩探测面把资源集中到最可能部署Java应用、最可能暴露日志入口的端口和服务上去。从Log4Shell的实际利用案例来看攻击者主要打的是两类入口一类是应用层服务的WEB入口包括HTTP/HTTPS的常用端口比如80、443、8080、8443另一类是基础组件端口比如使用了嵌入式HTTP服务的中间件、数据库管理后台、消息队列组件等这些服务往往同时承担业务通信和日志记录功能请求体或协议头成为载荷进入的通道。实际测量时我们选取了包括22、80、443、8080、8443、9200、6379在内的多个端口组。其中22端口和9200、6379这类“非典型Web端口”的选择是研究过程中逐步加进去的因为初步数据表明攻击者并不局限于Web入口他们会扫描包括Redis、Elasticsearch在内的所有可能因为配置不当而暴露在公网上的Java服务。2.3 无害探测载荷的设计思路探测载荷是整个系统的核心。Log4Shell触发的关键字符串是${jndi:前缀后面跟着一个URLJava的日志框架会把这段字符串解析为JNDI查询从而向指定服务器发起一次远程资源访问。作为测量系统我们的目标是诱捕真实的利用信号同时不能对目标系统造成真实伤害。我们采取的方案在业内被称作“无害饵料”构造一个类似${jndi:ldap://我方观测服务器/log4shell-probe}的探测字符串发送到目标系统。如果目标Java应用存在漏洞它就会尝试解析这个字符串并向我方观测服务器发起一次LDAP或HTTP回调。这样一来我方的观测服务器收到回调就说明目标系统存在漏洞而这个回调请求本身不会执行恶意代码也没有把目标系统引向第三方。观察服务器只需要记录回调的来源、时间、路径信息就完成了漏洞确认。这个设计的关键在于探测载荷不能直接使用公网上流行的那几套恶意Payload因为那些Payload会把目标系统带向攻击者控制的服务。而“无害饵料”把探测闭环控制在我们自己的观测半径内既能确认漏洞状态又不会让被探测方承受额外风险。2.4 扫描调度、去重与数据落库探测载荷准备好了下一步是节奏问题。主动扫描天然容易惹麻烦发得太快会被目标机器的安全设备识别和丢弃发得太慢又无法在有效时间窗口内覆盖足够多的目标。我们最终采用了随机分块扫描的策略把IPv4地址空间划分成多个分块每天选取若干分块进行一轮完整扫描并对已经扫描过的分块进行按周为周期的复核。这样既能保证观测覆盖面又能让纵向对比有一个稳定的时间间隔。数据落库是另一个容易翻车的地方。一次扫描产生的记录量极其庞大如果每个IP每个端口都保存全量请求响应存储压力会很快击垮普通服务器。我们做的是两级过滤第一级只有出现Log4Shell特征字符串的请求才会被详细保存第二级对于来自同一IP的重复探测只保留首次请求和最后一次请求中间过程只更新计数器。这也就是为什么会要求你说截断要分成两级因为如果不做这个筛选存储系统和分析系统很快就会被海量噪声吞没有价值的信号反而不容易被发现。实际运行中两级过滤大概能把需要落盘的数据量压缩到原始量的百分之五以下。3. 纵向测量把时间轴拉长之后看到了什么3.1 爆发期、调整期、沉淀期三个阶段的时间分界线把观测数据按时间轴排列之后Log4Shell利用行为呈现出一个非常典型的“三段式”生命周期。这个规律如果不做纵向测量很难发现。第一个阶段是爆发期大致在漏洞信息公开后的前三天到一周。这个阶段的特点是探测流量呈指数级上升大量扫描器在同一时间涌入几乎每个有公网地址的目标都会收到试探请求。攻击源IP数量在这个阶段达到峰值但载荷样式非常单一基本都是同一套公开PoC的变体。第二个阶段是调整期大约在第二周到第四周。涌入的流量开始下降但载荷样式反而变多了。攻击者开始在原始载荷上做变形比如把jndi拆分成jn${...}di、大小写混写、中间插入额外参数等。这些变形的目的很简单——绕过早期那些“见到${jndi:就拦截”的粗粒度检测规则。第三个阶段是沉淀期从第二个月开始一直延续到数月之后。主动扫描流量回落到一个较低的稳定水平但并没有完全消失。攻击源IP的新鲜度开始下降也就是说最后还在出手的那批扫描器很大一部分是有特定目标库的它们不是在广撒网而是在靶向复扫。可以说漏洞利用的高峰期大概只有两三周但利用行为本身形成了漫长的“长尾”这股长尾甚至会持续到下一个爆发性漏洞出现时才被转移注意力。3.2 攻击源IP的“回访率”与基础设施复用纵向视角下最有意思的发现是攻击源IP行为的两极分化。把整个观测周期内的攻击源IP按“是否多次出现”做个聚类会发现一个大约“二八分布”的规律大约两成左右的IP会在观测窗口内反复出现贯穿多个阶段剩下八成IP只来过一次或者只活跃了不到一天然后彻底消失。“一次性IP”很好解释它们是临时租用的云服务器、被攻陷的跳板机或者动态IP的扫描器用完即弃这类IP通常和自动化传播的地毯式扫描关联紧密。“反复出现IP”则是更值得关注的对象。这批IP表现出明显的运营痕迹它们有稳定的扫描间隔、固定的载荷模板、相同的时间段偏好很多IP甚至在Log4Shell爆发之前就在其他端口上执行过Web路径扫描说明它们是某个攻击者或团队长期维护的基础设施。对于防御方来说这个发现有一个直接价值在漏洞爆发初期针对一次性攻击源IP做封闭处理是收效最快的动作因为八成的噪声流量会随着这些IP的消失而显著减少。而反复出现的那两成IP则需要纳入长期威胁情报监控因为它们不会因为一次补丁更新就放弃扫描它们会随着新漏洞的出现反复出手。3.3 载荷变体的演进信号除了攻击源IP载荷本身也提供了丰富的信号。纵向观察载荷样式变化可以反推攻击者的技术水平和工具来源。爆发初期的载荷几乎都是“裸奔”式的直接拼接原始特征字符串前面放一个木马或挖矿程序的回调地址技术上没有做任何隐蔽处理。这个阶段的扫描器识别起来几乎零成本全靠数量堆。进入调整期后载荷呈现出明显的“工具化”特征。比如有的样本会把特征字符串拆成几段拼接有的会利用编码转换把ldap://改成看起来无害的编码形态还有的开始在URL里加入随机路径来避免被按路径匹配的规则直接拦截。这些变形手法多数不是攻击者手动编写而是市面上的扫描框架更新了模块自动生成了绕过变体。在载荷变体的演化里有一条对检测规则设计很重要的规律无论怎么变形最终都要触达JNDI查询所需的协议前缀比如ldap://、rmi://、dns://等协议头。如果把检测规则的核心落在“日志数据中是否出现JNDI协议头且协议头指向非白名单域名”而不是机械地匹配${jndi:全文绕过的概率就会大幅下降。这个经验是测量数据直接给的。4. 从数据到情报测量结果如何反哺日常防护4.1 攻击者的目标偏好与“容易被骗”的资产画像纵向测量除了能看攻击者还能反向勾勒出“哪些资产最容易成为攻击目标”的画像。把探测响应数据按目标端口、目标操作系统指纹、目标应用类型做分组会得到一个比较清晰的“优先级列表”。在我们的测量里端口8080和8443的响应率始终高于其他端口这并不意外这两个端口通常承载开发框架内置的Web服务很多还处于默认配置状态。响应率第三高的是443端口但443端口上的响应率和前两者的差距并不大说明在HTTPS服务上也有大量Java应用存在。真正值得意外的是在9200Elasticsearch和6379Redis这两个端口上的探测响应率明显高于其他非Web端口。这说明公网上存在数量不少的产品型软件实例直接暴露在外它们没有前置的应用层防护一旦漏洞有效利用成本极低。这个测量结果给资产管理人员提供了一个校验工具如果你所在的组织正面临Log4Shell风口期的排查但不确定哪些资产最危险可以先对照“端口服务暴露面”和“组件版本信息”这两个维度拉一遍清单。与其把每个Java进程都翻一遍不如优先排查那些同时满足“公网可达”“非标准Web端口”“日志会记录用户输入”这三个条件的服务。这三项条件都满足的应用是整个攻击面里风险系数最高的一层。4.2 补丁落地速度的另一面有效防护时间窗口纵向数据对补丁策略的评估也有真实素材。我们把某些已知存在漏洞且最终被修复的目标在修复前后的可触发状态放在时间轴上对比能看到一个“默认不用恐慌、但必须快速行动”的结论。具体来说虽然Log4Shell的危险性拉满但公网上的利用流量在漏洞公开后的第一天就达到了第一波高峰而绝大多数安全团队完成“检测规则全覆盖”和“资产版本排查”的时间普遍在两到五天之后。这中间的时间差会导致一个尴尬的结果很多流量是攻击者抢在你完成修复之前打的但他们未必拿到了“入场券”。等到你的规则上线、补丁落地高峰期的扫描已经过去了。但反过来说纵向测量显示一个漏洞的利用长尾持续数月这意味着不能因为“高峰期过去了”就放松警惕。很多慢节奏扫描器会在补丁发布、安全话题降温后的半年里继续试探那些错过修复窗口的老系统。对防守方来说“先挡住前两周的洪水再花一个月清长尾”是比较合理的资源投入节奏。4.3 检测规则与威胁情报的生命周期管理测量数据还会揭示一个在常规安全运营里容易被忽略的问题——检测规则的时效性。很多团队在漏洞爆发时加班加点上线了一堆检测规则然后就放在那里不管了。但威胁情报和检测规则是有生命周期的它们的有效性会随着时间推移、攻击手法变化而衰减。纵向数据告诉我们Log4Shell的载荷样式在几个月内经历了好几轮迭代早期基于特征字符串的规则放到后期漏报率会逐渐升高误报率反而也可能因为匹配过于宽泛而上升。正确的做法是至少每隔两到四周回看一次Hotspot情报库把已经“跑偏”的检测规则做一次校正删除那些已经被利用过但没有产生任何告警的冗余规则同时把新出现的高频载荷特征加入实时检测。任何安全运营项目如果只做规则上线不做规则退役最终都会被海量无用告警拖垮Log4Shell只是比较典型的例子。5. 测量里绕不开的坑、边界与伦理5.1 关键字匹配的误报陷阱整个测量系统最耗时的工作不是扫描本身而是误报清洗。一开始我们的分析脚本简单按“是否包含${jndi:”来判断一次请求是不是Log4Shell利用结果发现误报率飙升到令人发指的程度。原因是大量正常的业务请求本身就包含这些字符串。比如有些开发者在代码里写的配置示例、日志里打印的异常栈、论坛里讨论漏洞时粘贴的样本都会被直接“中招”。更离谱的是有些自动化安全扫描器会在流量里插入等价的字符串来测试目标是否防御了Log4Shell这些扫描器实际上把我们的观测端点变成了一个互相“打标签”的测试场。解决误报的方法是把判定条件从“关键字存在”升级为“行为有效”只有目标同时满足以下条件才判定为真实利用信号——分析请求来源IP是否具备主动扫描特征或者会在多个不同目标间反复出现、请求是否带有可执行性的上下文比如协议头指向一个真实可达的地址、以及目标是否对探测字符串产生了回调行为。这三重条件叠加之后误报率才降到了一个可以接受的量级。5.2 扫描合法性、授权与被动受害者主动网络望远镜项目最大的风险其实不在技术而在合法性和伦理边界。大规模主动扫描必然会产生大量的探测流量这些流量会到达大量并非主动参与研究的系统上还可能会被目标系统的安全设备记录甚至触发告警。这个项目如果在没有授权的情况下对任意IP发起扫描本身就可能构成对目标系统的未授权访问。做这类研究时严谨的团队都必须先界定清楚几个边界扫描对象是否限于可被研究豁免的网络资产探测动作是否会对目标系统的稳定性构成影响观测服务器是否明确标注了研究用途和联系方式以及是否遵守了所在司法辖区对网络扫描行为的具体规定。我在实操中还有一个额外原则主动探测的载荷必须保证是“非破坏性”的不能触发写数据、删除数据、修改配置等操作探测会话必须在收到有效回调前自动终止。这一条原则一定要写进扫描器代码里而不是只停留在项目PPT上。5.3 轻量复现思路在受控环境里架一台“小望远镜”如果你也想做类似的研究甚至只是想在实验室里验证Log4Shell的触发机制完全不需要搭一台覆盖全球的巨型望远镜。一个受控环境下的轻量复现方案包括一台独立VPS作为观测服务器上面运行一个简单的LDAP或HTTP服务用于接收回调一个基于互联网公开扫描框架改写的、只带无害探测载荷的扫描器以及一个SQLite数据库用来记录回调时间、来源、目标端口。操作时重点不在扫描范围有多大而在于测量设计是否严谨。你完全可以把扫描范围限制在实验室内部或自己有权测试的子网里在这个小范围内检验整套测量逻辑探测载荷是否被正确触发、回调是否能被准确记录、去重和两级过滤是否按照预期工作。小型方案跑通后再在获得授权的条件下逐步扩大范围。这样既不会给自己惹来法律风险又能把网络望远镜的核心方法论完整走一遍。根据我的实测经验从零到跑通这样一套小系统一个周末足够了。回顾整个项目纵向测量真正教会我的不是怎么构造一个漂亮的探测载荷而是理解“漏洞利用从来不是单个时间点的事件而是一条有生命周期的曲线”。Log4Shell只是这条曲线的一个样本下一次有类似的通用组件漏洞出现时这套望远镜和纵向分析方法依然能够派上用场。踩过的坑无非是误报、合法性和数据噪声但只要测量边界划得清楚探测载荷守得住无害底线数据的回报率还是相当可观的。