A flaw in how files are stored in Signal Desktop before 6.2.0 allows a threat actor to potentially obtain sensitive attachments sent in messages. Subsequently, a similar issue with Signal Desktop before 6.2.0 exists, allowing an an attacker to modify conversation attachments within the same directory. Client mechanisms fail to validate modifications of existing cached files, resulting in the ability to implement malicious code or overwrite pre-existing files and masquerade as pre-existing files. Local access is needed.
While using signal, it was observed that the preview of an image was still visible even after having deleted the image because the image had been “replied” to. After looking through multiple files, the culprit directory was identified.
To replicate, an image was sent in a group chat
The image was stored as a regular file in this directory, and the image can be recovered by modifying the extension and adding .png (on macOS and Linux you can see a preview of the native extensions so you don’t have to manually look at file properties)
This isn’t an edge case though, Signal is temporarily storing all of these attachments, unencrypted. Images were recovered from early 2022.
On this image in particular, you can see that the date is labeled as 10/26/2022.
Based on previous vulnerability research with Keybase, I then wondered if the image would properly get purged if I were to delete it. After deleting the file, it was indeed purged from the %AppData% folder. However, there was one small edge case: replying to the attachment. If someone were to reply to the attachment, the file would not be cleared from the cache, thus CVE number one: Cleartext Storage of Sensitive Information (CVE-2023-24069) was born. In general, the cache mishandling opens up a slew of issues. An adversary that can get their hands on these files wouldn’t even need to decrypt them and there’s no regular purging process, so undeleted files just sit unencrypted in this folder.
As displayed, the file was successfully recovered, even after being deleted (and basically the reason I went on this wild chase to being with).
When I discussed this vulnerability, several people had brought up the fact that Signal stores the decryption key on disk with the Desktop Client anyway. While true, this is just one less step to decrypt files, because…well you don’t have to decrypt them at all. The possible attack vector would be an adversary who already has local host access, looking to intercept your communications to recover secrets to pivot elsewhere in the environment or exploit external trust (such as passwords for third-party services).
The other possible risk could be foreign emissaries being wrongfully detained and forcefully searched. An adversary intelligence organization could pull the disk from a PC and take a snapshot, and recover all of these attachments, unencrypted. Again though, we return back to the fact that the Signal Desktop Client stores the encryption key on disk anyway (lol). Nonetheless, this vulnerability is another point of failure and makes it five times easier for unskilled adversaries to possibly recover sensitive information.
I wanted to ensure that this wasn’t specific to Windows, but being that the Signal Desktop Client has a shared codebase across operating systems, it probably wasn’t a Windows only vulnerability.
Navigating to the valid directory on Linux proved the same issues
Once again, the files were being stored in the cache, unencrypted. The same results were produced when the file was deleted but the attachment was previously quoted in conversation as well, confirming that the vulnerability exists across operating systems.
I still wasn’t satisfied though. I wanted to do something cooler than discuss a lack of encryption on files, and the ability to recover “deleted” files. After all, the people screaming about how this isn’t a vulnerability weren’t going to be appeased — as per usual.
Toying around with the client, I observed strange behavior. If I were to go in this /attachments.noindex/*/ folder, I could replace pre-existing sent attachments seamlessly. The client would automatically update it for me.
What you’re looking at is a set of three pictures. In picture number one, I identify the hacker pepe meme that I sent in a group chat, stored in a subdirectory within attachments.noindex — unencrypted, naturally. I named the german shepherd photo with the same value as the pepe meme, and overwrote it.
In picture number 2, you see that now when I try to download the pepe meme from the chat, it produces a picture of a german shepherd. Unfortunately that wasn’t enough to do anything. No one could see any updates to the attachment because everyone has a separate cache on their filesystem. HOWEVER. If you forward the attachment in another group chat or conversation, or the current one, Signal Desktop Client would now propagate the german shepherd rather than pepe which is what you thought you were forwarding.
Within itself, this is already its own vulnerability: CVE-2023-24068: Incorrect Resource Transfer Between Spheres. Amazing. Signal’s Desktop Client is not validating the existing file and it’s importing the new one without update any of the information or checking the file. Basically, it innately believes that the file is what it says it is. What we have here is the start of an attack chain.
Chaining CVE-2023-24069 with CVE-2023-24068 for fun and for Espionage
Up until this point we’ve established some key-operating knowledge:
- Signal isn’t purging the cache correctly, resulting in unencrypted media files being stored.
- When deleted, there are some cases in which the file is still able to be recovered.
- Images can covertly be swapped and replaced, resulting in a new image propagating when forwarding, or a new image being produced when downloaded.
It was at this moment that I realized the Signal Desktop Client was likely storing ALL attachments in this way, including documents, and then I realized what an actual intelligence operator might do. Why would someone want to replace the file with something different when you can just backdoor the existing file?
First, for the sake of this proof of concept, imagine that we get access to the host machine of a high priority target, i.e. a prominent member of ‘x’ organization, who constantly forwards attachments from one signal group to another. Within one of their Signal groups we see a PDF file called “EndYearStatement”.
We have this fake PDF file. Now to backdoor it. Navigating to the attachments.noindex folder on the victim’s machine, we make a copy of the file. Malicious shellcode or components can now be introduced to the file. Copying the file name, the PDF is overwritten with our PDF that looks like the victim’s original file (but with our malicious code). It should be noted that you have to use the same file extension, you cannot swap the file out for a different extension.
The victim will still see the the same filename and preview — but the malware that we introduced has overwritten it.
If we were trying to abuse this vulnerability to spy on an adversary or gain access to their organization/group’s host machines, this process would be most ideal in the circumstance that our target is the type of person who naturally forwards attachments. We can wait for them to forward the new attachment to their group chats, and we can sit in our C2 and collect new beacons as we abuse a trusted relationship. It’s silent and covert, with no pretext required so none of the victims would be aware that the attachment was compromised. Not even the person who sent the original attachment to begin with.
For the sake of this proof of concept though, this process needs some assistance. We forward the attachment to a different group chat.
As you can see, the attachment did indeed retain its properties. However, when the group it was forwarded to downloads the attachment, they will be served the malicious one. It’s vital to backdoor the existing attachment, rather than send a new one to reduce suspicion.
Did it work? Uhhh nope it didn’t.
Joking. It worked. You can see that the one line PDF of “Dummy PDF file” includes our revisions: