На днях попался прекраснейший разбор уязвимости CVE-2025-27363 в системной библиотеке для показа шрифтов FreeType, которая в том числе используется в Android и её применение в WhatsApp. Мне кажется, это очень красивый эксплойт.
Пусть меня исправят профессиональные reverse-инженеры, если я спутал детали, но кратко она работает так.
Внутри многих PDF содержится собственный шрифт. Это стандартная практика: PDF на то и PDF, чтобы он выглядел максимально одинаково на разных устройствах.
В WhatsApp у многих пользователей включено превью показа PDF-документов, и в момент его создания библиотека FreeType начинает обрабатывать этот шрифт.
Дальше начинается магия. В библиотеке есть примерно такой код:
• num_subglyphs — количество компонентов символа.
• FT_Short — знаковое 16-битное число.
• FT_NEW_ARRAY — выделение памяти под массив.
Ключевая деталь: FT_Short может хранить значения от −32768 до 32767.
Но атакующий делает шрифт, у которого количество компонентов символа равно: num_subglyphs = 65533; // 0xFFFD, а в результате получается преобразование (FT_Short)65533 == -3, и выделение памяти происходит FT_NEW_ARRAY(points, 1), то есть под один элемент.
А дальше FreeType выполняет следующий код:
points[0] = loader->pp1; //допустимая запись, а остальное — вне памяти
points[1] = loader->pp2;
points[2] = loader->pp3;
points[3] = loader->pp4;
и только первые 16 байт выполняются в своей памяти, а остальные 48 байт — вне её.
Это называется Out-of-Bounds Write (OOB Write).
В результате атакующий получает возможность повредить соседние объекты в памяти. При удачном расположении объектов и обходе защит это потенциально позволяет добиться выполнения произвольного кода внутри процесса приложения.
В статье говорится, что есть подтверждённые целевые атаки на 90+ целей из разных стран.
Особенно впечатляет, что в описанном сценарии атака потенциально становится zero-click: пользователю даже не требуется открывать PDF, достаточно автоматической обработки документа приложением. Не забывайте обновлять систему патчами безопасности!
На днях узнал про любопытную команду в Git — --delete-merged .
Суть простая: команда за один запуск дропает все ветки, которые уже были влиты в origin . Конечно, можно и руками подчистить или промпт скрипт написать. Но командой как-то удобнее.
Работает так:
$ git branch --delete-merged 'origin/*' --dry-run
Would delete branch feature/login (was abc1234).
Would delete branch feature/login-fix (was def5678).
Would delete branch fix/typo (was 9876fed).
Посмотрел, убедился, что ничего лишнего — запускаешь без --dry-run:
На днях попался репозиторий с CLI-тулзой, которая обещала уменьшить потребление стандартного эмулятора с ~8 ГБ до ~1,5 ГБ на Apple Silicon и Linux.
Что-то не очень хочется тянуть неизвестную зависимость на свой ноутбук — подумал я, и отправил агента разобраться, чего там внутри.
Выяснилось, что никакой магии нет: просто упакованное использование уже стандартных инструментов.
Вот что можно сделать, чтобы ускорить работу эмулятора:
1. Купить ноутбук с 64GB RAM
2. При добавлении эмулятора выбираем образ «Google APIs», а не «Google Play». Если вам не нужен Play Store, то APIs легковеснее, а ещё на нём работает adb root.
3. Для начала зайти в Device Manager → Edit → Show Advanced Settings → RAM, и там поставить значение примерно в 2048 MB.
4. Ещё можно отключить ненужные штуки, типа камеры, микрофона или Bluetooth через ~/.android/avd/<NAME>.avd/config.ini
И последний пункт — это запуститься с флагом -lowram вместо запуска из студии. То есть:
На днях ревьювил код, связанный с копированием в буфер обмена
И заметил, что многие приложения неверно используют буфер обмена при копировании приватной информации. Типа данных карт, паролей из менеджера или 2FA-кодов.
Существует флаг IS_SENSITIVE в ClipboardManager.setPrimaryClip(). Если его не проставить — скопированное содержимое оказывается в превью клавиатуры (той самой подсказке над клавишами). Что совсем небезопасно.
Работает всё просто:
// API 33+
clipData.apply {
description.extras = PersistableBundle().apply {
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
}
}
// API 32 и ниже
clipData.apply {
description.extras = PersistableBundle().apply {
putBoolean("android.content.extra.IS_SENSITIVE", true)
}
}
Ещё стоит не забывать подчищать критичные данные при копировании. Детали можно почитать тут.
Так что если у вас в приложении есть какого-то рода приватные данные — не забывайте заботиться о ваших пользователях. ☺️