Огляд коду
PumpkinSpice — це додаток на Flask з маршрутами, які спеціально розроблені для локального доступу. Він імітує ситуації, коли адміністративні функції обмежені лише локальними мережами або певними хостами. Крім того, він включає функціональність бота, який симулює перегляд усіх "адрес", поданих через додаток, адміністратором.
У таких задачах, як ця, імітація дії користувача часто вказує на наявність вразливості Stored XSS у додатку. Тепер давайте розглянемо шаблони.
Addresses:
{% for address in addresses %}
{{ address|safe }}
{% endfor %} ``` У файлі `addresses.html` фільтр Jinja `safe` застосовується до кожної адреси, що дозволяє рендерити дані як HTML, створюючи точку ін'єкції XSS.
З цією вразливістю XSS, давайте тепер пошукаємо ще одну вразливість, яку можна об'єднати з нею.
app.py
@app.route("/api/stats", methods=["GET"])
def stats():
# код опущено для зручності
command = request.args.get("command")
if not command:
return render_template("index.html", message="Не вказано команду")
results = subprocess.checkoutput(command, shell=True, universalnewlines=True)
return results
```
У файлі app.py
маршрут /api/stats
приймає параметр command
, який виконується за допомогою модуля subprocess
. Без будь-якої фільтрації, це робить додаток вразливим до Command Injection (ін'єкції команд).
Ми виявили дві критичні проблеми в додатку. Тепер давайте протестуємо додаток локально, щоб підтвердити наявність вразливостей і розглянути, як їх можна використати разом.
Локальне тестування
Після того, як ми запустимо додаток локально за допомогою скрипту build-docker.sh
, давайте надамо наступний пейлоад у поле вводу адреси.
Це створить файл proof.txt
у папці static, до якого ми зможемо отримати доступ через HTTP, щоб перевірити його успішне створення.
Тепер, коли ми підтвердили, що можемо виконувати системні команди, експлуатуючи вразливість XSS і відсутність фільтрації на адміністративних маршрутах, давайте запустимо інстанс Challenge і захопимо прапор.
Експлуатація
Ми змінимо пейлоад, який використовувався для створення proof.txt
у нашій локальній Docker-інстанції, щоб замість цього скопіювати прапор з кореневої директорії в папку static додатка.
Ми використали wildcard (шаблон) тому, що ім'я файлу з прапором було змінене у скрипті entrypoint.sh
під час запуску додатка.
Хоч ми і не знаємо точне ім’я файлу з прапором, але ми знаємо, що воно починається з "flag".
Тепер давайте отримаємо прапор за допомогою команди curl
.
Нам вдалося успішно захопити PumpkinSpice!
Джерела
- https://jinja.palletsprojects.com/en/stable/templates/#jinja-filters.safe
- https://flask.palletsprojects.com/en/stable/quickstart/#static-files
- https://owasp.org/www-community/attacks/xss/
- https://owasp.org/www-community/attacks/Code_Injection
- https://owasp.org/www-community/attacks/Command_Injection
Перекладено з: HTB Challenge Write-Up: PumpkinSpice