Вебинар: Использование статических анализаторов кода при разработке безопасного ПО - 19.12
Исследователи из Кембриджского университета опубликовали технику незаметной подстановки вредоносного кода в рецензируемые исходные тексты. Подготовленный метод атаки (CVE-2021-42574) представлен под именем Trojan Source и базируется на формировании текста, по-разному выглядящего для компилятора/интерпретатора и человека, просматривающего код.
Примеры применения метода продемонстрированы для различных компиляторов и интерпретаторов, поставляемых для языков C, C++ (GCC и Clang), C#, JavaScript (Node.js), Java (OpenJDK 16), Rust, Go и Python.
Мы опубликовали и перевели эту статью с разрешения правообладателя. Оригинал опубликован на сайте OpenNET.
Метод основан на применении в комментариях к коду специальных Unicode-символов, меняющих порядок отображения двунаправленного текста. При помощи подобных управляющих символов одни части текста могут выводиться слева-направо, а другие — справа-налево. В повседневной практике подобные управляющие символы могут применяться, например, для вставки в файл с кодом строк на иврите или арабском языке. Но, если при помощи указанных символов комбинировать строки с разным направлением текста в одной строке, отрывки текста, отображаемые справа-налево, могут перекрыть уже имеющийся обычный текст, отображаемый слева-направо.
Используя данный метод, в код можно добавить вредоносную конструкцию, но затем сделать текст с этой конструкцией незаметным при просмотре кода, через добавление в следом идущем комментарии или внутри литерала символов, показываемых справа-налево, что приведёт к наложению на вредоносную вставку совершенно других символов. Подобный код останется семантически корректным, но будет по-разному интерпретироваться и отображаться.
Рисунок 1. Отображаемый текст, содержащий атаку Trojan Source "растянутая строка" в C++.
Рисунок 2. Закодированные байты атаки Trojan Source "растянутая строка" в C++.
Рисунок 3. Отображаемый текст, содержащий атаку Trojan Source "комментирование кода" в C++.
Рисунок 4. Закодированные байты атаки Trojan Source "комментирование кода" в C++.
В процессе рецензирования кода разработчик столкнётся с визуальным порядком вывода символов и увидит в современном текстовом редакторе, web-интерфейсе или IDE не вызывающий подозрения комментарий, но компилятор и интерпретатор будут использовать логический порядок символов и обработают вредоносную вставку как есть, не обращая внимания на двунаправленный текст в комментарии. Проблеме подвержены различные популярные редакторы кода (VS Code, Emacs, Atom), а также интерфейсы для просмотра кода в репозиториях (GitHub, Gitlab, Bitbucket и все продукты Atlassian).
Рисунок 5. Подверженность уязвимости различных программ для работы с кодом.
Выделяются несколько способов использования метода для реализации вредоносных действий: добавление скрытого выражения "return", приводящего к завершению выполнения функции раньше времени; заключение в комментарий выражений, нормальным образом видимых как действующие конструкции (например, для отключения важных проверок); присвоение иных строковых значений, приводящих к сбоям проверки строк.
Например, атакующий может предложить изменение, включающее строку:
if access_level != "user[RLO] [LRI]// Check if admin[PDI] [LRI]" {
которая будет отображена в интерфейсе для рецензирования как:
if access_level != "user" { // Check if admin
Дополнительно предложен ещё один вариант атаки (CVE-2021-42694), связанный с использованием омоглифов, символов, внешне похожих по начертанию, но отличающихся значением и имеющих разные unicode-коды (например, символ "ɑ" напоминает "a", "ɡ" — "g", "ɩ" — "l"). Подобные символы можно использовать в некоторых языках в именах функций и переменных для введения разработчиков в заблуждение. Например, могут быть определены две функции с неотличимыми именами, выполняющие разные действия. Без детального разбора сразу не понять, какая из этих двух функций вызывается в конкретном месте.
Рисунок 6. Отображаемый текст, содержащий атаку Trojan Source "функции-омоглифы" в C++.
Рисунок 7. Закодированные байты атаки Trojan Source "функции-омоглифы в C++.
В качестве меры для защиты рекомендуется реализовать в компиляторах, интерпретаторах и сборочных инструментах, поддерживающих Unicode-символы, вывод ошибки или предупреждения при наличии в комментариях, строковых литералах или идентификаторах непарных управляющих символов, меняющих направление вывода: {U+202A} (LRE), {U+202B} (RLE), {U+202C} (PDF), {U+202D} (LRO), {U+202E} (RLO), {U+2066} (LRI), {U+2067} (RLI), {U+2068} (FSI), {U+2069} (PDI), {U+061C} (ALM), {U+200E} (LRM), {U+200F} (RLM). Подобные символы также должны быть явно запрещены в спецификациях языков программирования и должны учитываться в редакторах кода и интерфейсах для работы с репозиториями.
Дополнение 1: исправления с устранением уязвимости подготовлены для GCC, Rust, Go, Python и binutils. Проблему также устранили GitHub, Bitbucket и Jira. В процессе подготовки исправление для GitLab. Для выявления проблемного кода предложено использовать команду:
grep -r \
$'[\u061C\u200E\u200F\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069]' \
/path/to/source
Дополнение 2: Рас Кокс (Russ Cox), один из разработчиков ОС Plan 9 и языка программирования Go, раскритиковал излишнее внимание к описанному методу атаки, который уже давно известен (Go, Rust, C++, Ruby) и не воспринимался всерьёз. По мнению Кокса, проблема в основном касается правильности отображения информации в редакторах кода и web-интерфейсах, решается применением корректных инструментов и анализаторов кода при рецензировании. Поэтому вместо привлечения внимания к умозрительным атакам было бы более правильным сосредоточить внимание на улучшении процессов рецензирования кода и зависимостей.
Рас Кокс также считает, что компиляторы не то место, где стоит устранять проблему, так как даже в случае запрета опасных символов на уровне компилятора останется огромный пласт инструментов, в которых использование проблемных символов остаётся допустимым, таких как системы сборки, ассемблеры, пакетные менеджеры и разнообразные парсеры конфигурации и данных. Для примера приведён проект Rust, который запретил обработку кода LTR/RTL в компиляторе, но не добавил исправление в пакетный менеджер Cargo, что позволяет совершить аналогичную атаку через файл Cargo.toml. Другими источниками атак могут стать такие файлы, как BUILD.bazel, CMakefile, Cargo.toml, Dockerfile, GNUmakefile, Makefile, go.mod, package.json, pom.xml и requirements.txt.
Примечание команды PVS-Studio. Незаметно внедрить уязвимость в уже существующий код может быть не так уж и просто на практике, однако описанная в статье уязвимость вполне реальна. Мы реализовали диагностику V1076 (C и С++) для поиска подозрительных Unicode последовательностей в релизе PVS-Studio 7.16. Для остальных языков (C#, Java) соответствующие диагностики появятся в следующих релизах. Они все будут релевантны SAST направлению, которое наша команда сейчас активно развивает.
0