Реальная реальность Write-up | Tinkoff CTF 2024

Ссылка на задание https://ctf.tinkoff.ru/tasks/rreality

Автор задания: Даниил Фукалов (@denciks),  SPbCTF

Сотрудники пришли на совещание в шлемах виртуальной реальности. Они никого не слушают и тайком что-то смотрят. Узнайте, что именно.

Приложение: rreality_879996x.apk

Устанавливаем приложение на эмулятор и запускаем. Нас встречает минималистичная форма входа и регистрации. Создаём аккаунт и входим. Admin уже начал с нами диалог и отправил ссылку на YouTube.

Диалог с админом

Диалог с админом

Проваливаемся в диалог.

Rickroll

Rickroll

Помимо любви админа к мемам, замечаем важную деталь, что отправленная им ссылка отобразилась не только как текст, а ещё и в виде встроенного плеера. При нажатии на видео оно воспроизводится прямо в диалоге. Отсюда понимаем, что имеем дело с WebView. Также, это легко заметить, если декомпилировать приложение и посмотреть что представляет из себя код MainActivity.

package com.spbctf.messenger;

import android.os.Bundle;
import android.webkit.WebView;
import androidx.activity.ComponentActivity;
import androidx.activity.compose.ComponentActivityKt;
import kotlin.Metadata;

public final class MainActivity extends ComponentActivity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WebView.setWebContentsDebuggingEnabled(true);
    }
}

Замечаем, что разработчик заботливо оставил для нас включенным инструменты отладки веб-вью компонента. В Google Chrome на компьютере переходим в chrome://inspect и анализируем исходники.

Приложение в инструменте отладки веб-вью

Приложение в инструменте отладки веб-вью

Анализируя JavaScript код или методом тыка, замечаем что, если сообщение содержит текст youtu.be, то приложение считает, что нам отправили ссылку на видео и преобразует его в iframe со встраиваемым плеером:

c = "youtu.be" ...
children: [t.message, t.message.includes(c) && (0, ...
n.jsx)("iframe", {src: t.message.replace(c, "youtube.com/embed/"),

В голову приходит идея отправить сообщение админу со ссылкой на вебхук, в котором в URL будет содержаться youtu.be (обычные вебхуки уже были проверены на этапе метода тыка и они не срабатывали). Отправляем админу нашу ссылку:

https://webhook.site/your_token_key?hey=https://www.youtu.be/watch?v=Dm8gSDnnpbE

На момент написания статьи, похоже, админ уже перестал ходить по ссылкам (или что-то сломалось), но во время CTF можно было увидеть, что админ сходил по ней.

Отлично, теперь нужно придумать как эксплуатировать это.

Во время анализа декомпилированного кода приложения или JavaScript кода в хроме можно было заметить, что из натива в веб пробрасываются три метода:

package com.spbctf.messenger.js;

import android.webkit.JavascriptInterface;
import com.spbctf.messenger.session.SessionController;
import com.spbctf.messenger.ui.MainViewModel;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;

public final class JsApiProd implements JsApi {
    private final MainViewModel mainViewModel;
    private final SessionController sessionController;

    public JsApiProd(SessionController sessionController, MainViewModel mainViewModel) {
        Intrinsics.checkNotNullParameter(sessionController, "sessionController");
        Intrinsics.checkNotNullParameter(mainViewModel, "mainViewModel");
        this.sessionController = sessionController;
        this.mainViewModel = mainViewModel;
    }

    @Override // com.spbctf.messenger.js.JsApi
    @JavascriptInterface
    public String getSession() {
        return this.sessionController.getSession();
    }

    @Override // com.spbctf.messenger.js.JsApi
    @JavascriptInterface
    public String getUsername() {
        return this.sessionController.getUsername();
    }

    @Override // com.spbctf.messenger.js.JsApi
    @JavascriptInterface
    public void logout() {
        this.mainViewModel.logout();
    }
}

То есть в JavaScript коде можно вызвать native.getSession() и вызов передастся в нативную часть приложения (на Kotlin), которая отдаст обратно в веб идентификатор сессии. Такого рода приложения называются гибридными.

Так как iframe обрабатывается тем же WebView, что и основной веб-код, то и для него доступны обращения к этим нативным методам.

Пишем простейшую html страницу с кражей сессии:


  
    
  
  
  











Размещаем html у себя на хостинге или в Firebase и отправляем ссылку админу. Моя ссылка выглядела примерно так:

https://my-demo.web.app/office?q=https://www.youtu.be/watch?v=Dm8gSDnnpbE

Репортим флаг и продолжаем попытки решить задачу с мемотавром!

© Habrahabr.ru