欢迎来到 无奈人生 安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

Golang语言TLS双向身份验证拒绝服务漏洞分析(CVE-2018-16875)

来源: 作者: 时间:2019-02-24 19:29 点击: 我要投稿
广告位API接口通信错误,查看德得广告获取帮助

概述
如果您的源代码是以Go语言编写的,并且它使用了单向或双向TLS身份验证,那么该程序将很容易受到CPU拒绝服务(DoS)攻击。攻击者可以通过某种特定的方式来格式化输入内容,使得Go的crypto/x509标准库中的验证算法,在尝试验证客户端提供的TLS证书链的过程中,占用了所有可用的CPU资源。
如果要保护您的服务,请立即升级到Go 1.10.6或更高版本,或者升级至1.11.3或更高版本。
背景
42Crunch的API安全平台的后端,已经使用了微服务的架构来实现。这一微服务使用Go语言编写,通过gRPC相互通信,并且具有用于外部调用的REST API网关。为了确保安全性,我们遵循着“能用TLS就尽量用”的宗旨,广泛依赖于双向TLS身份验证。
Go在其标准库中提供本地的SSL/TLS支持,以及用于操作连接、验证、身份验证和证书的大量x509及TLS原语。这一本地支持,通过使用标准、经过检查、定期维护的TLS实现,来避免外部依赖性,并降低风险。
那么自然,42Crunch就可能会受到影响。因此,我们必须认真分析这一TLS漏洞,以确保42Crunch平台的安全性。
42Crunch安全团队发布了关于这一漏洞的分析以及详细信息。
问题
TLS链验证中的拒绝服务漏洞,最初由Netflix发现并报告,如Golang的问题跟踪器中所述:
crypto/x509包负责解析并验证X.509编码的密钥和证书。该包在处理攻击者提供的证书链时,本应该进行使用资源是否合理的判断。crypto/x509包没有限制为每个链验证执行的工作量,这可能允许攻击者制作导致CPU拒绝服务的恶意输入。Go TLS服务器接受客户端证书,TLS客户端将验证证书是否受到影响。
这里的问题之处,在于调用路径crypto/x509 Certificate.Verify()函数,该函数负责授权控制和验证证书。
漏洞详细分析
为了简化这一部分内容,并且使读者能够清楚了解,我们仅以TLS客户端连接到验证客户端证书的TLS服务器为例,展现这一过程的具体细节。
TLS服务器持续监听TLS客户端的8080端口,并根据一个受信任的证书颁发机构(CA)对客户端的证书进行验证:
caPool := x509.NewCertPool()
ok := caPool.AppendCertsFromPEM(caCert)
if !ok {
        panic(errors.New("could not add to CA pool"))
}
 
tlsConfig := &tls.Config{
        ClientCAs:  caPool,
        ClientAuth: tls.RequireAndVerifyClientCert,
}
 
//tlsConfig.BuildNameToCertificate()
server := &http.Server{
        Addr:      ":8080",
        TLSConfig: tlsConfig,
}
 
server.ListenAndServeTLS(certWeb, keyWeb)
在一个标准的TLS验证方案中,TLS客户端连接到TLS服务器的8080端口,并提供其“信任链”,其中包括客户端证书、根CA证书以及所有中间CA证书。TLS服务器处理TLS握手,并验证客户端证书,检查客户端是否可信(客户端证书是否由服务器信任的CA进行签名)。下图展现了TLS握手时的简化版流程:

通过Go的crypto/x509库,我们最终进入到x509/tls/handshake_server.go:doFullHandshake(),具体如下:
...
if c.config.ClientAuth >= RequestClientCert {
        if certMsg, ok = msg.(*certificateMsg); !ok {
                c.sendAlert(alertUnexpectedMessage)
                return unexpectedMessageError(certMsg, msg)
        }
        hs.finishedHash.Write(certMsg.marshal())
 
        if len(certMsg.certificates) == 0 {
                // The client didn't actually send a certificate
                switch c.config.ClientAuth {
                case RequireAnyClientCert, RequireAndVerifyClientCert:
                        c.sendAlert(alertBadCertificate)
                        return errors.New("tls: client didn't provide a certificate")
                }
        }
 
        pub, err = hs.processCertsFromClient(certMsg.certificates)
        if err != nil {
                return err
        }
 
        msg, err = c.readHandshake()
        if err != nil {

[1] [2] [3]  下一页

概述
如果您的源代码是以Go语言编写的,并且它使用了单向或双向TLS身份验证,那么该程序将很容易受到CPU拒绝服务(DoS)攻击。攻击者可以通过某种特定的方式来格式化输入内容,使得Go的crypto/x509标准库中的验证算法,在尝试验证客户端提供的TLS证书链的过程中,占用了所有可用的CPU资源。
如果要保护您的服务,请立即升级到Go 1.10.6或更高版本,或者升级至1.11.3或更高版本。
背景
42Crunch的API安全平台的后端,已经使用了微服务的架构来实现。这一微服务使用Go语言编写,通过gRPC相互通信,并且具有用于外部调用的REST API网关。为了确保安全性,我们遵循着“能用TLS就尽量用”的宗旨,广泛依赖于双向TLS身份验证。
Go在其标准库中提供本地的SSL/TLS支持,以及用于操作连接、验证、身份验证和证书的大量x509及TLS原语。这一本地支持,通过使用标准、经过检查、定期维护的TLS实现,来避免外部依赖性,并降低风险。
那么自然,42Crunch就可能会受到影响。因此,我们必须认真分析这一TLS漏洞,以确保42Crunch平台的安全性。
42Crunch安全团队发布了关于这一漏洞的分析以及详细信息。 本文来自无奈人生安全网
问题
TLS链验证中的拒绝服务漏洞,最初由Netflix发现并报告,如Golang的问题跟踪器中所述:
crypto/x509包负责解析并验证X.509编码的密钥和证书。该包在处理攻击者提供的证书链时,本应该进行使用资源是否合理的判断。crypto/x509包没有限制为每个链验证执行的工作量,这可能允许攻击者制作导致CPU拒绝服务的恶意输入。Go TLS服务器接受客户端证书,TLS客户端将验证证书是否受到影响。
这里的问题之处,在于调用路径crypto/x509 Certificate.Verify()函数,该函数负责授权控制和验证证书。
漏洞详细分析
为了简化这一部分内容,并且使读者能够清楚了解,我们仅以TLS客户端连接到验证客户端证书的TLS服务器为例,展现这一过程的具体细节。
TLS服务器持续监听TLS客户端的8080端口,并根据一个受信任的证书颁发机构(CA)对客户端的证书进行验证:
caPool := x509.NewCertPool()
ok := caPool.AppendCertsFromPEM(caCert)
if !ok {
        panic(errors.New("could not add to CA pool"))
}
 
tlsConfig := &tls.Config{
        ClientCAs:  caPool,

www.wnhack.com


        ClientAuth: tls.RequireAndVerifyClientCert,
}
 
//tlsConfig.BuildNameToCertificate()
server := &http.Server{
        Addr:      ":8080",
        TLSConfig: tlsConfig,
}
 
server.ListenAndServeTLS(certWeb, keyWeb)
在一个标准的TLS验证方案中,TLS客户端连接到TLS服务器的8080端口,并提供其“信任链”,其中包括客户端证书、根CA证书以及所有中间CA证书。TLS服务器处理TLS握手,并验证客户端证书,检查客户端是否可信(客户端证书是否由服务器信任的CA进行签名)。下图展现了TLS握手时的简化版流程:

通过Go的crypto/x509库,我们最终进入到x509/tls/handshake_server.go:doFullHandshake(),具体如下:
...
if c.config.ClientAuth >= RequestClientCert { www.wnhack.com
        if certMsg, ok = msg.(*certificateMsg); !ok {
                c.sendAlert(alertUnexpectedMessage)
                return unexpectedMessageError(certMsg, msg)
        }
        hs.finishedHash.Write(certMsg.marshal())
 
        if len(certMsg.certificates) == 0 {
                // The client didn't actually send a certificate
                switch c.config.ClientAuth {
                case RequireAnyClientCert, RequireAndVerifyClientCert:
                        c.sendAlert(alertBadCertificate) www.wnhack.com
                        return errors.New("tls: client didn't provide a certificate")
                }
        }
 
        pub, err = hs.processCertsFromClient(certMsg.certificates)
        if err != nil {
                return err
        }
 
        msg, err = c.readHandshake()
        if err != nil {

内容来自无奈安全网

[1] [2] [3]  下一页

www.wnhack.com

。 (责任编辑:admin)
【声明】:无奈人生安全网(http://www.wnhack.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱472701013@qq.com,我们会在最短的时间内进行处理。