Что значит некорректные входные данные

Качественный код: проверка данных обязательна

Дискуссия, которая возникла в комментариях к посту про -555 тазиков , свидетельствует о том, что не для всех очевидно как реагировать на некорректные данные, полученные от пользователя.

Между тем, пример с отрицательным количеством товара, также как и различные XSS, SQL-injections — все это частные случаи, требующие подхода, известного как «Защитное (безопасное) программирование» (Secure programming).

Данная тема довольно часто и подробно рассматривается в специализированной литературе, например, см. «Совершенный код» С. Макконнелла (Steve McConnell, Code Complete), Глава 8 «Защитное программирование».

Приведу небольшую цитату из этой книги (если кто не читал — рекомендую):

Защитное программирование не означает защиту своего кода словами: «Это так работает!» Его идея совпадает с идеей внимательного вождения, при котором вы готовы к любым выходкам других водителей: вы не пострадаете, даже если они совершат что-то опасное. Вы берете на себя ответственность за собственную защиту и в тех случаях, когда виноват другой водитель.
В защитном программировании главная идея в том, что если методу передаются некорректные данные, то его работа не нарушится, даже если эти данные испорчены по вине другой программы. Обобщая можно сказать, что в программах всегда будут проблемы, программы всегда будут модифицироваться и разумный программист всегда будет учитывать это при разработке кода.
Эта глава рассказывает, как защититься от беспощадного мира неверных данных, событий, которые «никогда» не могут случиться, и других программистских ошибок. Если вы опытный программист, то можете пропустить следующий раздел про обработку входных данных и перейти к разделу 8.2, который расскажет об утверждениях.

8.1. Защита программы от неправильных входных данных.

Вы, возможно, слышали в школе выражение: «Мусор на входе – мусор на выходе» («Garbage in, garbage out»). Это вариант предостережения потребителю от разработчиков ПО: пусть пользователь остерегается.

Читайте также:  Что значит нехватка йода

Для промышленного ПО принцип «мусор на входе – мусор на выходе» не слишком подходит. Хорошая программа никогда не выдаст мусор независимо от того, что было у нее на входе. Вместо этого она использует принципы: «мусор на входе – ничего на выходе», «мусор на входе – сообщение об ошибке на выходе» или «мусор на входе не допускается». По сегодняшним стандартам «мусор на входе – мусор на выходе» — признак небрежного, небезопасного кода.

Существует три основных способа обработки входных мусорных данных, перечисленных далее.

Проверяйте все данные из внешних источников
Получив данные из файла, от пользователя, из сети или любого другого внешнего интерфейса, удостоверьтесь, что все значения попадают в допустимый интервал. Проверьте, что числовые данные имеют разрешенные значения, а строки достаточно коротки чтобы их можно было обработать. Если строка должна содержать определенный набор значений (скажем, идентификатор финансовой транзакции или что-то подобное), проконтролируйте, что это значение допустимо в данном случае, если же нет – отклоните его. Если вы работаете над приложением, требующим соблюдения безопасности, будьте особенно осмотрительны с данными, которые могут атаковать вашу систему: попыткам переполнения буфера, внедренным SQL-командам, внедренному HTML- или XML-коду, переполнения целых чисел, данным передаваемым системным вызовам и т.п.

Проверяйте значение всех входных параметров метода
Проверка значений входных параметров метода практически тоже самое, что и проверка данных из внешнего источника, за исключением того, что все данные поступают из другого метода, а не из внешнего интерфейса. В разделе 8.5 вы узнаете, как определить, какие методы должны проверять свои входные данные.

Решите, как обрабатывать неправильные входные данные
Что делать, если вы обнаружили неверный параметр? В зависимости от ситуации вы можете выбрать один из дюжины подходов, подробно описанных в разделе 8.3

Защитное программирование – это полезное дополнение к другим способам улучшения качества программ, описанным в этой книге. Лучший способ защитного кодирования – изначально не плодить ошибок. Итеративное проектирование, написание псевдокода и тестов до начала кодирования и низкоуровневая проверка соответствия проекту – это все, что помогает избежать добавления дефектов.…

Механизм проверки может быть различным и зависит от типа данных/языка/библиотек/фреймворка и т.д. Это могут быть утверждения (assertions), перечислимые типы данных (enum), свойства и так далее. Главное, чтобы в архитектуре приложения проверки были обязательным элементом, логически отделенным от процесса обработки данных.

Касательно реакции на некорректные данные, полученными через пользовательский интерфейс, то, на мой взгляд — нужно быть честным с юзером. Попытка предугадать, что хотел получить пользователь, указав несуществующий почтовый индекс, отрицательное количество товара или некорректный текст вместо свого e-mail — будет самообманом. Мы никогда не узнаем, о чем действительно думал посетитель во время заполнения формы. А значит, не сможем выяснить — какое значение подразумевалось на самом деле.
Вероятно, он опечатался, возможно, какой-то кулхацкер проверял — как тут все работает, а быть может это просто ошибка в интерфейсе.
В любом случае, если происходит ошибка при вводе данных — логично приостановить выполнение программы и сообщить пользователю о том, что введенные данные неверны. (Естественно, речь идет о понятных для пользователя сообщениях, например, «населенного пункта с таким индексом не существует», вместо «http/500, UE throw… incorrect zip… at class N»).

Бытует мнение, что это снизит «дружественность» интерфейса. Это не так. Напротив, ПО станет более понятным, предсказуемым и безопасным — как для пользователя, так и для разработчика. Это легко проверить на практике: достаточно писать такие ошибки в лог, и в последствии проанализировать его содержание.

Стремление добиться того, чтобы программа продолжала выполняться любой ценой, сбрасывая некорректные значения к дефолтным – опасно, и, скорее всего, говорит о том, разработчик не вполне понимает — какой в итоге может оказаться эта цена.

Источник

Проверка надежности Web приложений, часть 2

В первой статье мы рассмотрели различные способы взаимодействия пользователя с Web-приложениями и исследовали разные методы HTTP ввода, которые обычно используются разработчиками. В этой части мы рассмотрим различные способы обхода проверки правильности ввода – выполнение кода на стороне сервера и SQL инъекции. Кроме того, мы исследуем проблемы на стороне клиента, связанные со слабой фильтрацией пользовательских данных – типа XSS нападений.

В первой статье мы рассмотрели различные способы взаимодействия пользователя с Web-приложениями и исследовали разные методы HTTP ввода, которые обычно используются разработчиками. В этой части мы рассмотрим различные способы обхода проверки правильности ввода – выполнение кода на стороне сервера и SQL инъекции. Кроме того, мы исследуем проблемы на стороне клиента, связанные со слабой фильтрацией пользовательских данных – типа XSS нападений.

Метод Черного ящика

Метод “черного ящика” – метод тестирования Web-приложений, исходный код которых недоступен испытателю. В результате испытатель исследует Web-приложение со стороны пользователя (или со стороны потенциального атакующего). В этом методе исследователь использует методы снятия отпечатков (как описано в первой части статьи), чтобы исследовать и идентифицировать все ожидаемые входные данные и взаимодействие пользователя. Blackbox-испытатель сначала попытается “прощупать” приложение и изучить его ожидаемое поведение (входные данные/неизвестное приложение/выходные данные).

Испытатель пытается выявить исключительные состояния и аномальное поведение Web-приложения, управляя входными данными – используя специальные символы, SQL параметры, запросы с чрезмерными параметрами и т.п. Любая неожиданная реакция Web приложения должна быть исследована. Это могут быть сообщения об ошибках сценария (возможно с отрывками кода), ошибки сервера (HTTP 500) или полузагруженные страницы.

Рис. 1 Blackbox проверяет GET переменные

Нужно исследовать любое неправильное поведение со стороны приложения в ответ на некорректные вводимые данные, так как это должно подразумевать, что разработчик приложения не в состоянии был проверить правильность вводимых данных.

Очень часто разработчики Web приложений (независимо от используемой среды), должным образом не проверяют пользовательский ввод на наличие потенциально опасных символов перед использованием этого ввода в SQL запросах. В зависимости от используемой базы данных, уязвимость SQL инъекция и ведет к изменению уровней доступа данных/системы для атакующего. Возможно не только управление SQL запросами, но и использование UNION в произвольных данных, использование подзапросов или добавление дополнительных запросов. В некоторых случаях можно читать и записывать произвольные файлы и выполнять произвольные команды на основной операционной системе.

Определение уязвимостей SQL инъекции

В большинстве случаев самый эффективный метод определения уязвимости SQL инъекции вручную – изучение входных данных приложения и вставка специальных символов. В большинстве популярных Web-серверов страница ошибки с технической информацией отображается по умолчанию, что позволяет исследователю узнать как можно больше информации об используемом SQL запросе.

Рис. 3 Еще одна потенциальная уязвимость SQL инъекции

Пример: обход авторизации, используя SQL инъекцию

Обход авторизации — один из наиболее часто используемых примеров SQL инъекции, который демонстрирует высокую опасность этого типа уязвимостей. Один из самых простых способов авторизовать пользователя на сайте – использовать форму, которая запрашивает имя пользователя и пароль. Когда форма передана сценарию входа в систему (login.asp), имя поля имя пользователя и пароль используются в качестве переменных в SQL запросе.

Исследуем следующий код (используя в качестве базы данных MS Access DB):

Set Conn = Server.CreateObject(«ADODB.Connection»)

Set Rs = Server.CreateObject(«ADODB.Recordset»)

SQL = «SELECT C=COUNT(*) FROM users where pass='» & pass & «‘ and user='» & user & «‘»

rs.open (sql,conn) if rs.eof or rs.bof then

response.write «Database Error»

Хотя и проверка is_numeric() препятствует пользователю вводить путь к файлу в переменной messageid, при этом содержание файла сообщений никак не проверятся (проблему с принятием неконтролируемого пути к файлу мы рассмотрим позже). Если сообщение содержит PHP код, оно будет включено include() и выполнено сервером.

Простой метод эксплуатации этой уязвимости состоит в том, чтобы отправить сообщение к доске объявлений простой кусок кода (в нашем примере PHP кода), затем просмотреть отправленное сообщение и увидеть, указывают ли выходные данные на выполнение кода.

SSI – механизм для включения файлов, который использует специальную форму HTML комментариев, которые предшествуют возможностям включения современных языков сценария, типа PHP или JSP. Старые CGI программы и классические ASP сценарии все еще используют SSI, чтобы включать библиотеки кода или элементы многократного использования, типа заголовков шаблона сайта. SSI интерпретируется Web-сервером, но не языком сценариев, т.е. если SSI теги введены во время выполнения сценария, то они будут приняты и обработаны Web-сервером. Методы эксплуатации этой уязвимости подобны указанным выше методам, используемым для инъекции кода сценария. SSI является устаревшей технологией, так что мы не будем акцентироваться на этой проблеме.

Существует множество других методов нападений инъекции в Web-приложениях. Так как Web-приложение часто использует содержание заголовков, куки и GET/POST переменных в качестве входных данных, то действия, выполненные этим приложением, которые управляют этими переменными, должны быть полностью исследованы. Есть множество различных действий, которое может выполнить Web-приложение, используя эти переменные – открытие файлов, поиск в базе данных, сопряжение с другими командами системы и взаимодействие с другими Web-приложениями. Каждое из этих действий требует своего собственного синтаксиса и требует, чтобы проверялась правильность входных переменных своим уникальным способом.

Например, когда мы имеем дело с SQL инъекцией, должны быть удалены специальные SQL символы и словосочетания. Но что если Web-приложение отрывает последовательный порт и посылает информацию дистанционно через модем? Пользователь может вставить дополнительные команды модема, чтобы завесить модем или набрать другие номера. Это один из примеров инъекции. Исследовать должен понять, что незаметно выполняет приложение – вызываемые функции и выполняемые команды – могут ли параметры к этим запросам или командам управляться через заголовки, куки или GET/POST переменные.

В качестве примера рассмотрим очень часто встречающуюся проблему в функции PHP fopen (). PHP file-open fopen() функция позволяет в URL задавать имя файла, облегчая тем самым доступ к Web-службам и удаленным ресурсам. Рассмотрим в качестве примера простую портальную страницу:

Сценарий index.php включает код верхнего и нижнего колонтитула, и fopen() открывает станицу, определенную в переменной GET. Если не установлена никакая переменная, то по умолчанию она устанавливается к main.html. Разработчик вызывает .html расширение, но не определяет префикс каталога. Из-за возможностей fopen() атакующий может в нашем случае представить:

В результате сценарий откроет страницу main.html в www.hackersite.com. Очень часто подобным образом в приложение включается PHP сценарий. В этом случае атакующий может внедрить произвольный PHP код с удаленного сервера в сценарий index.php, который будет выполнен на целевом сервере.

Один из типичных примеров подобной уязвимости можно посмотреть здесь. http://www.securityfocus.com/bid/6463

Большинство квалифицированных разработчиков Web приложений знают о текущих проблемах SQL инъекции и используют разнообразные функции для фильтрации ввода. Однако, как только проблема затрагивает менее распространенные системные команды или протоколы, проверка правильности ввода часто некорректна или неадекватна, из-за слабого понимания более широких проблем проверки правильности входящих данных.

Обход каталога и URL

Большинство используемых web приложений для генерации конечной Web страницы используют различные куски кода, расположенные в нескольких файлах. Такой подход уязвим, как показано выше, к проблемам инъекции кода. Также очень часто в переменные, определяющие расположения файла, можно вставить относительный путь, чтобы включить произвольные файлы на системе.

Рассмотрим предыдущий пример с инъекцией кода, в котором разработчик не определил суффикс файла с Fopen():

В результате чего атакующий может получить доступ к любым файлам, которые доступны для чтения Web-приложению.

Запрос возвратит содержание /etc/passwd, если не выполняется дополнительная проверка на наличие символа пути (/.) в переменной file.

Эта проблема затрагивает большинство современных Web-технологий, включая PHP, Java и Microsoft .NET. Если это поддерживается на целевой среде, уязвимые приложения могут использоваться как открытое реле или прокси-сервер. Пример:

Этот недостаток — одна из самых простых проблем защиты, которую легко определить и исправить, хотя он часто встречается на небольших сайтах, код приложения которых выполняет простую сборку кода. Проблема может быть смягчена двумя способами. Сначала осуществите внутренний числовой индекс к документам или, как в нашем коде доски объявлений, используйте файлы в числовой последовательности со статическим префиксом и суффиксом. Во вторых, удаляйте любые символы пути типа [/\], которые могли бы использовать атакующие, чтобы обратиться к ресурсам вне дерева каталогов приложения.

Нападения межсайтового скриптинга (как часть нападений инъекции содержания) отличаются от других методов нападения, описанных в этой статье, так как этот метод воздействует на клиента Web-приложения (то есть браузер пользователя). Cross Site Scripting (XSS) происходит везде, где разработчик неправильно позволяет пользователю управлять выходными HTML данными приложения — это может быть результатом запроса поиска, или любых других выходных данных приложения, где входные данные пользователя затем отображаются пользователю без какой либо фильтрации HTML содержания.

Рассмотрим простой пример XSS в следующем URL:

В этом примере содержание параметра ‘name’ отображается в возвращенной странице. Пользователь может представить следующий запрос:

Books

Если символы <> не удаляются или фильтруются Web-приложением, тэг

будет отображен в возвращенной Web странице и интерпретирован браузером как правильный HTML. Более интересный пример:

Источник

Оцените статью