В этой небольшой статье, в рамках прохождения уязвимой виртуальной машины Format с площадки Hack The Box, я покажу, как повысить привилегии путем эксплуатации уязвимости f-строки в Python.
Еще по теме: Атака на API веб‑приложения Django
Эксплуатация уязвимости f-строки в Python
Для начала получим информацию о системе. Я буду использовать для этого скрипты PEASS.
Загрузим на хост скрипт для Linux, дадим право на выполнение и запустим сканирование. В выводе будет много информации, смотрим самое интересное.
Настройки sudoers доступны только при вводе пароля.
Видим несколько файлов, в том числе исполняемых, которые добавлены в систему пользователем.
Больше ничего интересного.
Так как мы знаем пароль пользователя, все‑таки проверим настройки sudoers.
1 |
sudo -l |
Оказывается, мы можем запустить приложение /usr/bin/license от имени пользователя root.
Проверим тип файла с помощью утилиты file.
1 |
file /usr/bin/license |
Это скрипт на Python. Смотрим его исходный код в любом удобном редакторе. Это приложение может быть запущено только привилегированным пользователем (строки 22–26). Затем приложение читает секрет из файла /root/license/secret, а из секрета формируется ключ шифрования (строки 37–43).
Затем приложение получает данные из базы Redis и открывает файл с ключами лицензии /root/license/keys (строки 48–61).
Следом из базы Redis читаются параметры username, first-name и last-name, которые вместе с содержимым лицензии выводятся пользователю (строки 62–78).
При выводе используется f-строка (строки 65 и 69). Так как через базу Redis мы можем контролировать входные данные, попробуем в качестве одного из параметров записать такую строку:
1 |
{license.__init__.__globals__[secret_encoded]} |
Она должна будет вывести секрет!
1 2 |
redis-cli -s /var/run/redis/redis.sock HMSET ralf first-name "{license.__init__.__globals__[secret_encoded]}" last-name ralf username ralf |
Теперь запускаем приложение, указывая созданный ключ ralf, и ищем в выводе секрет.
1 |
sudo /usr/bin/license -p ralf |
Полученный секрет пробуем применить в качестве пароля рута. Пароль подходит, забираем флаг.
Машина захвачена!
Защита от уязвимости f-строки в Python
Уязвимость f-строки в Python может возникнуть, если вставка переменных в строку не происходит безопасно. Это может привести к проблемам с безопасностью, таким как инъекции.
Чтобы обезопасить использование f-строк и избежать уязвимостей, следует следовать следующим правилам:
1. Не вставляйте данные, которые могут быть введены пользователем напрямую в f-строку. Это может привести к SQL-инъекциям и другим атакам. Не делайте так:
1 2 |
user_input = input("Введите что-то: ") f_string = f"Привет, {user_input}!" |
2. Используйте функции форматирования, которые обеспечивают экранирование значений, такие как `html.escape` для HTML-строк или параметризированные запросы для баз данных. Пример с экранированием HTML:
1 2 3 4 5 |
import html user_input = input("Введите что-то: ") safe_input = html.escape(user_input) f_string = f"Привет, {safe_input}!" |
3. Если вставляете переменные, удостоверьтесь, что они имеют ожидаемый тип данных. Избегайте автоматических преобразований. Пример:
1 2 |
number = 42 f_string = f"Число: {number:d}" # d - ожидаемый формат для числа |
4. Используйте f-строки только с данными, которые вы контролируете и которые можно считать надежными.
Эти простые правила помогут избежать уязвимостей при использовании f-строк в Python.
ПОЛЕЗНЫЕ ССЫЛКИ: