Chrome на Android сломал чужие MitM-сертификаты, но это можно исправить
Прозрачность сертификатов (CT) — отличный проект компании Google, который сейчас фактически стал стандартом де-факто в интернете. Серверы CT показывают все выпущенные EV-сертификаты в открытых и общедоступных источниках.
Всё работает отлично до тех пор, пока не сломается.
В частности, в последнее время браузер Chrome создал ряд проблем под Android, фактически заблокировав работу сторонних приложений, таких как снифферы, MitM-прокси и средства разработки. Эти программы устанавливают в систему собственные доверенные сертификаты для перехвата и разбора трафика.
Первые признаки проблемы появились в мае 2022 года. Примерно в этом время в документации Chrome Enterprise v99 под Android возникло следующее примечание о прозрачности сертификатов:
Написано, что CT уже действует на десктопах, а сейчас распространится на всех пользователей Android Chrome.
Проблема в том, что после таких изменений у нас перестанут работать многие полезные инструменты, в том числе на рутованных устройствах.
После внедрения CT все эти инструменты при попытки проанализировать HTTPS-трафик или совершить другое действие от имени своего корневого сертификата получат одинаковую ошибку: «Требуется прозрачность сертификата» (на скриншоте).
ERR_CERTIFICATE_TRANSPARENCY_REQUIRED
Certificate Transparency (RFC 6962, а недавно принята вторая версия RFC 9162) — стандарт безопасности для мониторинга цифровых сертификатов в интернете. Он работает через систему публичных журналов, куда в конечном итоге попадают все сертификаты, выданные центрами сертификации.
Однако в публичный лог не попадёт ваш личный самоподписанный сертификат, который вы сделали для использования на своём собственном смартфоне. В этом и проблема.
Понятно, от какой угрозы CT защищает пользователей.
Различные злоумышленники пытаются установить в систему доверенные сертификаты своих собственных центров сертификации. Так пытаются сделать некоторые VPN-сервисы, китайские зловреды, национальные провайдеры и др. В этом случае система глобального доверия может оказаться подорвана, потому что MiTM-актор с корневым сертификатом сможет читать и подменять любую информацию в канале HTTPS, то есть к любому защищённому сайту, включая Google, Gmail и др.
Жертва такой атаки будет нормально подключаться к настоящим сайтам. В то же время трафик можно прослушать третьему лицу. Браузер не заметит подделки и будет сигнализировать «замочком» HTTPS, что всё нормально. Это очень опасно. Отдельные люди годами сидят на такой «прослушке» и ничего не замечают.
Поэтому прозрачность сертификатов введена неспроста. Общий прозрачный лог сертификатов в виде глобального дерева Меркла хранит все документы от каждого глобального центра сертификации, с метками времени (SCT), а браузеры проверяют эти SCT. Данные метки служат определённым доказательством, что сертификат предъявлен общественности и внесён в открытую базу. Ну и любой желающий всегда может посмотреть эту базу и проверить SCT.
Но бывают исключительные ситуации, когда установка MiTM-прокси реально необходима. Например, для дебаггинга трафика при разработке мобильных и веб-приложений, для реверс-инжиниринга, пентестинга. Есть целый класс инструментов, таких как mitmproxy и HTTP Toolkit специально для подобных целей. Они в процессе работы выдают поддельные сертификаты для серверов, к которым подключается клиент (с разрешения клиента, то есть браузера). Работа таких инструментов теперь затруднена, потому что браузер больше не даёт разрешения.
От «принудительной защиты» со стороны Chrome пострадают в первую очередь профессиональные разработчики, тестеры, специалисты по безопасности, исследователи.
На устройстве Android в реальности установлено несколько разных хранилищ сертификатов (CA):
/system/etc/security/cacerts/
/data/misc/user/0/cacerts-added/
- CA отдельного приложения
Раньше можно было просто поместить свой MitM-сертификат в системное хранилище (такое возможно после рутования) — и система ему доверяла. Ваша «троянская» программа нормально работала и сканировала трафик к любым доменам для дебаггинга и веб-разработки.
Но с версии Android Chrome 99 браузер начинает проверять метки SCT для всех сертификатов, которые выдаёт ваш MitM-прокси, на каждой страничке выбрасывая ошибки NET::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED
.
В Chromium это не признали багом (статус WontFix
), поэтому решать проблему придётся самостоятельно.
Разработчики HTTP Toolkit поясняют, что нам просто нужно запустить Chrome с флагом --ignore-certificate-errors-spki-list=$YOUR_SPKI_FINGERPRINT
. Они предлагают такой обходной путь (на рутованном смартфоне):
- Сделайте отпечаток SPKI своего сертификата:
openssl x509 -in $YOUR_CA_CERTIFICATE -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
- Создайте файл с одной строкой:
chrome --ignore-certificate-errors-spki-list=$YOUR_SPKI_FINGERPRINT
- Командой
adb push
скопируйте файл на устройство Android по следующим адресам:/data/local/chrome-command-line
/data/local/android-webview-command-line
/data/local/webview-command-line
/data/local/content-shell-command-line
/data/local/tmp/chrome-command-line
/data/local/tmp/android-webview-command-line
/data/local/tmp/webview-command-line
/data/local/tmp/content-shell-command-line
Это гарантирует его применение для всех версий Chromium как в нормальном, так и в отладочном окружении. - Установите разрешения для всех файлов:
chmod 555
, чтобы они были доступны для чтения Chromium при запуске. - Принудительно остановите Chrome (
am force-stop com.android.chrome
), а затем запустите снова. - Проверьте в
chrome://version
, что наш параметр командной строки сработал.
В принципе, эту последовательность действий можно прописать в автоматическом скрипте по AKB, если требуется изменить настройки браузера Chrome на большом количестве устройств.
На этом проблема решена.