Last week security researchers from Project Discovery published details on three Lucee vulnerabilities:

  • A Remote Code Execution (RCE) on isDefined, StructGet, Empty functions
  • A RCE on CF_CLIENT cookie values
  • A RCE on REST CFC requests, which was patched in 2023: CVE-2023-38693

The RCE on isDefined, StructGet, Empty functions

Lucee Allows RCE when a variable can be passed to the isDefined, structGet or Empty functions. Here are some examples of what vulnerable code might look like:

isDefined(url.x)
isDefined("#url.x#")
isDefined("url.#x#")

The following code is not vulnerable because it does not pass a variable to the first argument, but rather a static string value:

isDefined("url.x")

I have updated Fixinator to flag the vulnerable instances of isDefined, structGet and empty, so you can use that to search through your code.

You will find that isDefined might be used a lot in your code, but many instances will not be vulnerable because they are passing a static value. If you do pass a variable to isDefined, structGet or Empty – you will want to rewrite that code, and/or upgrade to Lucee >=6.0.1.59, or Lucee >=5.4.5.8 (both are snapshots) and set the settings:

Application.cfc

this.security.limitEvaluation=true;

Environment Variable

LUCEE_SECURITY_LIMITEVALUATION=true

System Property

lucee.security.limitEvaluation=true

Update: The this.security.limitEvaluation feature does appear to work after Lucee 6.0.0.538. I tested Lucee 6.0.1.0, and it does throw a lucee.runtime.interpreter.SecurityInterpreterException:invalid syntax, variables are not supported.
when attempting to exploit the issue.

Fixinator now also looks for the this.security.limitEvaluation setting, and suggests that you add it to your Application.cfc files. I’ve also added a new feature to Fixinator to help with engine specific issues, so you can now pass engines=adobe if you do not use Lucee and it will not flag the issue in your scans. The default is that it flags issues for all engines.

Fixing vulnerable isDefined calls

To fix the vulnerable isDefined calls, you can typically use structKeyExists, or simply the keyExists member function. You will need to know which scope you are expecting the variable to be in. Let’s take a look at how to fix this one:

isDefined("url.#x#")

We can simply rewrite that as follows:

structKeyExists(url, x)
//or
url.keyExists(x)

If you have something like isDefined("form.checkbox#x#") that can be safely rewritten as form.keyExists("checkbox#x#")

The RCE on CF_CLIENT cookie values

The second issue, pertaining to the CF_CLIENT cookies. If you do actually use client variables make sure you are not using the cookie storage mechanism. Using the cookie storage is already something to avoid from a security prospective, but thanks to this issue it is definitely something you should not use.

I’ve found that a good mitigation against this is the following:

Application Settings

Add the following to your Applicaiton.cfc:

this.clientManagement=false;
this.clientStorage="memory";

Or if you use Application.cfm in your cfapplication tag:

<cfapplication clientManagement="false" clientStorage="memory">

Lucee Admin Settings

You can also set the default client storage to memory in the Lucee Admin, and ensure that client management is not enabled by default.

Web Server Blocks

When thinking about security defense in depth, means that you have multiple layers of security that are sometimes redundant incase one layer fails. Adding web server blocks or WAF rules can be a good way to do this in practice.

Example nginx CF_CLIENT cookie block:

if ($http_cookie ~* CF_CLIENT) {
   return 404;
}

Example rule in CloudFlare:

(
 upper(http.cookie) contains "CF_CLIENT" 
 or url_decode(upper(http.cookie)) contains "CF_CLIENT"
)

In both these examples we are just looking for CF_CLIENT in the cookie request header and blocking the request.

To address this issue in my products, I’ve updated Fixinator to look for this.clientStorage in your Application.cfc/cfm, and I’ve updated FuseGuard to look for this cookie when it scans incoming requests (as of FuseGuard 3.6.0).

The RCE on REST CFC requests

The third vulnerability was patched by the Lucee team back in August of 2023. I don’t have much to add to that one other than you should make sure you have upgraded to a patched version of Lucee. If you are running a version of Lucee less than 5.3, then it is probably not patched. Some versions of 5.3 have been back ported with a patch, you’ll want to double check your version. If you are on 5.4, then make sure you are on 5.4.3.2 or greater. See Lucee’s post for details.

To learn more on this I recommend reading the writeup, and also Brian’s writeup on the topic.

Lucee RCE Vulnerabilities February 2024 was first published on February 22, 2024.

Similar Posts