[Looking for Charlie's main web site?]

On handling the June 2024 CF update change of default algorithm from CFMX_COMPAT

If you're considering or have already implemented the latest CF updates from June 2024, you might have struggled a bit to understand completely what Adobe was getting at in the update technotes, as they can sometimes be rather terse in covering some points (worse, some folks don't even read the technotes before applying the updates). Briefly, a key aspect of the update changes the default algorithm that CF uses--for code that does not specify one, in several CF functions, related to encryption, hashing, or randomization.

As another case where Adobe is opting to sacrifice compatibility for security, the update changes from using the very old default of CFMX_COMPAT (as the default) to using either of a couple different alternatives, depending on the function. And if you're not careful/paying attention, you could break some critical part of your app by applying this update.

TLDR; In this post, I want to share a bit more to help you understand the impact of this update, whether you're a developer or an administrator--and whether you've applied or not yet applied the update. Even if you HAVE done it and "all seems well" (in test or even in prod), do beware there may be nasty problems waiting to bite you that could take time to crop up. I'll explain the issues, and help you find the code using these functions, then help you determine if that code is or IS NOT affected by this change. I'll also discuss some real-world scenarios and challenges, with solutions.

Finally, I'll explain an available JVM arg that can be used to revert this behavior, for those who may feel they need to sacrifice security for compatibility, so as to get to this June update and take their time to address this change in the encryption default. I also explain how the CFMX_COMPAT algorithm DOES still remain available as an option, despite what some have asserted, which may be an acceptable option to use. Then I wrap up with some thoughts on how it may not be so bad that I'm only getting this post out a few weeks after the June update.

For more, read on.

Contents:

Background

Readers of my blog should have seen that I did a blog post the day Adobe released in mid-June an update for ColdFusion 2023 and 2021 (updates 8 and 14, respectively). As always, the main focus of my post was to get the word out about the update (as not everyone notices them, even with the CF Admin feature to indicate a new update is available--which doesn't help those whose servers have no internet access.)

But I also gave a heads-up about the risk to beware in this update, reflected in the title, Updates released for ColdFusion 2023/2021, today June 11 2024, and another possible breaking change. And as always I shared in the post the link to Adobe's technote for each version's update (which usually reflect the same info for a given update, though not always), and I also shared a link to the Adobe forum entry that they (Saurav) created to announce the update.

And that technote offered a good bit of info that should have helped most to grok the matter, but I find that sometimes people come away from the technotes still a little mystified. Often in my blog post announcing the update I'll elaborate a bit, but sometimes since I also only learn of the update that day, I don't really get a chance to dig too deeply. This post is my follow-up to that.

(And sorry that it's been a few weeks. Sadly, in my work I help people in dealing with things like CF updates and a LOT more. Sometimes that precludes me getting to write all the posts I might want to, or other matters come up--such as the Java update released last week, or my take on the special "patch" Adobe came out with to help with fallout from the March CF updates.)

What the June update does (and does not) affect

You could be forgiven for either under-estimating or over-estimating what the impact is of the June CF updates. Some came away thinking "this doesn't affect me, as we don't do any encryption", while others said "we only do encryption in one place and we confirmed it's ok". (Again, it has more to do with than JUST encryption/decryption.) Still others might be frozen in panic: "how the heck am I ever going to be able to figure out what's impacted in our code?"

Here's the crux of the matter:

  • if you use any of these 7 CFML functions, you have to at least assess your use of them: Encrypt, EncryptBinary, Decrypt, DecryptBinary, Hash, Rand, Randomize. RandRange
    • note that each takes an argument that names an algorithm (all 7 functions got that algorithm arg starting with CF7). Sadly, the argument may be the 2nd or 3rd, depending on the function. You've got to look at the docs (which Adobe links to in the update technote, which I link to in my blog post about the update)
  • the issue is that if your code does NOT specify that arg naming the algorithm, then prior to this update CF would have used "CFMX_COMPAT" as the value by default
    • After the update, such code would now use a DIFFERENT default algorithm: and that's where things can go wrong. If you have in the past created some database record or file or link using that old algorithm, then any CFML code that would now try to "read" that would use the NEW algorthm, which may fail (with an error or just logically be incorrect)
    • Note also that the new "default algorithm" varies between the seven different functions. See that Adobe update technote for the details on each
  • If instead your code DOES specify the arg naming an algorithm, then that code does NOT "need" to change
    • That said, if you DO specify that old CFMX_COMPAT value as the algorithm you're using, Adobe is suggesting people switch to a better one

So the bottom line is that you need to find any use of these in your code (and I share tips below on doing that, including via different tools), and then you need to determine if your use of those functions needs to change, per the points above.

As for any code you have using these seven CFML functions where you DO specify the algorithm argument, that code is not affected at all by this change in the default.

How to find potentially affected code

So how can you find that potentially affected code? Well, on the surface, you just need to "search your code base". I do want to share a couple of tips on that.

1) First, when it comes to searching for the functions, note that there are 4 prefix values you can search for which will cover all 7 functions: encrypt, decrypt, hash, and rand. That's perhaps easier than looking for all 7. (More on "how" to search for them in a moment.)

Of course, you may well find hits that you can ignore: references to those terms in comments or text, javascript code, etc.

2) Second, as for HOW to search for the code, that will depend on your tools (and your comfort with them). If you use an editor/IDE--whether that's VSCode, Sublime, Notepad++, or perhaps CFBuilder, Dreamweaver, CF Studio (yep, there are CF people still using that), you can easily search for those strings without even need of a regex.

Or note there are tools that are dedicated file text search tools. Everyone has their favorites, whether as Windows or Linux or Mac tools. I'll share that my favorite file text search tool on Windows remains the free (and modern) File Locator Lite tool, which I have written about before.

Now that you've found the code, what can you do with it? And more important, why should you worry about the problems associated with this change in behavior? Again, it ONLY affects you where you have code using those 7 functions but which does NOT specify the algorithm argument.

Why might this change of behavior lead to a problem? And how can you handle it?

So why should this change concern you? Well, there are at least a few scenarios where you could get bitten, whether doing encryption/decryption or hashing, for example. These are just a few scenarios: I'm sure there are others.

Encryption challenges

if you have some affected CFML encryption code (which doesn't set the algorithm argument), then prior to this update the value it would have been based on that CFMX_COMPAT algorithm. But the same code running AFTER the update (which doesn't set the algorithm argument) would now produce a DIFFERENT (for the same incoming value and encryption key), because it would be using the new default algorithm.

And if you store the result of such encryption in a database or file or perhaps an email or URL that has been shared, the later attempt to DECRYPT that value may either FAIL or simply produce a DIFFERENT result--in which case some logical test or use of the decrypted value will be incorrect. Let's look a little closer.

What if you have used encryption for data stored in a database?

At least if you stored that encrypted value in a database, you know how it was encrypted before this change (using cfmx_compat, if none was specified in your code before this update), so you have multiple choices:

  • you could change your code (doing the encryption and the decryption) to instead formally USE the CFMX_COMPAT value. That code will now "keep on working" (though Adobe would argue that the CFMX_COMPAT algorithm is old and insecure). Don't believe those who are asserting that CFMX_COMPAT has been removed: it has not. I'll reiterate this point below. This is an option you can consider on a case-by-case basis, if you may have different code/use cases doing such encryption/decryption
  • you could use the "lifeline" (or "training wheels") that Adobe has offered with this update, and implement a new JVM argument that reverts CF to the previous behavior, where the default algorithm (if none is specified) is again "CFMX_COMPAT". That's a temporary option available only until CF2025, but at least it allows you to still be able to apply the June update--which has other benefits security fixes beyond this one issue. More on this option below. Again, this just changes the default for code that does NOT specify an algorithm. You could still do either the change above or the next one
  • Otherwise if you ARE motivated to change your algorithm, you could perform a process to extract your encrypted data from the database (decrypting it with "cfmx_compat", if that's how it was encrypted), and then re-encrypt it with a better encryption algorithm (the new default or one you choose) and store it back into the database. Then you could change your code to use that new (better) encryption algorithm going forward.

Do note that a subtlety about changing to using a new encryption algorithm (other than CFMX_COMPAT) is that the encrypt* and decrypt* functions also take a required "key" argument (in addition to the string to be encrypted), and in the case of CFMX_COMPAT that key could be any string. But with all the other algorithms, this "key" value must be something generated from the CFML function called generatesecretkey. See the CFML docs for more, such as for encrypt, for example.

What if you have used encryption for data "sent elsewhere"?

But what if you may have used the encryption mechanism (without an algorithm specified) to create a value that was sent to someone in an email or to create some URL that has been shared? Or perhaps you offer an API where people can obtain something you encrypted and THEY have stored it. In these cases you may have no way to "get the encrypted value back" to re-encrypt it (like in the database discussion above).

You still have at least 3 choices, like in the previous section. But if you DON'T want to change your decryption code to revert to CFMX_COMPAT using either the 1st or 2nd options just listed, you will have to deal with the fact that if you rely on the new default (or choose some better algorithm), some later attempt to decrypt such a value (in an email or url, for example) may fail (if you can't readily tell somehow which algorithm was used).

One thought is that you could implement error handling that tries to decrypt it using the new algorithm such that it fails, you could then try using CFMX_COMPAT. It's imperfect, but I'm just spit-balling here. Perhaps we'll hear from others in comments as they discuss how they may have dealt with all this.

(Again, if you do change to using a new algorithm for the encrypt/decrypt functions, you will need to change their second argument (the "key") to use generatesecretkey() instead of just any string.)

Hashing challenges

If you've got code using the CFML hash function (and you didn't specify the algorithm to use), then this leads to perhaps a more challenging situation: first, again the hashed result for a given input value will be different (before and after this update--for any code doing a hash but that does not include the argument naming the hashing algorithm).

So for example, you may be hashing password values before storing them in a database. This is a widely recommended better practice compared encrypting them--because it's a one-way process: you are given a password and you hash it, which produces a very random string which you store in the database. And then when you are TESTING a password against that stored value, you hash that password to be checked and COMPARE THAT HASHED VALUE to what's stored in the database. On the surface, it's great. No one can ever figure out what the password was, that was stored in the database because the hashing is a one-way process (that's the generally accepted understanding, at least.)

The problem is that now you ALSO cannot "recover" any of the hashed passwords to "re-hash them with a new algorithm" as was "so easy" to do above regarding encrypted values stored in a database (and people who hash passwords may still encrypt other sensitive database, so you may have to deal with both situations).

In this scenario, since you don't HAVE the values that would need to be "reprocessed", it would seem these are your options. They are similar to those listed above:

  • Change your code (that does the hash without specifying an algorithm) to go ahead and specify CFMX_COMPAT as the algorithm. Some might argue that it's perhaps not quite AS important to change to a more secure algorithm for hashing. You need to study and decide that for yourself
  • Implement the JVM argument (mentioned in the previous section) which reverts CF to the previous behavior, so the default algorithm (if none is specified) is again "CFMX_COMPAT". Once more: that's a temporary option available only until CF2025. More on this option below. But it buys you time to deal otherwise with this problem, while still being able to apply the June update. Again, this just changes the default for code that does NOT specify an algorithm. You could still do either the change above or the next one
  • If you WOULD want to use a new algorithm for some code that creates a hash, such as to store a hashed password in a database (going forward), it would seem you'd need to resort to creating a new column in your database to store such a NEWLY/differently hashed password and perhaps another column tracking THAT you're using the newly hashed password. Then modify your code that both CREATES and USES such a hashed password to work differently based on these two scenarios

That last suggestion may feel hacky/kludgy. Again, I'm just spit-balling here: perhaps someone will offer different/better ideas for resolving this dilemma (where you have code doing a hash but which had no algorithm--and you don't want to use CFMX_COMPAT going forward, but you need to deal with values hashed using the old CFMX_COMPAT in the past).

At least with hash, there is no "key" arg (like with the encrypt/decrypt functions), so no need to worry about switching it from a simple string to using generatesecretkey().

What about the rand* functions?

On the surface, it would seem that the rand* functions (rand, randomize, and randrange) will generally be easier to deal with. You don't normally need to "work backward" from such a randomized value, such that if your code starts using a new algorithm (by default, because none is specified in your code) it will just create new differently-random values.

Before we wrap up, let me elaborate a bit on the notion of setting CF to still use CFMX_COMPAT.

On using the new JVM arg to change the default back to CFMX_COMPAT

As I noted at the open (and have now reiterated a couple of times), Adobe did recognize that this change (trading compatibility for security) might prove to be "too much" for some folks to readily attend to (to find and change their code). But again this June update entails MORE than just this one change: what if you want to get to this June update but do NOT want to (or can't) change your affected code (as discussed ablve)?

Just like with the key change in the March 2024 update (regarding searchimplicitscopes), Adobe has offered an option in this release allowing you to revert CF back to its previous behavior of using CFMX_COMPAT as the default algorithm (in the affected functions, and where you do not specify their algorithm argument).

As discussed in the June update's technotes (for each of CF2023 and 2021, linked to in my first blog post on the June update), that JVM argument is:

-Dcoldfusion.encryption.useCFMX_COMPATAsDefault=TRUE

Before doing this, not a couple of things:

First, as for where to put such a JVM arg, you could add it--carefully--in the CF Admin's "java & jvm" page and its "java args" field, or via the jvm.config file (such as in CF's cfusion/bin folder) and its java.args line. In either case, don't add such a JVM arg as a "new line" there: all the args are technically all on a single line. Either add it to the end of the line or after some other arg there, being sure to leave a space before or after any other. (But do NOT put a space WITHIN that argument above, including before or after the "=", which is a mistake Adobe initially made in the technotes.) Any such mistake could keep CF from starting--which would also keep you from getting back into the CF Admin to change the args, if that's where you changed them.

Then also, as I noted above, implementing this JVM arg changes ONLY the default algorithm for code that does NOT specify an algorithm. Code that already does name an algorithm (or that you change in addressing these issues) will work just fine using whatever algorithm you name in that function.

But again this is workaround you can rely on only TEMPORARILY: Adobe makes clear in the technotes for this update that the JVM arg will NOT function in CF2025 and beyond. (Since it's a -D argument, it's not that "ColdFusion will fail to start if you leave the argument in beyond CF2023." It will simply be IGNORED in CF2025 and beyond--and then you will HAVE to deal with the code changes discussed above, for any of the seven functions where you don't specify an algorithm.)

As a final aside, some may want to hear this clarification: Adobe has NOT provided with this update any sort of application-level setting for changing the default algorithm for these seven functions, like they did for the searchimplicitscopes setting discussed in the March 2024 update. That's as much because (as discussed at the outset and in the update technotes), the default is changing to different algorithms for the different functions.

Note that CFMX_COMPAT has NOT been removed

Finally, as I've also said a couple of times above, you absolutely CAN change your code (where you use these functions but fail to name an algorithm) to that the code instead DOES specify to use the "old" CFMX_COMPAT algorithm. This is even stated specifically in the June update technotes: "Note that CFMX_COMPAT is still available."

Again, Adobe discourages people from using it (as indeed they long have, referring to it as "the least secure" algorithm since they added more and more new ones starting with CF7, aka CFMX7.)

But for some situations, using that specific "old" algorithm (naming it, in your code) may be the right solution, or an acceptable one, at least may be a better short-term workaround than using the JVM arg (which again affects ALL use of the affected functions where code doesn't name an algorithm).

Summary: and on the delay in getting around to all this

So, phew, that was another marathon post. Why would I need to say so much when Adobe's discussion of the whole matter is just a couple dozen sentences? Well, I'll let you judge if somehow I've added "needless melodrama" or "over-explaining" to this matter. I think all that I said above needed to be said, judging from the help I have been offering people the past month, either in the community or as clients of my troubleshooting consulting services.

And indeed, while I am sorry I didn't get this note out sooner after the June update, the time since the update (released while I and others were at CFCamp in Germany that week of June) has allowed me the opportunity to learn more and solidify my own understanding of things as I've helped others. That delay can be seen as helping you. :-)

Speaking of delays, one more bit of "good news" (that might diminish the pain of this being delayed getting posted) is that some folks are indeed themselves delayed in getting around to this June update: many are still reeling and dealing with the March 2024 update. Or perhaps in their haste they opted to just put in the jvm arg (to deal with the key change in either or each of the updates).

Lastly, I'll say again that I am open to more ideas from folks either on the scenarios I described or the solutions I proposed. If I get enough new ideas, I may even create a new post on that more specifically (and of course I would credit anyone who shared a new idea, unless you opted to remain anonymous in your comment).

As always, hope all this was helpful.

For more content like this from Charlie Arehart: Need more help with problems?
  • If you may prefer direct help, rather than digging around here/elsewhere or via comments, he can help via his online consulting services
  • See that page for more on how he can help a) over the web, safely and securely, b) usually very quickly, c) teaching you along the way, and d) with satisfaction guaranteed
Comments
Copyright ©2024 Charlie Arehart
Carehart Logo
BlogCFC was created by Raymond Camden. This blog is running version 5.005.
(Want to validate the html in this page?)

Managed Hosting Services provided by
Managed Dedicated Hosting