Food Store
“Food Store 😋…”
Introdução
Esta é uma resolução do desafio do Mobile Hacking Lab
onde descobri recentemente que eles estão oferecendo treinamento e laboratórios gratuitos para explorar e praticar suas habilidades de hacking mobile. Então, decidi fazer o curso e praticar os laboratórios.
Objetivo
Explorar uma vulnerabilidade de SQL injection, que permita que você se registre como um usuário PRO, ignorando as restrições de usuário padrão.
Writeup
Quando iniciei o aplicativo, criei um usuário e depois fiz login. Notei que meu usuário tinha 100 créditos e foi classificado como um usuário comum.
Primeiro, comecei a fazer engenharia reversa e abri o aplicativo usando o jadx-gui
.
AndroidManifest.xml
<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>
Não havia muito o que ver no arquivo AndroidManifest.xml - apenas três activities, e somente duas delas estavam exportadas.
O objetivo desse desafio é claro: registrar-se como um usuário PRO. Então, comecei examinando o processo singup para entender melhor como funciona o registro de usuários.
Percebi que o método addUser
na classe dbHelper
passa um objeto newUser
como argumento, então decidi investigar como o usuário está sendo criado.
Aqui está o trecho de código addUser
:
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();
}
As variáveis Username
, encodedPassword
e encodedAddress
estão concatenadas. Esse é um exemplo claro de SQL injection.
Coisas importantes a serem mencionadas:
- O único valor que pode ser controlado é o nome de usuário, pois essa variável não é codificada em base64.
- O último valor,
0
, está chumbado para indicar se o usuário é um usuário PRO ou não.
Payload
Durante a criação do payload, monitorei o logcat
em busca de mensagens de erro SQL. Como o aplicativo está definido como debuggable=“true”
, ele fornece informações mais detalhadas nos registros de log.
Quando tentei criar um usuário chamado SuperUser e adicionei uma aspa simples, recebi uma mensagem de erro nos logs.
Agora que entendi como a consulta está sendo construída, só preciso recriá-la para me registrar como um usuário PRO.
Para explicar melhor, aqui está uma comparação entre a consulta SQL e meu payload:
A consulta:
VALUES ('“ + Username + ‘’, ‘” + encodedPassword + “’, ‘” + encodedAddress + “’, 0);
Meu payload:
VALUES ('parad0x', 'MTIz', 'YWJj', '1'); --
Simplesmente adicionei uma aspa simples para fechar o campo de nome de usuário, incluí os valores codificados em base64 para a senha e o endereço, alterei o valor final de 0
para 1
para tornar o usuário um PRO e, em seguida, fechei a consulta e adicionei --
para comentar o restante da consulta original.
Meu usuário agora é PRO.
Bonus
Durante a engenharia reversa, também encontrei uma maneira de obter mais créditos e ter um usuário PRO “temporário” usando a Intent declarada dentro da LoginActivity e enviando os valores extras por meio do ADB.
Abaixo eu deixei um vídeo da PoC para a demonstração dessa execução!
Referências
Posts:
- Post Board parte 2
- Post Board parte 1
- Guess Me Parte 2
- Guess Me Parte 1
- Food Store
- IOT Connect
- UnCrackable L1 Parte 2
- UnCrackable L1 Parte 1
- CVE-2022-26352
- DCA php
- Docker Code Analyzer
- Vulnado Parte 3
- Vulnado Parte 2
- Vulnado Parte 1
- Damm Vulnerable WebSocket
- OWASP ZAP Zed Attack Proxy
- Estratégias de um code review
- O que é code review?