Reverse engineering, Windows internals, x86 magic, low level programming, and everything else I feel like writing about.

CrySyS SecChallenge 2020: AuthentIoTicator

Our dearest betatesters!

As probably almost all of you know, we’re one of the fastest growing startup company in our days. Since I started to write these words, we hired about 4 people. Yeah, we’re that fast.

However, every company has a management team, and ours has decided that it is time for us to jump into the IoT market, and make us even bigger. Our duty is to create an open source Authentication framework, that anyone can use to safely and securely authenticate their users. Our best software developers worked hard to create this platform, and they say it’s bulletproof. They have so much confidence that indeed this code which you can download from our repo has already been shipped within several smart fridges, IP cameras, smart lamps and so on, due to our preorder deal, which sold really well.

Our primary target was the ESP32 platform, especially the NodeMCU-ESP32s device, programmed with the Arduino IDE. Since Arduino is wide spread, and the ESP32 chip has a robust core (ESP32duino) for it, we could reach more people by making it this way.

But as all things this project should also move on, so since we’re trying to release and abandon this project, we thought we would invite a few betatesters to make sure it is as bulletproof as our developers says it is. We really hope that you don’t find any issues with it, because we don’t really have any idea how could we update about 460000 devices already sold in the market with this software.

Looking forward for your results.

Sincerely, SafeCorp

*Side note: No hardware is needed in order to solve this challenge.

Categories

Hardware, Arduino, ESP32duino

Files

Solution

Looking at the files in the zip, we can easily notice Defines.h has some interesting defines:

#define MASTER_JWT_PAYLOAD "{\"role\":\"admin\",\"magic_values\":\"19ded1378d19776b57187e8db221d79fefdb6acd6877f9627e71c6b3c47f175c181814bacde36302ee7bf894ca8ce05cf24fceb6410ee105a84bdf5e0b49bfe20d03\"}"
#define FLAG_BASEVALUES "7abae307f64d05321e7639d2807ea0cddeaf599231478c30211e91dd9b4b6208502b7aeefc805776df4bb6cbfbffbf32c21b9185007db85a9c0dab6d59168b8e417e"

When checking where they’re used, we see this code in AuthentIoTicator.ino:

  String seed = jwtPayload.substring(jwtPayload.indexOf("\"magic_values\":\"") + 16, jwtPayload.length());
  seed = seed.substring(0, seed.indexOf("\""));
  
  int seedLength = seed.length();
  char seedConvertedToInt[seedLength / 2];
  convertCharArrayContainingHexaValuesAsASCIIToByteArray(seed.c_str(), seedLength, seedConvertedToInt);
  
  char flagBasevaluesConvertedToInt[seedLength / 2];
  convertCharArrayContainingHexaValuesAsASCIIToByteArray(FLAG_BASEVALUES, seedLength, flagBasevaluesConvertedToInt);
  
  String responseString = "<html><body><h2>Welcome back, Admin!</h2><p>Your entry code for today is: ";
  
  for (int i = 0; i < seedLength / 2; i++) {
    responseString += (char)(seedConvertedToInt[i] ^ flagBasevaluesConvertedToInt[i]);  
  }
  
  responseString += "</p><p>Hope you have a good day, please be sure to leave a feedback to our new super cool Auth system!</p></body></html>";
  
  makeResponse(clientRequest, 200, responseString);

Let’s try doing that xoring ourselves:

const uint8_t k_magic[] = { 0x19, 0xde, 0xd1, 0x37, 0x8d, 0x19, 0x77, 0x6b, 0x57, 0x18, 0x7e, 0x8d, 0xb2, 0x21, 0xd7, 0x9f, 0xef, 0xdb, 0x6a, 0xcd, 0x68, 0x77, 0xf9, 0x62, 0x7e, 0x71, 0xc6, 0xb3, 0xc4, 0x7f, 0x17, 0x5c, 0x18, 0x18, 0x14, 0xba, 0xcd, 0xe3, 0x63, 0x02, 0xee, 0x7b, 0xf8, 0x94, 0xca, 0x8c, 0xe0, 0x5c, 0xf2, 0x4f, 0xce, 0xb6, 0x41, 0x0e, 0xe1, 0x05, 0xa8, 0x4b, 0xdf, 0x5e, 0x0b, 0x49, 0xbf, 0xe2, 0x0d, 0x03 };
const uint8_t k_flag[] = { 0x7a, 0xba, 0xe3, 0x07, 0xf6, 0x4d, 0x05, 0x32, 0x1e, 0x76, 0x39, 0xd2, 0x80, 0x7e, 0xa0, 0xcd, 0xde, 0xaf, 0x59, 0x92, 0x31, 0x47, 0x8c, 0x30, 0x21, 0x1e, 0x91, 0xdd, 0x9b, 0x4b, 0x62, 0x08, 0x50, 0x2b, 0x7a, 0xee, 0xfc, 0x80, 0x57, 0x76, 0xdf, 0x4b, 0xb6, 0xcb, 0xfb, 0xff, 0xbf, 0x32, 0xc2, 0x1b, 0x91, 0x85, 0x00, 0x7d, 0xb8, 0x5a, 0x9c, 0x0d, 0xab, 0x6d, 0x59, 0x16, 0x8b, 0x8e, 0x41, 0x7e };

int main()
{
  for (auto i = 0u; i < 66; ++i)
    printf("%c", k_magic[i] ^ k_flag[i]);

  return 0;
}

Output:

cd20{REDACTED}