组件风险分析与修复指引:Bcprov Jdk15on 组件安全风险

2024-06-08 339 0

针对开源组件得安全分析,遇到组件安全风险,可通过升级安全版本或打补丁的方式进行修复,升级组件版本常遇安全兼容性的问题,可通过修复代码中的风险点进行打补丁修复。

如下,是Bcprov Jdk15on  1.70版本 组件安全风险分析:

依赖坐标:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</<artifactId>>
    <version>1.70</version>
</dependency>

漏洞风险——Bouncy Castle 信任管理问题漏洞

CNNVD-202307-168

CVE-2023-33201

漏洞描述

Bouncy Castle是Bouncy Castle组织的密码学中使用的API集合。它包括适用于Java和C#编程语言的API 。

Bouncy Castle For Java 1.74之前版本存在安全漏洞,该漏洞源于在将证书的Subject Name插入到搜索过滤器时没有进行转义,导致存LDAP注入漏洞。

解决方案

相关commit:

漏洞补丁:

参考方案:

  • 目前厂商已发布升级补丁以修复漏洞,补丁获取链接:

https://github.com/bcgit/bc-java/commit/e8c409a8389c815ea3fda5e8b94c92fdfe583bcc

安全建议

https://github.com/bcgit/bc-java/wiki/CVE-2023-33201

例外修复分析

经分析,漏洞风险涉及Java类如下:

org.ouncycastle.jce.provider.X509LDAPCertStoreApi

参照官方的目前厂商已发布升级补丁以修复漏洞,补丁获取链接:

https://github.com/bcgit/bc-java/commit/e8c409a8389c815ea3fda5e8b94c92fdfe583bcc

得以了解,Github上面就是对search方法的第二个参数进行了参数过滤:

安全例外修复代码如下(打补丁)

然后我们在项目路径下打个补丁,JVM的加载机制会决定,新写的这个类,会把jar包里面的那个同名同路径的覆盖掉。如下:

[X509LDAPCertStoreSpi.java]

package org.bouncycastle.jce.provider;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CRL;
import java.security.cert.CRLSelector;
import java.security.cert.CertSelector;
import java.security.cert.CertStoreException;
import java.security.cert.CertStoreParameters;
import java.security.cert.CertStoreSpi;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRLSelector;
import java.security.cert.X509CertSelector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.x509.CertificatePair;
import org.bouncycastle.jce.X509LDAPCertStoreParameters;

public class X509LDAPCertStoreSpi extends CertStoreSpi {
    private X509LDAPCertStoreParameters params;
    private static String LDAP_PROVIDER = "com.sun.jndi.ldap.LdapCtxFactory";
    private static String REFERRALS_IGNORE = "ignore";
    private static final String SEARCH_SECURITY_LEVEL = "none";
    private static final String URL_CONTEXT_PREFIX = "com.sun.jndi.url";

    public X509LDAPCertStoreSpi(CertStoreParameters var1) throws InvalidAlgorithmParameterException {
        super(var1);
        if (!(var1 instanceof X509LDAPCertStoreParameters)) {
            throw new InvalidAlgorithmParameterException(X509LDAPCertStoreSpi.class.getName() + ": parameter must be a " + X509LDAPCertStoreParameters.class.getName() + " object\n" + var1.toString());
        } else {
            this.params = (X509LDAPCertStoreParameters)var1;
        }
    }
    private static String[] FILTER_ESCAPE_TABLE = new String['\\' + 1];


    static {

        // Filter encoding table -------------------------------------

        // fill with char itself
        for (char c = 0; c < FILTER_ESCAPE_TABLE.length; c++) {
            FILTER_ESCAPE_TABLE[c] = String.valueOf(c);
        }

        // escapes (RFC2254)
        FILTER_ESCAPE_TABLE['*'] = "\\2a";
        FILTER_ESCAPE_TABLE['('] = "\\28";
        FILTER_ESCAPE_TABLE[')'] = "\\29";
        FILTER_ESCAPE_TABLE['\\'] = "\\5c";
        FILTER_ESCAPE_TABLE[0] = "\\00";

    }

    /**
     * Escape a value for use in a filter.
     * @param value the value to escape.
     * @return a properly escaped representation of the supplied value.
     */
    private String filterEncode(String value)
    {
        if (value == null)
        {
            return null;
        }

        // make buffer roomy
        StringBuilder encodedValue = new StringBuilder(value.length() * 2);

        int length = value.length();

        for (int i = 0; i < length; i++) {

            char c = value.charAt(i);

            if (c < FILTER_ESCAPE_TABLE.length) {
                encodedValue.append(FILTER_ESCAPE_TABLE[c]);
            }
            else {
                // default: add the char
                encodedValue.append(c);
            }
        }

        return encodedValue.toString();
    }


    private DirContext connectLDAP() throws NamingException {
        Properties var1 = new Properties();
        var1.setProperty("java.naming.factory.initial", LDAP_PROVIDER);
        var1.setProperty("java.naming.batchsize", "0");
        var1.setProperty("java.naming.provider.url", this.params.getLdapURL());
        var1.setProperty("java.naming.factory.url.pkgs", "com.sun.jndi.url");
        var1.setProperty("java.naming.referral", REFERRALS_IGNORE);
        var1.setProperty("java.naming.security.authentication", "none");
        InitialDirContext var2 = new InitialDirContext(var1);
        return var2;
    }

    private String parseDN(String var1, String var2) {
        int var4 = var1.toLowerCase().indexOf(var2.toLowerCase());
        String var3 = var1.substring(var4 + var2.length());
        int var5 = var3.indexOf(44);
        if (var5 == -1) {
            var5 = var3.length();
        }

        while(var3.charAt(var5 - 1) == '\\') {
            var5 = var3.indexOf(44, var5 + 1);
            if (var5 == -1) {
                var5 = var3.length();
            }
        }

        var3 = var3.substring(0, var5);
        var4 = var3.indexOf(61);
        var3 = var3.substring(var4 + 1);
        if (var3.charAt(0) == ' ') {
            var3 = var3.substring(1);
        }

        if (var3.startsWith("\"")) {
            var3 = var3.substring(1);
        }

        if (var3.endsWith("\"")) {
            var3 = var3.substring(0, var3.length() - 1);
        }

        return var3;
    }

    public Collection engineGetCertificates(CertSelector var1) throws CertStoreException {
        if (!(var1 instanceof X509CertSelector)) {
            throw new CertStoreException("selector is not a X509CertSelector");
        } else {
            X509CertSelector var2 = (X509CertSelector)var1;
            HashSet var3 = new HashSet();
            Set var4 = this.getEndCertificates(var2);
            var4.addAll(this.getCACertificates(var2));
            var4.addAll(this.getCrossCertificates(var2));
            Iterator var5 = var4.iterator();

            try {
                CertificateFactory var6 = CertificateFactory.getInstance("X.509", "BC");

                while(true) {
                    byte[] var7;
                    do {
                        do {
                            if (!var5.hasNext()) {
                                return var3;
                            }

                            var7 = (byte[])((byte[])var5.next());
                        } while(var7 == null);
                    } while(var7.length == 0);

                    ArrayList var8 = new ArrayList();
                    var8.add(var7);

                    try {
                        CertificatePair var9 = CertificatePair.getInstance((new ASN1InputStream(var7)).readObject());
                        var8.clear();
                        if (var9.getForward() != null) {
                            var8.add(var9.getForward().getEncoded());
                        }

                        if (var9.getReverse() != null) {
                            var8.add(var9.getReverse().getEncoded());
                        }
                    } catch (IOException var13) {
                    } catch (IllegalArgumentException var14) {
                    }

                    Iterator var16 = var8.iterator();

                    while(var16.hasNext()) {
                        ByteArrayInputStream var10 = new ByteArrayInputStream((byte[])((byte[])var16.next()));

                        try {
                            Certificate var11 = var6.generateCertificate(var10);
                            if (var2.match(var11)) {
                                var3.add(var11);
                            }
                        } catch (Exception var12) {
                        }
                    }
                }
            } catch (Exception var15) {
                throw new CertStoreException("certificate cannot be constructed from LDAP result: " + var15);
            }
        }
    }

    private Set certSubjectSerialSearch(X509CertSelector var1, String[] var2, String var3, String var4) throws CertStoreException {
        HashSet var5 = new HashSet();

        try {
            if (var1.getSubjectAsBytes() == null && var1.getSubjectAsString() == null && var1.getCertificate() == null) {
                var5.addAll(this.search(var3, "*", var2));
            } else {
                String var6 = null;
                String var7 = null;
                if (var1.getCertificate() != null) {
                    var6 = var1.getCertificate().getSubjectX500Principal().getName("RFC1779");
                    var7 = var1.getCertificate().getSerialNumber().toString();
                } else if (var1.getSubjectAsBytes() != null) {
                    var6 = (new X500Principal(var1.getSubjectAsBytes())).getName("RFC1779");
                } else {
                    var6 = var1.getSubjectAsString();
                }

                String var8 = this.parseDN(var6, var4);
                var5.addAll(this.search(var3, "*" + var8 + "*", var2));
                if (var7 != null && this.params.getSearchForSerialNumberIn() != null) {
                    var3 = this.params.getSearchForSerialNumberIn();
                    var5.addAll(this.search(var3, "*" + var7 + "*", var2));
                }
            }

            return var5;
        } catch (IOException var9) {
            throw new CertStoreException("exception processing selector: " + var9);
        }
    }

    private Set getEndCertificates(X509CertSelector var1) throws CertStoreException {
        String[] var2 = new String[]{this.params.getUserCertificateAttribute()};
        String var3 = this.params.getLdapUserCertificateAttributeName();
        String var4 = this.params.getUserCertificateSubjectAttributeName();
        Set var5 = this.certSubjectSerialSearch(var1, var2, var3, var4);
        return var5;
    }

    private Set getCACertificates(X509CertSelector var1) throws CertStoreException {
        String[] var2 = new String[]{this.params.getCACertificateAttribute()};
        String var3 = this.params.getLdapCACertificateAttributeName();
        String var4 = this.params.getCACertificateSubjectAttributeName();
        Set var5 = this.certSubjectSerialSearch(var1, var2, var3, var4);
        if (var5.isEmpty()) {
            var5.addAll(this.search((String)null, "*", var2));
        }

        return var5;
    }

    private Set getCrossCertificates(X509CertSelector var1) throws CertStoreException {
        String[] var2 = new String[]{this.params.getCrossCertificateAttribute()};
        String var3 = this.params.getLdapCrossCertificateAttributeName();
        String var4 = this.params.getCrossCertificateSubjectAttributeName();
        Set var5 = this.certSubjectSerialSearch(var1, var2, var3, var4);
        if (var5.isEmpty()) {
            var5.addAll(this.search((String)null, "*", var2));
        }

        return var5;
    }

    public Collection engineGetCRLs(CRLSelector var1) throws CertStoreException {
        String[] var2 = new String[]{this.params.getCertificateRevocationListAttribute()};
        if (!(var1 instanceof X509CRLSelector)) {
            throw new CertStoreException("selector is not a X509CRLSelector");
        } else {
            X509CRLSelector var3 = (X509CRLSelector)var1;
            HashSet var4 = new HashSet();
            String var5 = this.params.getLdapCertificateRevocationListAttributeName();
            HashSet var6 = new HashSet();
            Iterator var7;
            String var9;
            if (var3.getIssuerNames() != null) {
                for(var7 = var3.getIssuerNames().iterator(); var7.hasNext(); var6.addAll(this.search(var5, "*" + var9 + "*", var2))) {
                    Object var8 = var7.next();
                    var9 = null;
                    String var10;
                    if (var8 instanceof String) {
                        var10 = this.params.getCertificateRevocationListIssuerAttributeName();
                        var9 = this.parseDN((String)var8, var10);
                    } else {
                        var10 = this.params.getCertificateRevocationListIssuerAttributeName();
                        var9 = this.parseDN((new X500Principal((byte[])((byte[])var8))).getName("RFC1779"), var10);
                    }
                }
            } else {
                var6.addAll(this.search(var5, "*", var2));
            }

            var6.addAll(this.search((String)null, "*", var2));
            var7 = var6.iterator();

            try {
                CertificateFactory var13 = CertificateFactory.getInstance("X.509", "BC");

                while(var7.hasNext()) {
                    CRL var12 = var13.generateCRL(new ByteArrayInputStream((byte[])((byte[])var7.next())));
                    if (var3.match(var12)) {
                        var4.add(var12);
                    }
                }

                return var4;
            } catch (Exception var11) {
                throw new CertStoreException("CRL cannot be constructed from LDAP result " + var11);
            }
        }
    }

    private Set search(String var1, String var2, String[] var3) throws CertStoreException {
        var2 = filterEncode(var2);

        String var4 = var1 + "=" + var2;
        if (var1 == null) {
            var4 = null;
        }

        DirContext var5 = null;
        HashSet var6 = new HashSet();

        try {
            var5 = this.connectLDAP();
            SearchControls var7 = new SearchControls();
            var7.setSearchScope(2);
            var7.setCountLimit(0L);

            for(int var8 = 0; var8 < var3.length; ++var8) {
                String[] var9 = new String[]{var3[var8]};
                var7.setReturningAttributes(var9);
                String var10 = "(&(" + var4 + ")(" + var9[0] + "=*))";
                if (var4 == null) {
                    var10 = "(" + var9[0] + "=*)";
                }

                NamingEnumeration var11 = var5.search(this.params.getBaseDN(), var10, var7);

                while(var11.hasMoreElements()) {
                    SearchResult var12 = (SearchResult)var11.next();
                    NamingEnumeration var13 = ((Attribute)var12.getAttributes().getAll().next()).getAll();

                    while(var13.hasMore()) {
                        Object var14 = var13.next();
                        var6.add(var14);
                    }
                }
            }
        } catch (Exception var22) {
            throw new CertStoreException("Error getting results from LDAP directory " + var22);
        } finally {
            try {
                if (null != var5) {
                    var5.close();
                }
            } catch (Exception var21) {
            }

        }

        return var6;
    }
}



4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

苹果试图保护你的隐私,OpenAI可能做不到
Shuffle:一款完全自动化的安全栈增强平台
如何使用CODASM编码Payload并降低熵值
SessionExec:一款针对会话安全的安全命令测试工具
Arkime:一款大规模数据包捕获和索引数据库系统
从蓝队流量角度分析Shiro-550反序列化漏洞

发布评论