48 lines
3.7 KiB
Markdown
48 lines
3.7 KiB
Markdown
<h1 align="center">MongoPages</h1>
|
||
|
||
<p align="center">
|
||
<img src="https://img.shields.io/badge/category-Web-blueviolet" alt="Web"/>
|
||
</p>
|
||
|
||
MongoPages позволяет загружать файлы и выполнять JavaScript на сервере. Результат показывается в предпросмотре страницы как JSON с экспортами модуля. Флаг лежит в `/flag.txt`. Нужно прочитать его через серверный JS с учётом ограничений загрузки.
|
||
|
||
## Решение
|
||
|
||
Сначала собираем условия:
|
||
|
||
| Ограничение | Что оно меняет |
|
||
|---|---|
|
||
| MongoDB недоступна напрямую | Работаем через веб-интерфейс |
|
||
| `.js` не больше 100 байт | Нужен короткий модуль |
|
||
| Запрещены подстроки `flag` без учёта регистра и `../` | Собираем путь вычислением |
|
||
| Ошибки скрыты за `Evaluation failed` | Выводим результат через exports |
|
||
| Страницы приватные | Открываем preview со своей сессией |
|
||
|
||
Платформа выполняет загруженный модуль через серверный JavaScript MongoDB. В конфигурации задания загрузчик MozJS разрешает динамический `import()` по абсолютному пути и не проверяет расширение файла.
|
||
|
||
В задании `/flag.txt` хранится как ES-модуль с именованным экспортом `flag`. Значение пока неизвестно, но формат подсказывает канал чтения: импортируем файл и забираем свойство namespace-объекта. Фильтр смотрит на исходный текст, поэтому разбиваем запрещённое слово в пути и имени свойства. Сохраняем код в `pwn.js`.
|
||
|
||
```js
|
||
export const x=(await import("/"+"fl"+"ag.txt"))["fl"+"ag"];
|
||
```
|
||
|
||
Это 60 ASCII-байт без завершающего перевода строки — меньше лимита. Подстрок `flag` и `../` в исходнике нет.
|
||
|
||
`await` на верхнем уровне нужен для порядка выполнения. Платформа читает exports после завершения импорта загруженного модуля. К этому моменту вложенный импорт уже закончится и `x` получит нужное значение.
|
||
|
||
Регистрируемся через `POST /register`, передавая `username` и `password` как поля формы, затем входим через `POST /login` с теми же данными и отправляем `pwn.js` на `/upload` в multipart-поле `file`. Затем открываем `/pages/<username>/` со своей cookie. В секции серверного выполнения появляется:
|
||
|
||
```json
|
||
{"x":"m0zjs_w4f_byp4ss"}
|
||
```
|
||
|
||
Оборачиваем значение в формат флага.
|
||
|
||
Можно также вынести код в `h.txt`, а из маленького `.js` сделать `export * from "/var/www/pages/<username>/h.txt";`. Лимит для `.txt` — 64 КБ, загрузчик расширение не проверяет. Но фильтр подстрок действует на все файлы, поэтому разбивать `flag` всё равно придётся.
|
||
|
||
[Солвер](solve/solve.py).
|
||
|
||
## Флаг
|
||
|
||
`caplag{m0zjs_w4f_byp4ss}`
|