Hacking Mandated Apps – Part 6: XOR Crypto FAIL [ MSTG-CRYPTO-1 ]

This blog post series describes identified flaws in Smart Sheriff, a mandated app, see Intro for background. Please note this work was coordinated with human right activists, vulnerabilities reported to the vendor, etc. Previous blog posts you might have missed and maybe you would like to read first for background:

The OWASP Mobile Application Security Verification Standard classifies the flaw explained in this blog post, under section V3: Cryptography Requirements, as follows:

MSTG-CRYPTO-1: The app does not rely on symmetric cryptography with hardcoded keys as a sole method of encryption.

Detailed information and steps to test for this kind of issue can be found in the OWASP Mobile Security Testing Guide:

XOR crypto FAIL

The first time we tested Smart Sheriff, we found out that the app:

  1. Hardcoded an encryption key in its source code
  2. Used this to “protect” phone numbers and other device information in transit over the network ( maybe because there was no SSL at all? )
  3. The algorithm was basically to XOR the information to “protect” with the hardcoded key

This issue was found in the following file:

File:
kr/co/wigsys/sheriff/d/d.java

Affected Code (decompiled):
public static String a(String var0) {
var1_1 = new byte[39];
var1_1[0] = 109; //Bytes for the hardcoded key!
var1_1[2] = 111;
[…]
var1_1[38] = 107;
var2_2 = new byte[var0.getBytes().length];
try {
var2_2 = var0.getBytes();
var5_3 = 0;
var6_4 = 0;
do lbl-1000: // 2 sources:
{
if (var6_4 >= (var7_5 = var0.getBytes().length)) {
var4_7 = var2_2;
return new String(var4_7);
}
var2_2[var6_4] = (byte)(var2_2[var6_4] ^ var1_1[var5_3]);
var8_6 = var1_1.length;
if (++var5_3 < var8_6) ** break block6
var5_3 = 0;
break;
} while (true);
}
catch (Exception var3_8) {
var4_7 = var2_2;
a.a(String.valueOf(c.b()) + "cryptoCode", var3_8);
return new String(var4_7);
}

So, we put together a python script to encrypt / decrypt phone numbers during the test using this mechanism. XOR is nice because it allows you to encrypt and decrypt with the same code 🙂

Script usage example:

Command (Decrypt phone number):

python xor.py ‘]5Z\WSVAB5]’

Output:

05555215554

This finding corresponds to the first round of testing we did on Smart Sheriff, and the report explains that even if the key was somehow not hard-coded plain-text attacks would have still been possible, this is from the public report itself:

SMS-01-005 Insufficient cryptographic XOR Protection for sensitive Data (High)

The application “encrypts” data such as Phone numbers and device IDs with a simple XOR operation. This is insufficient to protect any of the encrypted entries. The key for this operation can either be easily reverse-engineered or extracted from the decompiled sources​ ​of​ ​the​ ​app,​ ​allowing​ ​an​ ​attacker​ ​to​ ​decrypt​ ​any​ ​of​ ​the​ ​protected​ ​data.

The example script below shows that even if the key is now known to an attacker, the cryptography in use by the app can be fully bypassed with the use of a simple and well-known​ ​plaintext​ ​attack.

Example​​ ​​Script:
XORdecrypt(“]5Z\WSVAB5]”)​​ ​​==​​ ​​’05555215554′
def​ ​XORdecrypt(s):
​ ​​ ​​ ​​ ​​abyte2​​ ​​=​​ ​​[109,​​ ​​0,​​ ​​111,​​ ​​105,​​ ​​98,​​ ​​97,​​ ​​103,​​ ​​116,​​ ​​119,​​ ​​0,​​ ​​105,​​ ​​103,​​ ​​115,
​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​121,​​ ​​115,​​ ​​116,​​ ​​101,​​ ​​0,​​ ​​109,​​ ​​115,​​ ​​102,​​ ​​105,​​ ​​103,​​ ​​104,​​ ​​116,​​ ​​0,​​ ​​105,
​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​ ​​​​110,​​ ​​103,​​ ​​104,​​ ​​104,​​ ​​104,​​ ​​107,​​ ​​0,​​ ​​107,​​ ​​107,​​ ​​107,​​ ​​111,​​ ​​107]
​ ​​ ​​ ​​ ​abyte0​ ​=​ ​[0​ ​for​ ​c​ ​in​ ​s]
​ ​​ ​​ ​​ ​abyte1​ ​=​ ​[ord(c)​ ​for​ ​c​ ​in​ ​s]
​ ​​ ​​ ​​ ​j​ ​=​ ​0;
​ ​​ ​​ ​​ ​k​ ​=​ ​0;
​ ​​ ​​ ​​ ​while​ ​True:
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​abyte0​ ​=​ ​[i​ ​for​ ​i​ ​in​ ​abyte1]
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​l​ ​=​ ​len(s)
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​if​ ​k>=l:
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​abyte0​ ​=​ ​[i​ ​for​ ​i​ ​in​ ​abyte1]
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​return​ ​””.join([chr(c)​ ​for​ ​c​ ​in​ ​abyte0])
else:
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​abyte1[k]​ ​=​ ​abyte1[k]^abyte2[j]
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​j+=1
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​abyte0​ ​=​ ​[i​ ​for​ ​i​ ​in​ ​abyte1]
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​l​ ​=​ ​len(s)
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​if​ ​j>=l:
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​j=0
​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​k+=1

This particular way of obfuscating important information again proves that the app was not conceived and written as secure or privacy-oriented endeavor. All “encrypted” information can be decoded trivially and allow any attacker to get hands on sensitive information​ ​and​ ​perform​ ​API​ ​calls​ ​to​ ​leak​ ​additional​ ​data.

Hack Smart Sheriff to pieces with us!

NOTE: Attendants will get lifetime access to our training portal with:
– Unlimited course updates & Step-by-step lab video recordings
Lots of real-world apps to practice with, such as:
  + Government-mandated and police apps in various countries
  + Many other excitingly vulnerable real-world apps!
  + IoT apps controlling Toys, Drones, etc.

Cannot make it? ping sales@7asecurity.com for training portal access.

Next blog post:

Hacking Mandated Apps – Part 7: AES Crypto FAIL [ MSTG-CRYPTO-1 ]