How to encrypt passwords

I am deploying lucee via a cloudformation script at amazon. I want to be able to store the database and admin passwords as a seperate object and just inject them into the proper xml at deploy time.

The problem is that the passwords in lucee are in encrypted, how do i convert my plain text password created when the database instance is formed into the encrypted version lucee uses?

ie: dbpassword = ‘mybadpassword’
password: “encrypted:encryptedpasswordstringfrommybadpassword”

Also since each instance of lucee is run in a container is the encryption key the same across all lucee installs so the same encrypted password will decrypt to the same value on all lucee servers?

If none of that works is it possible to store the password unencrypted by leaving the encrypted identifier off, certainly not an ideal method?

I assume the same method to encrypt is used for the admin password as well.

Brad should know. He has this on Forgebox. Password is SHA256 salted hash. DB is encrypted Blowfish, I think.
https://www.forgebox.io/view/lucee-password-util

Also saw this:

2 Likes

Yep, that library will do it but you don’t need to use that lib directly. Use CFConfig which is built for this purpose. CFConfig bundles the lib above plus a lot more wrapped up as a CLI.

https://cfconfig.ortusbooks.com/introduction/getting-started-guide

2 Likes

I like this solution as it seams a little less problematic in case the internal details change going forward it seems less fragile.

Although it does require an external dependency since I need to install commandbox and CFConfig separately.

This seems to work with the admin password but not the database password. Is the salt the same as for the admin password? Also, the encrypted database password seems to be 112 characters. Is there some additional processing done or?

Thank you.

@Zach_Brown Database password and admin passwords are not handled the same. The DB passwords are encrypted in a reversible format. The admin passwords are hashed and not reversible. Either way, the answer is the same. Use CFConfig to apply your settings and you won’t need to worry about the details of how each password works :slight_smile:

Thanks for the information, @bdw429s! You answered some questions that were otherwise hard to solve for us!

Just to confirm: do I understand it correctly that, in order to set up a data source in Lucee, we either have to use the Lucee Administrator GUI, or we have to install CFConfig, and thus Commandbox, and thus a second instance of Java on our production server? :slightly_frowning_face:

Giving broad access to the Lucee administrator or setting up a Java instance on the server just to create a data source every now and then seems like a bit of overkill.

One alternative I can think of, is to create a whole bunch of data sources, save their passwords - both encrypted and decrypted - delete the datasources, and then use the hashes in an Application.cfc when we need a data source.

None of these options seem ideal, I have the feeling there must be a better way? Especially since Lucee offers the option to configure data sources using Application.cfc, but that seems kind of superfluous if you need to set it up first in the administrator anyway just to create a password? Am I missing something?

I’m not clear what you mean by a “java” instance but let’s clarify a few things:

  • CommandBox doesn’t require it’s own JRE folder on disk. It’s happy to use a system JRE or even the JRE that your Lucee installation is using. It will look for the JAVA_HOME env var to find java.
  • CommandBox doesn’t need to stay running. It’s only running for as long as it takes for your cfconfig import command to run, then it’s done. Just like Git, or npm would work.
  • Depending whether you regularly need to change the settings on the server, you can remove CommandBox when you’re done if it’s just a one time setup where you load in some utils, configure the server, them remove the utils
  • CommandBox technically doesn’t even need to live on the server. I don’t recall if you’re using Windows or Linux, but all CommandBox needs is access to the files which can happen over a network share if you like as cfconfig import from=file.json to=\\web03/C$/lucee/tomcat/lib/lucee-server (or whatever the path is)

You may be overthinking it. On Linux, CommandBox can be installed and uninstalled with a single apt-get command. You could automate the whole thing in a few lines of bash.

Again, datasource passwords are NOT HASHED. They are encrypted and easily reversible. I wouldn’t recommend putting the encrypted passwords in your source control as it only takes a hacker a few seconds to turn them into plain text.

Putting the datasources in Application.cfc is perfectly valid and I’m not sure where you got the idea that you “need to set it up first in the administrator anyway just to create a password” as that’s not true. Honestly, if the Application.cfc approach works best for you, then use it and just set the passwords as environment variables, which is super common now. And in your CFML code in app.cfc just grab them like so:

password: server.system.environment.DB_PASS,

You can pull env vars right out just like that. Then forget about encrypting them at all because they aren’t going to show up in any files anywhere on disk.

2 Likes

Hey bdw429s, thanks so much for your detailed response, I greatly appreciate it!

Thanks for this! I cannot configure this in CommandBox itself, can I? Should I set the environment variable in Windows (yes, I’m on Windows), or in Tomcat, or somewhere else? I guess that’s a total newbie question, so I do appreciate your patience with me :slight_smile:

I did find I can make CommandBox work by simply installing a second copy of Java using the Oracle link that opens when CommandBox loads, but if I can make it work by pointing it to Lucee’s JRE, that would be so much better!

I’m happy to keep it on all our servers, if it allows our devs to configure new websites without having to RDP to the server first. We’ve locked down Lucee’s Administrator for external access. Perhaps we’re making our lives difficult for no good reason, but it’s a habit we kept from locking down ACF. Perhaps I’m unjustly projecting ACF’s vulnerabilities onto Lucee, but this is why I was hoping for an SSH solution to creating data sources, and how I found CFConfig and CommandBox.

Yes, this is why I thought I might be missing something here. The Lucee documentation shows (“recommends” may be overstating it, but it’s the only example given…) that the datasource for the Application.cfc is first created in the Administrator. And I can’t really see how to do it otherwise, because how else would we get the encrypted password? I assume it needs the private key and the right algorithm from the administrator itself. But this is where I feel there might be a different way that I’m just not seeing?

The java lookup behavior differs a bit between Linux and Windows for CommandBox. Mostly because we use a tool called Launch4j to create our Windows exes and I don’t have much control over how it works. On Linux it’s

  • look for jre folder in the same folder as box
  • look for a JAVA_HOME env var

On Windows, it’s

  • look for jre folder in the same folder as box
  • look in the registry to see what the default version of Java is that’s installed

In the past, launch4j didn’t allow me to search an env var, but checking their ticket tracker just now it appears this has been added as an option! I will make a ticket to support this in the next CommandBox release as it’s been a sore point for a while on Windows.

For you right now, you have two options for Windows

  • Add the registry entries necessary to register Lucee’s JRE as the default java installation so Launch4j’s exe will find it
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft]

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit]
"CurrentVersion"="1.8.0_181-1-ojdkbuild"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.8.0]
"JavaHome"="C:\\Development\\Java\\java-1.8.0-openjdk"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK]
"CurrentVersion"="10.0.2.1-ojdkbuild"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\10]
"JavaHome"="C:\\Development\\Java\\java-10-openjdk"`
  • Symlink Lucee’s JRE folder to the same directory as CommandBox. (I haven’t tested this, but I assume it will work)

Yeah, that’s just because it’s the “easy” method :slight_smile:

You can use the library I wrote that powers CFConfig internally:
https://www.forgebox.io/view/lucee-password-util
Create an instance of the CFC in that lib and call the encryptDataSource() method on it. If you already have CFConfig installed into CommandBox (which means you have the password util also installed as a dependency) you can run this one-liner from the CommandBox REPL:

CFSCRIPT-REPL: getinstance( 'PasswordManager@lucee-password-util' ).encryptDataSource('foo')
dcd8b2c436fed0955b2c9d012551f97d

which returns the encrypted version of the password foo, Now just slap encrypted" in front of it so it looks like this:

password: "encrypted:dcd8b2c436fed0955b2c9d012551f97d",

and that’s what you pass to your Application.cfc. There’s tons of ways you could automate that with a CommandBox Task Runner or whatever if you like.

2 Likes

Thanks so much! Yeah, the env var route looks a bit more difficult than I thought, but the symlink route will be very quick and easy. It’s amazing how many tricky things we solve with symlinks!

Thanks for the direct link to the encryptDataSoure() method, that would make it indeed nice and scalable, without a bunch of dependencies. Will look into it!