Reverse-Engineering an IP camera - Part 6

In the previous articles we saw some security vulnerabilities related to the camera operation and now I'm interested on using them to find a way to replace the camera software with my own-version of the IPC.

The camera contains an update function that allows it to check online for new software versions and update itself. Fortunately for the users (and unfortunately for me), the camera only accepts encrypted software update packages, so I'm not able to simply upload my own modified version of the camera software.

As demonstrated in Part 3, the camera includes a decrypter software, which is used by the update function to decrypt the received update package. Since I have root access to the camera shell, I can use this program, rsa_dec, to decrypt a package downloaded from the manufacturer server, but I cannot use it to encrypt, because the encryption function is not included in the program. The manufacturer must use a second program for encryption.

The decryption process expects a file with the extension ".bin.enc", and produces a file with extension ".bin". The update script indicates this binary file is created by simply joining three other files:

  • payload.bin: A squashfs file containing the new software to be installed.
  • payload.md5: Contains only a MD5 hash of the payload.bin, used to check its integrity after decryption.
  • bootloader.sh: A shell script that is called after the decryption and stores the squashfs payload.bin in the correct position in the camera flash memory.

So, in order to create my own modified version of the software, I need to:

  1. Create a new version of IPC.
  2. Use squashfs-tools to create a new payload.bin.
  3. Calculate the payload.bin MD5 and store in a second file.
  4. Join these two files with the original payload.sh into a single binary file.
  5. Encrypt this single binary file.
  6. Find a way to send this file to the camera.

Diving in the camera file system I was able to find the private key used to decrypt files:

aaA

The naming used for both the program (rsa_dec) and the key (keyrsa) suggests that the camera uses an RSA encryption method, so I would need a public key, which is not available inside the camera. Besides that I also need to understand the format of the encrypted file, and other encryption parameters used in the process. So, my best approach would be to decompile rsa_dec too.

I launched Ghidra again, but this time it was a painful job. Encryption algorithms use a lot of high-level calculations that, once converted to assembly, make the code too hard to understand, unless you're experienced with implementing these algorithms. I'm pretty sure there are people out there that can identify an RSA algorithm by just overseeing some MIPS mnemonics, but that's not my case. It made me want to give up several times.

Until I noticed that an error log function inside the code was receiving some interesting information: Again, the developer left some very useful information regarding the source-code: the .c file name and the function name:

sasas

With a few Google searches I ended up in the GitHub repository of the original rsa_dec developer. Now I had not only full access to the rsa_dec source code, but also to the encrypter program, rsa_enc!

I downloaded the full project, searched for that function name and found the exact line of code that was providing the debug information I saw in the decompiler:

dsasd

(By the way, I'm very suspicious that  the camera developer disrespected the rsa_dec open-source licensing by not including the licensing along with the binary.)

dsds

Back to the code, I've managed to successfully build it with gcc and finally I had the same encryption program used by the camera developer, and also the private key. I just need now to extract the public key from the private key and I would be able to encrypt my alternate version of the camera software.

However, things are never easy in the world of reverse engineering embedded systems. The rsa_dec and rsa_enc use proprietary file format for both the key and encrypted files, so I would not be able to use other tools like openssl to generate the public key. I would have to analyze the rsa_dec code to understand the key file format, then extract it to a format supported by openssl, generate the public key, then create a script to store it in the rsa_dec format. Too complicated...

But I realized something: RSA is not the best method for encrypting a large file like this software update (Almost 2 Mb). The rsa_dec performance would suck when doing that inside a low-cost hardware as the one used in the camera. Maybe rsa_enc is not encrypting the whole file, and that could be a vulnerability waiting to be exploited.

And it was exactly what happened. The rsa_enc provides two encryption methods: "Full" and "quick". With the "quick" method, which is the one used by the camera, only the file header is encrypted with RSA. In this header, the rsa_enc stores a numeric seed for a pseudo-random number generator. The rest of the file is encrypted by simply XORing the original file with random numbers generated with the encrypted seed, as depicted in the next image:

qwewqe

And that's a vulnerability, because, if I know the seed, I can encrypt the file by XORing it myself. And I can get the seed from the original file by running rsa_dec on a debugger.

Also, since the header doesn't change for the same seed and same public key, I can simply copy the header bytes from the manufacturer encrypted file and use it in any of my own files. Voila! I'm now fully able to create my own counterfeit IPC and send it to the camera and it will be smoothly installed:

EWE

So, I edited the original IPC software to change the address of the hard-coded servers it connects to. Rather than connecting to the manufacturer servers, my forged IPC version will try to connect to the world-famous website www.pudim.com.br.

Having physical access to the camera would make this attack very simple now: I just need to put the encrypted file in a SD card, insert the card in the camera and reset it. The camera auto-updates itself if it finds an update software package when restarting.

But to make this attack even more effective, it should require no physical access to the camera. So I created a simple HTTP server in Python to simulate the camera update server, and used DNS spoofing to redirect the camera update requests to my computer instead of the actual server. This preparation would allow any person to replicate this forged update attack once connected to the same local network as the camera.

Here's a video demonstrating this attack: