Brief us your requirements below, and let's connect
1101 - 11th Floor
JMD Megapolis, Sector-48
Gurgaon, Delhi NCR - India
1st floor, Urmi Corporate Park
Solaris (D) Opp. L&T Gate No.6
Powai, Mumbai- 400072
#12, 100 Feet Road
Banaswadi,
Bangalore 5600432
UL CyberPark (SEZ)
Nellikode (PO)
Kerala, India - 673 016.
Westhill, Kozhikode
Kerala - 673005
India
In this article, we present the general concepts behind a proactive protection mechanism (sentinel RASP) for mobile banking application development.
We provide several concrete examples and we offer an insight view, using a C# test project.
Table of Contents
Here we demonstrate the features of a sentinel system in a mobile context. This system might also be referred to as Runtime Application Self-Protection or simply RASP.
A sentinel system is a background process that is usually not easily detectable. It monitors “in real-time” several parameters associated with the mobile operating system and the applications it protects.
For instance, a sentinel could detect attempts to use an emulator or a debugger. It could also check the integrity of files and scan the memory (flash, RAM, EEPROM) for viruses. A sentinel would have two parts: a “detector” part and a “reactor” part. The detector would signal that it detected possible attempts to attack the application while a reactor would take the proper decision following that information.
In what follows, we will create a small sentinel system, acting as concept proof to concretely illustrate how such a system would work.
To develop a rapid test mobile application, we shall use visual studio 2008. We will develop a small application in C# for windows phones. Of course, we could develop the same test application for Android or Ios using Xamarin but our application is only created for the purpose of demonstrating the concepts of sentinels.
Our “banking application” will have a log in button with a username and password.
Our small banking imaginary application allows sending directly money to any VISA or MASTERCARD credit card from a funding credit card which has been previously registered and loaded to a remote server.
The program will hash the password using a complicated function taking as input the username, hashed password, and the IMEI of the mobile phone, then send some ciphered data to a remote server, get a ciphered response and then returns to the caller a one-time authorization code acting as a symmetric key K1. Once authenticated, the application offers to transfer money to an account. The application will sign the transaction data using its private key K2, append the signature to the transaction data and cipher the whole thing using the one-time symmetric key K1.
The application will send the following banking transaction data:
Here we explain the meaning of the different parameters.
Parameter | Meaning |
TIMESTAMP | Timestamp computed when the application generates the data |
USERNAME | Username of the user of the application |
HASHED_PASSWORD | the hashed password of the user |
IMEI | The mobile phone IMEI |
AMOUNT | Amount of the transaction in U.S dollars |
CARD_RECIPIENT | The 16 digits of the recipient’s credit card |
DATE_EXP_RECIPIENT | The expiration date of the recipient’s credit card |
CVV_RECIPIENT | The CVV of the recipient’s credit card |
FIRSTNAME_RECIPIENT | The first name of the recipient’s credit card |
LASTNAME_RECIPIENT | The last name of the recipient’s credit card |
FUNDING_CARD_TOKEN | A token representing the sender’s funding credit card, registered in a token vault |
Our goal is to demonstrate how an attacker can break the security of such a protocol and how sentinels can prevent this attacker to do so.
This “imaginary” protocol is not so uncommon as many developers clearly lack serious IT security culture and create often homebrew solutions, especially in the Android world. Rather than asking developers to re-write the application, the sentinels prevent and protect actively that banking application.
alsoRead
We will use, as we mentioned earlier, Visual Studio 2008 and the smart Device development kit. We also will need the windows mobile 6 SDK.
We create a new project in Visual 2008.
Of course, the windows mobile 6 is no longer actively supported on actual smartphones and mobile devices – since support from Microsoft stopped in 2013 – but we wish only to present the concept proof of the sentinel. Besides Windows mobile, version 10 is still present on the market – as of 2019 – with the Lumia phones.
We develop the front-end screens with the fields for the username and the password.
We develop the application by making sure most of the essential functions are coded.
Of course, we lack code quality, we do not control the input from the user and we even do not catch exceptions!
Here is how the test program will work:
The username and password are entered, the password is hashed and sent to a third party library which will contact an authorization server.
String Username = textBox1.Text;
String Password = textBox2.Text;
parameters.username = Username;
String hash_password = Utils.Hash_password(Username, Password);
parameters.hashed_password = hash_password;
//generate access code to DLL
Int32 code = GenCode.GenerateNewCode();
The main form can access the third party protected dll only by generating a one-time code.
That one time-code uses common counter between the DLL and the caller and generate the code as such:
//generate the one time secret
static public Int32 GenerateNewCode()
{
Random r = new Random(counter);
for (int i = 0; i < counter; i++)
{
secret = (Int32)((secret * r.Next()) % 100.000);
}
counter++;
return secret;
}
The Dll is equipped with a few protection against bruteforcing and disable access after a certain amount of unsuccessful attempts. Only that Dll may contact the authorization server.
The dll will then do supposingly some tricky operations and contact the authorization server to receive back the one-time code that will generate the transaction 3DESkey.
Here is the way it is processed on the (stub) bank server, which we represent by a separate dll, StubTestBankServer.dll:
public static long getAnswerfromServerAuthCode(string username, string hash_password)
{
//we should validate plenty of things
//we simply verify that user and password matches our files
//here there is but just one user in bank!
if(username.Equals("hitchcock7"))
{
//password= !!32!book!DECIDED!
String res= Utils.Hash_password("hitchcock7","!!32!book!DECIDED!");
if(res.Equals(hash_password))
{
return getAnswerfromServerAuthCode();
}
return 0;
}
return 0;
}
The transaction 3DES key K1 is computed very basically by taking the MD5 hash of the number of CPU ticks at the current date-time.
Then the user is authenticated and can access the transaction screen.
The form will gather the data from the user and build the transaction flow.
It will compute the IMEI as a security measure so to check the application is not been used on a non-authorized phone as the server as a list of registered phones.
public static String getIMEI()
{
IntPtr hSim = IntPtr.Zero;
byte[] iccid = new byte[10];
int zero = 0;
SimInitialize(0, IntPtr.Zero, 0, ref hSim);
SimReadRecord(hSim,
EF_ICCID,
SIM_RECORDTYPE_TRANSPARENT,
0,
iccid,
(uint)iccid.Length,
ref zero);
SimDeinitialize(hSim);
string serial = FormatAsSimString(iccid);
return serial;
}
The program uses a static KEK key which is the same for all phones because it is hardcoded in the program.
That KEK is used to access 3DES ciphered files located in the temp folder of the phone and containing a unique RSA private key split into components. These files are 3DES ciphered so the private key is supposed to be protected.
This is how they are retrieved by the application:
public static byte[] getRSAKey(keycomponent comp)
{
//read it from the 'database'
//decipher the key
TripleDES tdes = TripleDESCryptoServiceProvider.Create();
//get our 3DES key
tdes.Key = GenerateThreeDESKeyFromKey(parameters.KEK);
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
StreamReader sr = File.OpenText("\\temp\\KEY" + comp + ".cipher");
String cipher = sr.ReadLine();
sr.Close();
byte[] ciphered = Utils.StringToByteArray(cipher);
byte[] decipher = tdes.CreateDecryptor().TransformFinalBlock(ciphered, 0, ciphered.Length);
tdes.Clear();
return decipher;
}
Concretely the form will have to call the getRSAKey function for all the key components:
public class RSACipher
{
private static RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider();
private static System.Security.Cryptography.RSAParameters rsaparams = new System.Security.Cryptography.RSAParameters();
public static void LoadKeys()
{
rsaparams.P = Utils.getRSAKey(keycomponent.P);
rsaparams.Q = Utils.getRSAKey(keycomponent.Q);
rsaparams.Exponent = Utils.getRSAKey(keycomponent.E);
rsaparams.Modulus = Utils.getRSAKey(keycomponent.MODULUS);
rsaparams.D = Utils.getRSAKey(keycomponent.D);
rsaparams.InverseQ = Utils.getRSAKey(keycomponent.InverseQ);
rsaparams.DP = Utils.getRSAKey(keycomponent.DP);
rsaparams.DQ = Utils.getRSAKey(keycomponent.DQ);
rsa.ImportParameters(rsaparams);
}
Finally, the application uses the private key to sign the transaction data which are sent to the remote server ( in fact our stub server – dll)
Here is an example of the transaction flow sent to the server:
In clear:
Ciphered with signature added at the end:
As we see the application has some non-trivial protection mechanism.
When received by the remote server, the data will be first separated and deciphered by the transaction 3DES key.
The transaction key is supposed to be checked for its freshness. It cannot be used for a replay attack because it can be used only once.
The transaction data are hashed and compared with the signature:
byte[] b_signature = Utils.StringToByteArray(signature);
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
byte[] h_data2 = sha1.ComputeHash(dc);
RSACipher.LoadKeys();
bool result_ = RSACipher.Verify(h_data2, b_signature);
if(result_==false)
return bank_transaction_code.INCORRECT_DATA;
The token is retrieved from a card vault to get the card data using a stub:
credit_card funding_card = Utils.GetCardFromVault(tk);
Finally, we simulate an authorization to a credit card processor.
//simulation of an authorization request to the card processor
private static bool AuthorizeTransaction(credit_card funding_card, credit_card receiver_card, int sum, string fn_, string ln_)
{
//simulating money available on card
if (sum > new Random().Next(5000))
return false;
return true;
}
Now that we have our test banking application, the fun is just beginning!
In the next part, we will demonstrate how sentinels can prevent attackers to perform malevolent transactions. You can know whether you need RASP for application security.
Acodez is a leading website design and software development company in India. We offer all kinds of web design and web development services to our clients using the latest technologies. We are also a leading digital marketing company providing SEO, SMM, SEM, Inbound marketing services, etc at affordable prices. For further information, please contact us.
Contact us and we'll give you a preliminary free consultation
on the web & mobile strategy that'd suit your needs best.
Leveraging AI for Automated Code Refactoring in Web Development
Posted on Nov 28, 2024 | Web DevelopmentAdvanced Content Delivery Network (CDN) Strategies for Global Web Performance
Posted on Oct 31, 2024 | Web DevelopmentWebAssembly In Modern Web Development: How It Can Revolutionize Web Performance
Posted on Oct 17, 2024 | Web Development