That title would have sounded very weird to me a year ago but that’s exactly what happened. Let me walk you through how we were approached by a client for a code review, had to find a zero day just to get started (CVE-2022-29856), and ultimately “decrypted a robot.” You’ll also get to see how surprisingly simple it was to accomplish.
It all started with a client requesting a run of the mill code review, but for their robots. Now you have to keep in mind that this is a company that manufactures and packages household products, so you can forgive me when the first thought was “wait, like, actual beep boop robots?”. Turns out no, not beep boop robots, but instead something called “RPA Robots”.
RPA stands for Robotic Process Automation and sounds a lot cooler than it actually is. Basically, RPA software suites (e.g. AutomationAnywhere or UIPath) enable employees to create “Robots”, i.e. scripts, to automatically perform some action for them. You could, for example, create a robot to take input from an email attachment, parse it, and have it input fields into a website from that attachment. RPA software is like someone slapping a GUI on top of a bunch of custom Python and Java libraries to make automation development simpler and quicker. It’s meant to shift the tedious time-consuming work to these robots instead of actual people.
So these robots were the “code” for the code review. No problem, a code review is a fairly straightforward process and we would have no problem completing one for this request. So we received the exported robot packages, which came as a .aapkg files.
AAPKG files are just zips:
So we unzipped, perused around, and repeated until we got every file. Several of the files, all named “commands”, had large Base64 data sections in an XML structure.
These “commands” files were by far the largest in their respective packages and we knew they probably contained the meat of the code since the rest of the files had supplementary details or metadata.
So we decoded the Base64 data and checked it out:
Well, that looks thoroughly unintelligible. Wonderful…So that means we’re looking at either:
Binary data format - Not nearly as common as it used to be, and you’d probably still see something that looks like semi structured data or text
Highly compressed - totally possible, but it would likely have a file type marker or some other indicator
Encrypted - extremely likely and common, the data would look very mathematically random
So let’s see if the data had any common file type markers in it, perhaps it follows a known format:
That’s a no. “data” is what the file command returns when it has no idea what it is. So let’s check how random the data is by calculating the entropy:
That’s some super random looking data. A Shannon entropy of 7.99 is extremely close to the theoretical maximum of 8. Encrypted data is supposed to look basically the same as completely random data. Experience has taught us that if you find Base64 data that has no file markers in it and has an entropy of of 7.5 or above, it’s highly likely to be encrypted data. Could it be something else entirely? Sure, but not usually.
Alright, so now we have reasonable suspicion that the meat of the robot code is encrypted in this exported package. Which makes perfect sense since companies love to advertise their data as “encrypted at rest” or use “military/bank grade encryption” to seem more appealing to customers. And if you look at the vendor’s marketing you’ll see what we mean:
Well, the problem with encryption is almost never the actual encryption. The problem is how you manage the encryption keys. Which begs the question, where is the key that encrypted this data?
We figured the laziest thing that the RPA software vendor could have done would be just to include the decryption key in the exported package files. We looked and found nothing, good for them. Interestingly, the package actually had no mention of encryption of any type. Now, it’s entirely possible this is a problem that has already been solved and posted online. Since we needed more information anyway for a better understanding, we started looking at online forums, support websites, and documentation for any clues. We found some clues from the RPA vendor’s documentation:
Now it’s important to remember that this is a very large and complex piece of software. We have no way of knowing if this documentation explicitly applies to our situation, but it does give you something to go off of. We now know we should prioritize looking for any mention of AES-256 (probably CBC) and RSA-2048, the two most common encryption methods. It’s likely the developers standardized on these encryption methods for ease of use and documentation.
But, we already looked for those and didn’t find anything in the package files. Maybe the key doesn’t come in the package file, maybe you have to supply it out of band and enter it manually when you import a robot. If that’s so, then there must be some interface or button or something asking the user for the decryption key. We looked at every document we could, but nothing showed up. We saw mention of inputting passwords to decrypt the file, but the wording made it seem like it was optional, and the client never provided a password. From our short testing and lots of document reading we gathered the following is true:
You can export robot code and it’s encrypted
There is no decryption key included in the exported package
You can import the package and don’t need to supply additional information
The two systems don’t talk to each other (as far as we could tell)
Once we realized that last bullet point, the “sploity sense” triggered and one possibility shot to the top of our “likely” list: a hardcoded crypto key. The only way two people can send symmetrically encrypted data (the AES-256 mentioned above) without ever sharing the key (in any way) is if both people already had the key, i.e. hardcoded. If that was true, then the key would likely be in the installation files for the RPA software. All we would need to do is get the install files, open them up, and start looking.
The install files are provided free to download from the vendor:
We started unpacking the large CAB files:
After grepping for various keywords (AES, RSA, PRIVATE KEY, etc), we got a hit for something interesting in a kernel.jar file. We opened the file using JD-GUI and look at what we found:
There it is. That’s the crypto key and initialization vector we need. We wrote a quick decryption tool and successfully decrypted the robot code to plaintext.
It looks like what we suspected earlier, that they use the same cipher in other components, turned out to be true. This means that any customer of AutomationAnywhere that exported a robot package may be at risk of the contents being leaked. While it was confirmed to exist in version 22 of the software, the documentation indicates the issue may go back all the way to version 8. We couldn’t confirm because AutomationAnywhere never responded to any of our emails.
Well that was a fun couple of hours. We were then able to begin the code review where we found several issues and provided the client a detailed report of remediation recommendations for the future development of their robots.
So that’s how you decrypt a robot.
The big take away is that cryptography is hard, but managing cryptographic keys is even harder. It’s also important to note that the vendor never technically lied. They do use “industry leading encryption”, and they do in fact encrypt their data at rest, but in the end it only slowed us by a couple of hours, simply because key management isn’t easy.
Software customers need to start understanding that encryption isn’t enough, that they need to start asking the vendors questions about how the encryption keys are handled. They can start by asking some basic questions like:
Is any data secured using default, hardcoded, or shared cryptographic keys or passwords? If so, what data?
Do I have the ability to change cryptographic keys or passwords? How?
Do any cryptographic keys or passwords leave the system for any reason? If so, what leaves, why? and how?
What other systems store, transfer, or process the cryptographic keys or passwords that my system relies on or uses?
Do I have the ability to revoke previous cryptographic keys or passwords and prevent them from impacting my system?
Regarding the vulnerability disclosure, over the course of several months we reached out multiple times to various contact emails at AutomationAnywhere to begin the disclosure process but never received any response.
