Предотвращение инжекционных атак и XSS

Инжекционные атаки и перекрестный сайт, пишущий сценарий (XSS), являются двумя типами уязвимостей, часто связываемых с веб-разработкой. Однако подобные проблемы могут произойти в любом типе приложения. Знакомясь с этими типами атак и понимая антиобразцы, которые они представляют, можно избежать их в программном обеспечении.

Предотвращение инжекционных атак

Существует два типа данных в мире: неструктурированные данные и структурированные данные. Тип, который Вы выбираете, может оказать значительное влияние на то, что необходимо сделать для создания программного обеспечения безопасным.

Неструктурированные данные редки. Это в основном включает файлы простого текста, когда они используются исключительно в качестве средние значения отображения текста. Как правило, что, кажется, неструктурированные данные, фактически слабо структурированные данные.

Со структурированными данными различные части данных имеют различное значение. Каждый раз, когда единственная часть данных содержит два или больше различных типов данных таким образом, потенциал для инжекционных атак существует. Потенциальные риски варьируются в зависимости от того, как Вы смешиваете данные — в частности, структурированы ли они строго или слабо структурированы.

Строго структурированные данные имеют фиксированный формат, определяющий, где должны быть сохранены каждые данные. Простой формат данных для материально-технических ресурсов хранилища мог бы, например, указать, что должно быть 4 байта, содержащие номер записи, сопровождаемый на 100 байтов человекочитаемого описания. Строго структурированные данные являются довольно прямыми для работы с. Несмотря на то, что интерпретация каждого байта зависит от его расположения в данных, пока Вы избегаете переполнять любых буферов фиксированного размера и действительно адаптируете проверки, чтобы гарантировать, чтобы значения были целесообразны, угрозы безопасности являются обычно относительно низкими.

Слабо структурированные данные, однако, несколько более проблематичны с точки зрения безопасности. Слабо структурированные данные являются гибридной схемой, в которой части данных имеют переменную длину. Слабо структурированные данные могут быть далее разделены на одну из двух категорий: явно измеренные данные и неявно измеренные данные.

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

Неявно измеренные данные более трудно интерпретировать. Это использует специальные символы-разделители в самих данных, чтобы описать, как должны быть интерпретированы данные. Например, это могло бы использовать запятые для разделения полей или кавычек для разделения данных от команд, воздействующих на те данные. Например, SQL и команда оболочки смешивают сами командные слова с данными, на которые воздействует команда. Файлы HTML смешивают теги с текстом. И т.д.

Поскольку неструктурированный, строго структурированный, и слабо структурированные данные с явными длинами, менее вероятно, изложат угрозы безопасности, остаток от этого раздела внимание на слабо структурированные данные с неявными длинами.

Опасности смешанных данных

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

Самый простой способ продемонстрировать проблему на примере. Рассмотрите следующий отрывок данных JSON:

{
    "mydictionary" :
    {
        "foo" : "Computer jargon",
        "bar" : "More computer jargon"
    }
}

Эта структура описывает вложенный набор пар ключ/значение. Ключи —mydictionary, foo, и bar— имеют переменную длину, как их значения (словарь, плюс строки Computer jargon и More computer jargon. Их длина определяется синтаксическим анализатором — часть программного обеспечения, читающего и анализирующего сложную часть данных, разделяя ее на его составные части. При парсинге данных JSON синтаксический анализатор ищет двойную кавычку, отмечающую начало и конец каждой строки.

Теперь предположите, что Ваше программное обеспечение является онлайновым словарем, позволяющим пользователям добавлять слова, проверяя их, чтобы удостовериться, что они не невежливые слова прежде, чем добавить их. Что происходит, если пользователь злонамеренно вводит что-то как следующий?

Term: baz
Definition: Still more computer jargon", "naughtyword": "A word you should not say

Наивная часть программного обеспечения могла бы вставить определение в файл JSON путем обертывания и срока и определения (как) в кавычках. Получающийся файл JSON был бы похож на это:

{
    "mydictionary" :
    {
        "foo" : "Computer jargon",
        "bar" : "More computer jargon",
        "baz" : "Still more computer jargon", "naughtyword": "A word you should not say"
    }
}

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

Вместо этого программное обеспечение должно было выполнить заключение в кавычки на данных — сканирование ввода для символов, имеющих особое значение в контексте содержания включения и изменения или иначе маркировки их так, чтобы они не были интерпретированы как специальные символы. Например, можно защитить кавычки в JSON путем предшествования им с наклонной чертой влево (\), как показано здесь:

{
    "mydictionary" :
    {
        "foo" : "Computer jargon",
        "bar" : "More computer jargon",
        "baz" : "Still more computer jargon\", \"naughtyword\": \"A word you should not say"
    }
}

Теперь, когда синтаксический анализатор читает JSON, он правильно читает определение baz как Still more computer jargon.", "naughtyword": "A word you should not say. Таким образом непослушное слово не определяется, потому что это - просто часть определения baz. Конечно, это все еще оставляет вопрос того, необходимо ли было проверить на несоответствующие слова в определениях, но это - отдельный вопрос.

Инжекция SQL

Наиболее распространенный тип инжекционной атаки является инжекцией SQL, метод, использующий в своих интересах синтаксис SQL для введения произвольных команд. SQL-оператор выглядит примерно так:

INSERT INTO users (name, description) VALUES ("John Doe", "A really hoopy frood.");

Этот пример содержит смесь инструкций ( INSERT сам оператор) и данные (строки, которые будут вставлены).

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

Для соединения проблемы язык SQL предоставляет оператору комментария, --, который заставляет SQL-сервер игнорировать остальную часть строки. Например, если пользователь вводит следующий текст как его или ее имя пользователя:

joe", "somebody"); DROP TABLE users; --

получающаяся команда была бы быть похожей на это:

INSERT INTO users (name, description) VALUES ("joe", "somebody"); DROP TABLE users; --", "A really hoopy frood.");

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

Немного менее наивная программа могла бы проверить на двойные кавычки и отказаться позволять Вам использовать их в своем имени пользователя или описании. Как правило это - нежелательный по нескольким причинам:

  • Этот подход может не быть совместим с UTF-8. Символы UTF-8 часто содержат те же числовые значения как кавычки, что означает, что (например), капитал G с седилью мог бы быть неправильно сохранен в Вашей базе данных, в зависимости от того, как Ваш SQL-сервер обрабатывает UTF-8 (или не делает).

  • Если Вы изменяете свой запрос немного для использования одинарных кавычек, повреждений решения.

  • Если пользователь помещает наклонную черту влево перед кавычкой, Ваши повреждения решения (если Вы также не заключаете тем в кавычки), потому что эти две наклонных черты влево тогда обрабатываются как буквенный символ.

  • Если Вы проверяете на запрещенные символы в JavaScript, но не выполняете подобные проверки на серверной стороне, злонамеренный пользователь может обойти проверки и ввести код так или иначе.

  • Если Вы проверите на запрещенные символы в JavaScript, потому что пользователь не может легко видеть, есть ли у Вас подобные проверки на серверной стороне, то Ваши пользователи будут волноваться о безопасности Вашего сайта.

  • Один из Ваших пользователей мог бы действительно хотеть, чтобы его или ее имя пользователя было "; DROP TABLE users; -- или возможно что-то немного менее экстремальное.

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

INSERT INTO users (name, description) VALUES (?, ?);

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

Для получения дополнительной информации о предотвращении атак с использованием кода на SQL на приложениях, использующих Базовые Данные сложными способами, считайте Предикаты Создания в Руководстве по программированию Предиката.

Выполнение команды языка C и сценарии оболочки

В языке программирования C существует много приемлемых способов выполнить внешнюю команду, с помощью exec, posix_spawn, NSTask, и связанные функции и классы. Существует также много неправильных способов использовать эти и другие функции. Этот раздел обеспечивает некоторые подсказки относительно того, как избежать дыр в системе безопасности при выполнении внешних команд.

  • Не используйте систему. system функционируйте выполняет внешний процесс оболочки и передает командную строку непосредственно той оболочке. Это означает, что необходимо должным образом заключить любые параметры в кавычки, что Вы передаете командам. system если те параметры прибывают из потенциально недоверяемых источников, функция особенно проблематична. Поэтому необходимо избегать использования system функция кроме с трудно кодированными командами.

  • Не используйте popen. popen имеет те же угрозы безопасности как system. Вместо использования popen, любое использование NSTask класс или конструкция канал и выполняют команду самостоятельно.

    NSTask класс упрощает связываться со стандартным вводом, выводить, и ошибочные дескрипторы дочернего процесса. Можно узнать больше путем чтения Ссылки класса NSTask.

    На уровне POSIX можно достигнуть той же вещи с pipe системный вызов, следующим образом:

    1. Используйте pipe системный вызов для создания одной или более пар связанных каналов.

    2. Используйте fork системный вызов для создания дочернего процесса.

    3. В дочернем процессе используйте dup2 системный вызов для замены один или больше стандартного ввода, стандартного вывода и дескрипторов файлов стандартной погрешности с конечной точкой канала по Вашему выбору.

    4. В дочернем процессе использовать exec, posix_spawn, или связанные функции для запуска желаемого инструмента.

    5. В родительском процессе читайте из или запишите в противоположный конец каждого канала.

    Например:

    int pipes[2];
    if (pipe(pipes) < -1) {
        ... // Handle the error
    }
     
    int pid = fork();
    if (pid == -1) {
        ... // Handle the error
    } else if (!pid) {
        // In the child process:
     
        dup2(pipe[1], STDOUT_FILENO); // or STDIN_FILENO or STDERR_FILENO
        close(pipe[0]);
     
        exec(...) or posix_spawn(...) // Run the external tool.
     
    } else {
        // In the parent process:
     
        close(pipe[1]);
        read(pipe[0], ...);
     
        waitpid(pid, ...); // Wait for the child process to go away.
    }

    Для получения дополнительной информации см. страницы руководства для pipe, fork, dup2, exec, posix_spawn, и waitpid.

  • Избегите сценариев оболочки, если это возможно. Используете ли Вы NSTask или любая из функций выше, избегайте использования сценариев оболочки для выполнения команд, потому что заключение в кавычки оболочки просто понять превратно. Вместо этого выполните команды индивидуально.

  • Контролируйте любые сценарии оболочки. Если Ваше программное обеспечение выполняет сценарии оболочки и передает потенциально недоверяемые данные им, Ваше программное обеспечение могло бы быть затронуто любыми ошибками заключения в кавычки в тех сценариях. Необходимо тщательно контролировать эти сценарии для заключения в кавычки ошибок, которые могли бы привести к дырам в системе безопасности.

    Для получения дополнительной информации читайте Специальные символы Заключения в кавычки и Безопасность Сценария оболочки в Shell, Пишущем сценарий Учебника для начинающих.

Заключение в кавычки на URLs

Правила для заключения в кавычки URL сложны и выходят за рамки этого документа. OS X и iOS обеспечивают подпрограммы для помощи Вам, но несомненно необходимо будет использовать корректную подпрограмму для того, что Вы пытаетесь сделать.

Для узнавания больше считайте Строки Преобразования в Кодирование URL в Сетевом Обзоре.

Заключение в кавычки на HTML и XML

Самый безопасный способ работать с HTML и XML состоит в том, чтобы пользоваться библиотекой, обеспечивающей объекты для каждого узла, такой как NSXMLParser класс или libxml2 API. Однако, если необходимо создать HTML или XML вручную, существует пять специальных символов, которые должны быть заключены в кавычки явно при преобразовании текста в HTML или XML:

  • Меньше, чем (<) — Замена &lt; везде

  • Больше, чем (>) — Замена &gt; везде

  • Амперсанд (&) — Замена &amp; везде

  • Двойная кавычка (") — Замена &quot; в значениях атрибута

  • Одинарная кавычка (") — Замена &apos; в значениях атрибута

Для узнавания больше о дырах в системе безопасности, которые могут следовать из отказа заключить содержимое HTML в кавычки должным образом считайте Сценарии Перекрестного сайта Предотвращения.

Предотвращение сценариев перекрестного сайта

Другой значительный риск, связанный с веб-разработкой, является сценариями перекрестного сайта. Сценарии перекрестного сайта относятся к введению кода в веб-сайт, заставляющий его вести себя по-другому, чем это иначе было бы. Атакующий мог бы, например, ввести клавиатурный перехватчик, выводящий на экран поддельное диалоговое окно входа в систему и передающий пароли обратно атакующему.

Существует много типов уязвимостей сценариев перекрестного сайта:

И т.д. Подробные данные сценариев перекрестного сайта выходят за рамки этого документа. Для узнавания больше о сценариях перекрестного сайта и о том, как избежать его считайте Шпаргалку Предотвращения XSS. Оттуда, можно найти ссылки ко многим другим статьям о веб-безопасности. Можно также найти много сторонних книг по сценариям перекрестного сайта.