Безопасное программирование


Содержание

Методы безопасной разработки программного обеспечения

Рассматриваются методы безопасной разработки программного обеспечения. Описываются цели и границы применения методов, достоинства и недостатки. В настоящее время существует достаточно большое количество методов безопасной разработки про граммного обеспечения (ПО).

Рассматриваются применяемые при разработке ПО методы, целью которых является повышение качества и безопасности конечного программного продукта. Методы безопасной разработки могут быть выделены в следующие группы, относительно этапов и процессов разработки ПО, в которых они применяются: методы, применяемые в процессе управления разработкой ПО; методы, применяемые при анализе и формировании требований и составлении спецификаций, а так же в процессе проектирования; методы, применяемые в процессе реализации; методы, применяемые в процессе тестирования, вводе в эксплуатацию и поддержке разработанного ПО. Методы безопасной разработки ПО различаются по следующим критериям: границы применения, цели использования в процессе разработки ПО. Решение об использовании при создании ПО того или иного метода безопасной разработки зачастую принимаются на основе указанных критериев. Поэтому целью данной работы является так же анализ различных методов с точки зрения их эффективности и границ применения. К числу методов, применяемых в процессе управления разработкой ПО относятся: метод “команды безопасности”, проведение обзорных анализов безопасности, метод “стерильной комнаты”, модель улучшения процессов CMMI, метод структурной корректности. Метод “команды безопасности” заключается в выделении в структуре организации группы либо отдела, называемых командой безопасности, которая отвечает за развитие и совершенствование процессов разработки с точки зрения информационной безопасности, выступает в роли эксперта по вопросам информационной безопасности для всей организации в целом и для каждого из проектов в частности.

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

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

Существуют так же итоговые обзорные анализы безопасности, проводимые экспертами по информационной безопасности (внешними либо внутренними). Сведения, полученные в результате проведения подобного обзорного анализа могут применяться для повышения эффективности применения методик обеспечения безопасности, а так же являться основанием для пересмотра отдельных этапов или всего процесса разработки ПО, практикуемого в организации. Разработка программного обеспечения методом «стерильной комнаты» представляет собой теоретически обоснованный, ориентированный на командную разработку процесс создания, верификации и сертификации корректных программных систем со статистическим контролем качества. Метод “стерильной комнаты” охватывает весь жизненный цикл разработки, включая управление проектом, определение спецификаций функций и архитектуры, проверку правильности функционала, а также статистическое тестирование при сертификации программ. Основная идея данного метода – предотвращение ошибок и дефектов в программных средствах предпочтительней, нежели их устранение. Основные принципы метода таковы: инкрементная разработка на основе статистического контроля качества; использование принципа структурной разработки представлений; тестирование на основе методов статистики; итеративная разработка; перераспределение времени между этапами жизненного цикла; разработка ПО должна базироваться на формальных методах. К преимуществам метода “стерильной комнаты” можно отнести: широкие возможности для верификации программных систем за счет использования формальных спецификаций, метод подразумевает подробное формальное описание всех возможных сценариев выполнения разрабатываемых программ, что значительно снижает вероятность некорректной работы программ, а также значительно уменьшает вероятность возникновения ошибок в спецификации и требованиях к ПО. Метод обеспечивает прозрачность, а значит и более полные возможности контроля и верификации формальных спецификаций, сформированных на основе требований к ПО. Метод позволяет обнаруживать и устранять ошибки и уязвимости на ранних стадиях разработки (начиная со стадии формирования спецификаций) и, таким образом предотвращает появление подобных критических ошибок на стадии проектирования и реализации. Из недостатков следует выделить, что метод фокусирует основное внимание на корректной разработке отдельных компонентов системы (что является очень эффективно при разработке отдельных компонентов), но в то же время не предоставляет достаточно эффективных инструментов для анализа и верификации системы в целом. Метод “стерильной комнаты” не предоставляет средств для анализа поведения системы в динамике (в процессе работы системы), требует достаточно сложных вспомогательных автоматизированных средств для верификации различных, представлений системы и их соответствия, а так же соответствия спецификаций, проектной документации и программного кода. Метод структурной корректности, включает в себя определение формальных нотаций для спецификаций систем и компонентов архитектуры с учетом их согласованности и корректности. Он позволяет с помощью формальных методов проверять программное обеспечение и своевременно устранять в нем дефекты на протяжении его жизненного цикла.

Данный способ включает в себя определение формальных нотаций для спецификаций систем и компонентов архитектуры с учетом их согласованности и корректности. Для безопасных систем выделяются категории состояний системы и операций, которые определяются с учетом их влияния на общую безопасность. Конечной целью является создание архитектуры, которая позволяет свести к минимуму число функций, критически важных для обеспечения защиты, и изолировать их. Это способствует дальнейшему снижению стоимости и сокращению объема работы (возможно, значительно более трудоемкой), связанной с проверкой правильности данных элементов. Модель улучшения процессов CMMI используется для общей оценки эффективности работы организации (в зависимости от определенных в модели критериев) и поиска путей ее повышения. Модель CMMI содержит основные направления развития процессов разработки в организации, наборы практик и методов разработки, адаптация и оптимизации которых с учетом специфики конкретной организации является достаточно эффективным инструментом для совершенствования всего процесса разработки. Методами применяемыми при анализе и формировании требований и составлении спецификаций, а так же в процессе проектирования являются Z-нотация, В-метод (нотация), UMLSec, оценка рисков и моделирование угроз. Z-нотация представляет собой язык формального описания, используемый для проектирования и моделирования вычислительных систем.

Язык Z является стандартом, утвержденным ISO (ISO/IEC 13568:2002). Z-нотация основана на стандартной математической нотации, используемой в аксиоматической теории множеств, лямбда-исчислении, и логике предикатов первого порядка. За счет сочетания двух видов математических нотаций позволяет составлять формальные описания требований и спецификаций, а также для составления проектов ПО различного уровня детализации и абстракции. В настоящее время язык Z является базисным для ряда других формальных нотаций, включая адаптированные варианты Z для объектно-ориентированных языков программирования. Однако большую роль в эффективности применения Z-нотации играет практический опыт разработчиков. Применение данной нотации значительно повышает время и трудоемкость разработки. B-нотация это формальная нотация, являющийся подвидом Z-нотации. В-метод позволяет создавать четкие, непротиворечивые, логически связанные спецификации, верифицируемые и математически корректные. Формальные спецификации и проектные, полученные в результате применения данного метода, близки к неформальным спецификациям разрабатываемого ПО по уровню детализации и модели представления, что позволяет минимизировать ошибки при переходе от неформальных спецификаций к формальным и далее к проектной документации. По сравнению с Z-нотацией, B-метод является более низкоуровневым методом. Он предназначен для применения на этапе программной реализации и учитывает многие нюансы данного процесса. Преимуществами данного метода является создание формализованных спецификаций и моделей, ориентированных на особенности программной реализации. UMLSec является стандартным расширением языка UML, предназначенным для проектирования и разработки безопасных ИС. Он включает в себя средства для представления функциональных требований и требований безопасности, спецификаций, проектирования. UMLSec представляет возможность визуального моделирования и проектирования различных уровней детализации представлений. UMLSec содержит достаточно большое количество шаблонов моделей и диаграмм, которые позволяют решать типовые задачи обеспечения информационной безопасности в короткие сроки и с высоким уровнем надежности.

В настоящее время имеется большое число программных средств, предназначенных для составления и описания диаграмм UMLSec, а также средства автоматического анализа их корректности. Кроме того, существует программное обеспечение, позволяющее на основе данных диаграмм формировать описания последовательности тестов для разрабатываемого ПО, верификации разрабатываемого ПО, генерации начального программного кода. Разработка ПО с использованием UMLSec менее ресурсоемкая со сравнению с большинством других формальных методов. Однако математические методы формализации не являются основными в UMLSec, что не позволяет полностью исключить непротиворечивость и неточности в спецификациях и проектной документации. Кроме того, следует отметить сложность верификации корректности реализации функциональности программ, проектированных с помощью UMLSec. К методам, применяемым в процессе реализации, относятся метод использования руководств разработчиков и контрольных ведомостей, метод безопасных и формальных языков программирования. Руководства разработчиков и контрольные ведомости являются набором основных принципов, практических советов и рекомендаций, как избежать появления наиболее типичных и распространенных уязвимостей в ПО в процессе написания программного кода. К подобным правилам следует отнести стандарты написания программного кода, действующие в организации, списки запрещенных либо рекомендованных к использованию функций языка программирования, используемого при разработке. Так же в процессе разработки возможно применение контрольных ведомостей (checklist), которые представляют собой списки значимых с точки зрения ИБ при разработке ПО моментов, выполнение которых разработчик в обязательном порядке должен проконтролировать и проверить. Обычно для каждого из этапов разработки существует своя контрольная ведомость.

В ходе разработки ведомости и руководства могут пересматриваться и обновляться для повышения эффективности их использования. Хотя подобные средства не способны гарантировать отсутствие ошибок и предотвратить появление ошибок и уязвимостей, не схожих с уже известными, они способны уменьшить общее количество уязвимостей в разрабатываемом ПО. Метод применения безопасных языков программирования учитывает, что многие часто используемые языки программирования имеют ряд свойств, которые могут оказаться источниками появления уязвимостей. Выбор языка программирования также может оказать существенное влияние на безопасность конечного продукта. Лучшими языками являются те, в которых все действия определены и обоснованы, поддерживаются функции, уменьшающие число ошибок (например, требуется строгое определение типов), осуществляется контроль за распределением памяти и использованием указателей. Одним из возможных вариантов для разработки безопасного ПО является язык программирования Ada95. За счет возможности выполнения проверок корректности реализованных модулей и функций непосредственно в процессе компиляции, расширенной обработки исключений, возможности спецификации типов, а так же общей формализации, повышающей эффективность верификации программного кода, написанного на данном языке, Ada 95 обеспечивает более высокий уровень надежности и безопасности по сравнению с другими языками программирования. К недостаткам данного языка следует отнести общую сложность реализации, сложность в изучении и использовании, значительное увеличение трудоемкости разработки, отсутствие поддержки объектно-ориентированного программирования.

Применение языков, разработанных с учетом различных вопросов безопасности (C#, Java, Ada95) может позволить избежать ряда типичных ошибок и уязвимостей ПО, повысить эффективность верификации программного кода. Методами, применяемыми в процессе тестирования, вводе в эксплуатацию и поддержке разработанного ПО являются применение различных способов тестирования и организация поддержки ПО. Использование в процессе тестирования анализаторов кода, а так же таких методов тестирования как тестирование на устойчивость, тестирование методом Баллиста, модульного тестирования программного кода позволяет эффективно выявлять дефекты системы безопасности, что не только не только сказывается на эффективности исправления ошибок, но и позволяет предотвращать их появление в будущих системах и проектах. Кроме того, аналогичные дефекты можно исключить из других уже разработанных программных продуктов. Знания о ошибках и уязвимостях, полученные в ходе поддержки выпущенного ПО могут быть использованы при применении некоторых методик безопасной разработки ПО для недопущения повторения подобных ошибок. Кроме того, анализ сведений об уязвимостях, выявленных после выпуска программного продукта является эффективным инструментом для оценки эффективности применяемых методик безопасной разработки и всего процесс разработки в организации в частности. Тестирование не дает гарантий, что ПО не содержит ошибок и уязвимостей и даже не гарантирует корректное поведение ПО и соответствие его функциональности требованиям. Однако использование эффективных методик тестирования в течении всего процесса разработки программного кода, корректное построение процесса тестирования способно обнаружить большинство из ошибок, уязвимостей и случаев неправильного функционирования, тем самым повышая безопасность ПО. В целом можно отметить что, корректное применение методов разработки безопасного ПО способно значительно повысить качество и безопасность разрабатываемого продукта при относительно умеренном уровне затрат. При этом, с учетом различной эффективности методов и различий в области их применения наиболее целесообразным представляется применение совокупности некоторых из рассмотренных методов для безопасной разработки на различных этапах создания ПО, например применение UMLSec на этапах формирования требований и проектирования, применение руководств разработчика, контрольных ведомостей и безопасных языков программирования на этапе разработки, а также применение таких методов тестирования как модульное тестирование, тестирование методом Баллиста, тестирование на устойчивость.

1.Сайт xakep.ru. Режим доступа: (https://xakep.ru/2011/08/03/56389/) (дата обращения 25.08.2020). — 13 УТИЛИТ ДЛЯ БЕЗОПАСНОЙ РАЗРАБОТКИ: ИНСТРУМЕНТЫ ОТ MICROSOFT ДЛЯ НАПИСАНИЯ НАДЕЖНОГО КОДА

2. Официальный сайт компании ИнфоТеКС .Режим доступа: (https://www.infotecs.ru/press/publications/detail.php? >

3. Зефиров С. Л., Колобанов А. Ю. Методы безопасной разработки программного обеспечения. – 2009. – С. 1-3.

Что каждый программист должен знать о безопасности

Многие начинающие программисты задаются вопросом: «каким минимумом знаний по безопасности должен обладать каждый разработчик или студент IT-шник?». Попробуем ответить на этот вопрос.

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

  • Не доверяйте входным данным! Проверяйте входные данные из ненадёжных источников — используйте белые списки, а не чёрные.
  • Планируйте безопасность с самого начала — это не то, чем можно заняться напоследок.
  • Делайте своё приложение простым — сложность увеличивает вероятность дыр в безопасности.
  • Сведите вашу поверхность атаки к минимуму.
  • Убедитесь, что ошибка во время работы приложения не поставит под угрозу его безопасность.
  • Обеспечивайте безопасность приложения на каждом этапе разработки.
  • Придерживайтесь принципа наименьших привилегий.
  • Используйте моделирование угроз.
  • Разделяйте привилегии, чтобы было проще отследить источник проблемы.
  • Хранить секретные данные сложно, а все секретные данные, спрятанные в коде, быстро перестанут быть секретными.
  • Не создавайте свои механизмы шифрования.
  • Использование одного лишь шифрования не делает ваше приложение абсолютно безопасным — злоумышленники найдут другое слабое место, ведь безопасность любой системы всегда равна безопасности самого слабого звена.
  • Знайте и помните о переполнении буфера и о том, как от него защититься.

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

Обучите ваших разработчиков лучшим практикам безопасности:

Хотите узнать о том, как защитить своё веб-приложение в более развёрнутой форме? Тогда загляните в нашу статью, там всё подробно расписано.

Политика разработки безопасного программного обеспечения

Политика разработки безопасного программного обеспечения

Внедрение мер по разработке безопасного программного обеспечения (ПО) на всех этапах жизненного цикла (SDLC ─ Secure Software Development Lifecycle) является обязательным условием конкурентоспособности на рынке для компаний, занимающихся разработкой ПО. Наша компания внедрила в свой процесс разработки лучшие практики по организации процесса разработки безопасного ПО с целью предоставления более надежной и безопасной продукции нашим заказчикам. В частности, Infotecs SDLC (ISDL) учитывает требования регламентов ФСТЭК России, национального стандарта ГОСТ Р 56939-2020, международных стандартов серии ISO/IEC 27000, материалы OWASP, а также рекомендации NIST (например, NIST SP 800-64, SP 800-100).

ISDL ─ это комплексный процесс, затрагивающий всю организацию и включающий следующее:

Программа обучения

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

Илон Маск рекомендует:  Iis регулирование процессов

Сбор требований

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

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

Учет всех действующих нормативно-правовых актов на раннем этапе способствует снижению расходов, рисков несоответствия, а также времени выпуска продукта на рынок в целом.

Стандарты и лучшие практики

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

Проектирование

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

Анализ сторонних компонентов

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

Анализ поверхности атак

Цель такого анализа ─ выявить, к каким компонентам или функциям злоумышленник имеет доступ и, соответственно, может их использовать, и свести количество таких компонентов и функций к минимуму.

Разработка модели угроз

Разработка модели угроз ─ один из наиболее важных этапов разработки продукта с учетом безопасности. Мы разрабатываем модель угроз с учетом результатов, полученных на предыдущем шаге. Затем мы используем ее для определения необходимого уровня безопасности и последующего выбора соответствующих мер защиты, которые должны быть реализованы в продукте.

Разработка


Безопасное программирование прежде всего направлено на предотвращение появления ошибок в коде на этапе разработки, что может быть достигнуто посредством:

  1. Внедрения строгого стандарта безопасного программирования и контролем его соблюдения посредством анализа кода;
  2. Внедрением современных инструментов автоматизации (статических анализаторов, компиляторов, систем контроля версий и т.д.) в среду разработки ПО.

Стандарт безопасного программирования

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

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

Процесс разработки ПО предполагает использование автоматизированных средств (компиляторов, систем контроля версий, анализаторов кода и т.д.), которые должны быть настроены надлежащим образом. Чтобы оставаться эффективными, эти инструменты должны своевременно обновляться, поэтому мы стараемся поддерживать актуальность версий средств автоматизации, используемых в нашей среде разработки.

Проверка

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

Тестирование мер защиты

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

Сканирование на наличие уязвимостей

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

Тестирование на проникновение

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

Выпуск и поддержка продукта

Выпуск продукта на рынок осуществляется только после успешного проведения финальной проверки безопасности (FSR – Final Security Review), выполненной командой разработки и экспертами по безопасности. Кроме того, мы разработали план реагирования на инциденты для устранения возможных проблем безопасности в наших продуктах. Мы также оказываем услуги технической поддержки (ссылка) и своевременно предоставляем заказчикам всю необходимую информацию о планируемых изменениях в продукте.

Финальная проверка безопасности / Сертификация

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

План реагирования на инциденты

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

Управление конфигурацией и изменениями

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

Вывод из эксплуатации

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

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

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

Удаление аппаратного и программного обеспечения

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

Внедрение процедур безопасной разработки программного обеспечения (Secure SDLC)

Вы разрабатываете программное обеспечение для себя или на заказ? Думаете, что старая шутка про «Тяп ляп и в продакшен!» точно не про вас? Мы поможем вам проверить, так ли это на самом деле, и выстроить процессы разработки ПО в соответствии с лучшими мировыми практиками.

4 главные опасности для заказчика программного обеспечения, с которыми мы поможем справится разработчику:

  1. Ошибки программирования, которые не только препятствуют нормальной работе приложений (зависания, BSOD, потеря данных), но и «приглашают» злоумышленника ими воспользоваться.
  2. Расширение функциональных возможностей приложений в ущерб безопасности в погоне за сроками и удобством.
  3. Встраивание функций, которые делают возможным обход механизмов защиты. Разработчики ПО оставляют такие функции для облегчения тестирования и отладки приложений, но забывают их отключить в финальной версии.
  4. Программные закладки, которые умышленно встраиваются в исходный код приложений или в обновления ПО и используются для получения несанкционированного доступа к информации или других вредоносных действий. В исходный код закладки встраивает злоумышленник из команды разработки.

Количество уязвимостей в ПО не сокращается само по себе

Для чего нужен Secure SDLC

Внедрение процедур безопасной разработки сокращает совокупную стоимость разработки за счёт более раннего обнаружения и устранения уязвимостей. По мнению Национального института стандартов и технологий США (NIST), затраты на устранение уязвимостей на этапе проектирования могут быть в 30 раз ниже затрат на устранение таких же уязвимостей после выпуска продукта.

Принцип Secure Software Development LifeCycle — классический риск-ориентированный подход из учебника. Его внедрение не устраняет уязвимости полностью (что очень долго и дорого), оно лишь снижает их до минимально приемлемого уровня.

Не отстают и регуляторы: ФСТЭК России с 1 июня 2020 года обязывает разработчиков средств защиты информации следовать требованиям ГОСТ Р 56939-2020 «Защита информации. Разработка безопасного программного обеспечения. Общие требования».

Состав работ по внедрению Secure SDLC

В качестве методик внедрения цикла безопасной разработки мы используем Рекомендации в области стандартизации банка России РС БР ИББС-2.6 -2014, MS SDL, OWASP Secure SDLC Cheat Sheet.

«Перспективный мониторинг» оценивает процессы разработки на всех стадиях цикла.

Пример Secure SDLC от компании HP


  • Наладим мониторинг безопасности используемых сторонних компонентов, который исключит для разработчика роль «догоняющего». Как только уязвимость будет опубликована — разработчику станет о ней известно.
  • Построим модель угроз и модель нарушителя и научим вас это делать.
  • Протестируем на проникновение разработанные продукты методом «черного ящика». В отчёте будет содержаться перечень уязвимостей, отсортированный по степени критичности, сценарии эксплуатации и рекомендации к устранению.
  • Оценим спроектированные решения с точки зрения безопасности и определим поверхность атаки.
  • Поможем внедрить статические анализаторы исходного кода в технологический процесс сборки ПО (Continuous Integration). Использование анализаторов на этапе разработки снижает количество ошибок и дефектов программного кода на 15–20%.
  • Сделаем фаззинг сетевых протоколов, форматов файлов, значимых для ПО переменных окружения, входных параметров веб-приложений. Разработаем кастомизированные фаззинг-решения для самостоятельного применения.
  • Проанализируем исходный код на предмет безопасности.
  • Проведём аудит процесса эксплуатации информационной системы и безопасности системы обновлений.

Defensive Programming. Звучит здорово, но что это такое?

Defensive Programming

Безопасное программирование это форма безопасного планирования, предназначенная для продолжительного функционирования частей ПО, несмотря на непредвиденное использование указанного ПО. это был вступительный заголовок на англоязычной википедии, как мне удалось его перевести. По логике скорее получается что безопасное программирование просто вытекает из принципов безопасного планирования и заключается в том, что любая часть нашего ПО должна выдерживать нестандартное использование данного ПО. В связи с этим я решил описать тут эту статью так, как смог понять её сам(если я оказался в чем-то не прав — поправьте меня).
Эту идею можно рассматривать как снижение или устранение перспективы закона Мёрфи(закона подлости, если попроще).
Методы безопасного программирования используются прежде всего тогда, когда часть ПО может быть использована неправильно, специально или по неосторожности, что может привести к катастрофическим эффектам.

Безопасное программирование подходит для улучшения ПО и исходного кода, с точки зрения следующих факторов:
— Общее качество: — Сокращение числа ошибок и багов в ПО(это само собой).
— Создание понятного исходного кода — Исходники должны быть понятны и легкочитаемы, это является плюсом при проверке программы(а также для других разработчиков, если таковые появятся, а также для самого себя).
— ПО должно вести себя предсказуемо, несмотря на неожиданные вводные данные или действия пользователя

Защищенное программирование:

В среде ИТ-специалистов безопасное программирование иногда называют защищенным программированием. По их заявлениям — такой подход минимизирует баги.
Ошибки в ПО — потенциальная лазейка, используемая взломщиками для внедрения кода(code injection), атаки системы(запрещающие обслуживание или другие атаки).

Разница между безопасным программированием и программированием, встречаемым в обычной практике, состоит в некоторых допущениях, сделанных программистом, пытающимся обработать все возможные состояния ошибки(error states).
Получается, что программист не может предположить, что специфический вызов функции или библиотеки, будет работать, как положено, и как оно обрабатывается в коде.
Например:

Эта функция обвалится, если переменная input будет длиннее 1000 символов. Большинство могут не принимать эту проблему всерьез, предполагая что никакой пользователь не станет заносить так много данных в переменную. Программист, практикующий методы безопасного программирования, не допустит такую ошибку, потому что, когда в приложении есть известный баг, закон подлости(или Мёрфи, кому как больше нравится) гласит, что данный баг обязательно встретится при использовании. Этот специфический баг демонстрирует уязвимость, использующую переполнение буфера. А вот как можно решить этот пример:

Методы.

Ниже приведены некоторые методы безопасного программирования:
Повторное использование настраиваемого(Интеллектуального(intelligent)) исходного кода:
Если существующий код протестирован и хорошо показал себя в работе, то повторное использование может снизить вероятность появления ошибок (багов) при внедрении.

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

У многих программных продуктов, возникли проблемы с наследованием старого исходного кода. Например:

  • Наследуемый код не может быть разработан в соответствии с правилами защитного программирования, и поэтому может быть более худшего качества, по сравнению с заново разработанным кодом.
  • Может оказаться, что наследуемый код был написан и протестирован в условиях, которые в текущее время уже не применимы. Таким образом получается, что прошлые тесты контроля качества уже не котируются(не являются валидными)
  1. Изначально код, был разработан для ввода ASCII данных. Теперь же для ввода данных используется UTF-8.
  2. Изначальный код был скомпилирован и протестирован на 32-битной архитектуре, но при компиляции на 64-битной архитектуре, могут возникнуть новые арифметические проблемы(такие как недействительные приведения типов и прочие)
  3. Если наследуемый код изначально предназначался для offline-машин(Компьютеров не подключенных к ЛС), то может случиться что код становится уязвимым при подключении к сети.

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

  • BIND 9, был представлен Полом Викси и Дэвидом Конрадом как «BINDv9 is complete rewrite(Полностью переписан)», «Security was a key consideration in design(Безопасность являлась ключевым фактором при проектировании)», называя безопасность, надежность и новые протоколы ключевой задачей для переписывания старых исходников.
  • Microsoft Windows пострадали от уязвимости в метафайлах Windows и другими эксплойтами связанными с форматом WMF. Центр обеспечения безопасности Microsoft описывает WMF-функции как «примерно в 1990 годах, была добавленна поддержка WMF… Это было другое время с точки зрения направленности на безопастность. (я бы сказал „с точки зрения обеспечения безопасности“, но смысл состоит немножко в другом)… все было полностью проверенно», не были разработаны с учетом инициатив безопасности Microsoft.
  • Oracle борется с проблемами наследия, такими как старые исходники написанные без учета проблем обращения SQL-инъекций и расширения привилегий. В результате многие уязвимости, на которые было выделено время для исправлений, были не полностью исправлены. Это вызвало резкую критику со стороны экспертов в области безопасности. Также дополнительную критику вызывало то, что установки по умолчанию(в основном наследие старых версий), не совпадали с их собственными рекомендациями безопасности, некоторые из которых трудно изменить, так как многие приложения требуют менее безопасной настройки наследования для правильного функционирования.
Безопасная обработка ввода и вывода(input и output(фиг знает как оно правильно должно звучать по русски)):
  • Безопасная обработка ввода и вывода относится к безопасной методике программирования, предназначенной для предотвращения багов и их использования.
  • Обработка вводных данных:
    • Обработчик вводных данных — приложение, сервер, или другая компьютерная система обрабатывающая получаемые от пользователя, клиента или компьютерной сети вводные данные.
    • Безопасная обработка вводных данных необходимо для предотвращения уязвимостей, связанных с инъекцией кода, обхода каталогов, и прочих.
  • Также к безопасной обработке вводных данных относятся проверка вводных данных, завершение операции при некорректных данных, фильтрация, шифрование и прочее.
Канонизация
  • Взломщики с легкостью изобретают новые виды предоставления неверных данных. Например, если при проверке запрошенный файл не является «/etc/passwd» , взломщик может использовать другой вариант данного имени файла, например «/etc/./passwd» .
  • Во избежание ошибок из-за неканонического ввода, используют канонизацию API.
Другие методы:

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

Проектирование по контракту:
  • Проектирование по контракту использует предварительные условия, постусловия и инварианты, чтобы предоставленные данные(и состояние программы в целом) были обработаны. Это позволяет сделать код лучше, документировать его допущения, и делать его безопасным. Также, оно может включать в себя проверку аргументов функции или методов до выполнения тела функции. Возврат значения перед выходом(break/return/throw/error code) также является плюсом.
  • Утверждения:
    • Внутри функции, вы можете проверить, что вы не ссылаетесь на что-либо не валидное(например NULL) и что длинна массива валидна перед обращениям к элементам, особенно на всех временных/локальных экземплярах. Хорошей эвристикой считается недоверие к библиотекам, написанным не вами. Таким образом, проверяйте все, что вы получили от них, после каждого их вызова. это часто помогает в создании маленькой библиотеки «утверждающих» и «проверяющих» функций, запускаемых совместно с логгером, таким образом вы можете трассировать свои пути и сократить обширные циклы отладки. С появлением аспектно-ориентированного программирования многие из утомительных аспектов безопасного программирования смягчаются.
  • Предпочтение исключений для кода возврата(return):
    • Вообще говоря, желательно выбрасывать понятные исключения вместо возврата значений, к которым, другие программисты, скорее всего не готовы. Это позволяет минимизировать жалобы клиента (или разработчика) и повышает надежность и безопасность вашего ПО.


Итак. Краткие выводы.
  1. Сколько не используй код повторно, рано или поздно его придется переписать с нуля(читай заменить на нечто более новое).
  2. Обрабатывайте все вводные данные, без этого никуда, и поможет не выпасть в overflow.
  3. Наследование старого кода — это конечно хорошо, но лучше написать свежий код, с учетом всех требований.
  4. Методы защищенного программирования лучше использовать всегда. Да и канонизацию тоже никто не отменял.

В общем Defensive Programming звучит гордо, но на деле получается, что не так оно и круто, как звучит.
Не стоит прибегать к неизученным приемам, если лень в них разбираться, особенно название приема звучит впечатляюще.

Основы программирования: Лекция #10. Безопасность в Интернете. Обработка естественных языков, II [CS50-2015, Гарвард]

Доброго дня, Пикабу! Представляем 21-ую лекцию легендарного Гарвардского курса CS50, который мы переводим и озвучиваем специально для JavaRush.

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

Если вы — новичок, пройдите CS50. Если кто-то из ваших знакомых приглядывается к ИТ и программированию, советуйте CS50 не глядя. Я серьезно.

CS50 подойдет любому человеку, кто решил стать «айтишником». Пожалуй, его можно рекомендовать и способным 12-летним, и умудренным опытом «перебежчикам» из других профессий. Идеально — старшеклассникам и студентам.

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

Что изучают на CS50?

— Основы компьютерных наук и программирования. Системы счисления, работа с командной строкой в Linux, циклы, условные переходы и прочие радости;

— Концепции алгоритмов и алгоритмичности мышления. Вы узнаете о том, какие задачи можно решать с помощью программирования и каким образом. О бинарном поиске, простом по сути, но очень эффективном и требующем тщательности в реализации, Дэвид Малан расскажет сходу, прямо на нулевой лекции. И попробуйте потом забыть сцену с разрывом телефонного справочника, а вместе с ней — и полученные знания! Вообще, курс охватывает все основные алгоритмы, которые нужно знать и понимать «айтишникам»;

— Концепции абстракции, структуры данных, инкапсуляции, управления памятью. Основы компьютерной безопасности. Процесс разработки ПО и веб-разработка;

— Основы языка программирования C и визуального языка Scratch. Собственно, все основные примеры и задания студенты делают на языке C;

— Основы баз данных и SQL;

— Веб-разработка: основы CSS, HTML, JavaScript и PHP. Естественно, только самые азы;

— Основы подготовки презентации проектов по программированию.

Поддержите нас плюсом и подписывайтесь на нас и сообщество «Наука».

Оборонительная программирование — Defensive programming

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

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

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

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

содержание

Безопасное программирование

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

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

Наступление программирование

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

Доверчивый внутренняя валидность данных

Доверяя компоненты программного обеспечения

методы

Вот некоторые защитные методы программирования:

повторное использование интеллектуального исходного кода

Если существующий код проверен и, как известно, работа, повторное использование может уменьшить вероятность ошибок в стадии внедрения.

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

проблемы наследия

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

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

Многие программные продукты испытывали проблемы со старым наследием исходного кода, например:


  • Наследство коды не могут быть разработаны в рамках инициативы оборонного программирования, и , следовательно , могут быть гораздо более низкого качества , чем новый дизайном исходного кода.
  • Унаследованного кода, возможно, были написаны и протестированы в условиях, которые больше не применяются. Испытания старые гарантии качества не может иметь юридической силы больше.
    • Пример 1 : унаследованный код может быть разработан для ввода ASCII , но теперь вход UTF-8.
    • Пример 2 : унаследованный код , возможно, был собран и испытан на 32-битных архитектурах, но при компиляции на 64-разрядных архитектурах могут возникать новые арифметические задачи (например , недействительные тесты знаковости, неверный типа отливки, и т.д.).
    • Пример 3 : унаследованный код может быть мишенью для автономных машин, но становится уязвим когда добавляется подключение к сети.
  • Код Наследство не написано с новыми проблемами в виду. Например, исходный код , написанный около 1990 года, вероятно, будет подвержена многим внедрения кода уязвимости, поскольку большинство таких проблем не было широко известно в то время.

Известные примеры унаследованной проблемы:

  • BIND 9 , представленный Пол Vixie и Дэвид Конрад , как «BINDv9 является полностью переписан », «Безопасность является ключевым фактором в дизайне», называя безопасность, надежность, масштабируемость и новые протоколы в качестве ключевых проблем для перезаписи старого унаследованного кода.
  • Microsoft Windows , пострадала от «» Windows Metafile уязвимости и других вредоносных программ, связанных с форматом WMF. Центр безопасности Microsoft Response описывает WMF-функцию , как «Около 1990 года, была добавлена поддержка WMF . Это было другое время в ландшафте безопасности . все были полностью доверять» , не разрабатывается в рамках инициатив в области безопасности в Microsoft.
  • Oracle является борьба с унаследованных проблем, таких как старый исходный код , написанный без решения проблем инъекции SQL и привилегий , в результате чего многие уязвимости безопасности , которые потребовалось время , чтобы исправить , а также сгенерированные неполные исправлений. Это привело к резкой критике со стороны экспертов безопасности , таких как Дэвид Личфилд , Александр Kornbrust , Сезар Cerrudo . Дополнительная критика в том , что установки по умолчанию ( в основном в наследство от старых версий) не совпадает с их собственными рекомендациями безопасности, такие как Oracle Database Security Контрольного список , который трудно изменить , как многие приложения требуют менее безопасных параметров унаследованных для правильного функционирования.

Канонизация

Злоумышленники могут изобрести новые виды представлений неверных данных. Например, если программа пытается отказаться от доступа к файлу «/ и т.д. / ПАРОЛЬ », взломщик может пройти еще один вариант этого имени файла, как «/etc/./passwd». Канонизации библиотеки могут быть использованы , чтобы избежать ошибок из — за не- канонического ввода.

Низкая толерантность против «потенциальных» ошибок

Предположим , что кодовые конструкции , которые кажутся проблемы склонной ( по аналогии с известными уязвимостями и т.д.) являются ошибки и потенциальные недостатки безопасности. Основное правило заключается в том: «Я не в курсе всех типов эксплойтов я должен защищать от тех , кто я. Ничего не знаю , и я должен быть активным!».

Защитное программирование. Что это такое?

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

Так есть ли разница между защитным программированием и обработкой ошибок?

История

Впервые я столкнулся с термином «защитное программирование» в книге Кернигана и Ритчи (The C Programming Language, 1st Edition). После тщательных поисков мне не удалось найти более ранних упоминаний этого термина. Вероятно, он был придуман по аналогии с «безопасным вождением», о котором стали активно рассуждать в начале 1970-х, за несколько лет до появления книги Кернигана и Ритчи.

В предметном указателе к книге K&R указано две страницы, на которых употребляется этот термин. На стр. 53 он означает написание кода, не допускающего возникновения багов, а на стр. 56 этот термин понимается уже немного иначе: создание кода, снижающего вероятность возникновения багов при последующих изменениях кода в процессе его доработки. В любом случае с тех пор термин «защитное программирование» употреблялся во многих книгах. Обычно под ним понимается обеспечение работоспособности кода даже при наличии багов — например, в книге «The Pragmatic Programmer» Эндрю Ханта и Дэйва Томаса (где о «программировании в защитном стиле» рассказывается в главе «Pragmatic Paranoia»), а также в других источниках.

Различия в толковании

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

Еще одна классическая и часто цитируемая статья, озаглавленная просто «Defensive Programming», имеет очень высокий рейтинг на сайте Codeproject.com. Это по-своему замечательная и содержательная статья, но она рассказывает не строго о защитном программировании, а, по признанию самого автора, «о методах, полезных при отлавливании программных ошибок». Как будет показано ниже, защитное программирование оказывает противоположный эффект — оно не отлавливает ошибки, а скорее скрывает их. Упомянутая статья с Codeproject.com затрагивает многие темы, и ее следовало бы переименовать, например, в «Good Coding Practices».

Сравнение обработки ошибок и защитного программирования

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

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

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

Итак, выбираемая нами стратегия — защитное программирование или явное добавление обработки ошибок — зависит от области применения конкретной программы. Подробнее мы поговорим об этом в разделе «Область применения».

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

  1. программа принимает информацию прямо от пользователя, который может ввести невалидные данные;
  2. программа принимает данные из текстового файла, написанного человеком;
  3. программа принимает данные из XML-файла (сгенерированного автоматически или вручную);
  4. программа считывает файл с бинарными данными, созданный другой программой;
  5. программа считывает файл с бинарными данными, созданный ею же;
  6. программа считывает файл с бинарными данными, содержащий контрольную сумму для проверки наличия/отсутствия в нем повреждений;
  7. программа считывает временный бинарный файл, только что созданный ею же;
  8. программа считывает файл, созданный ею же и отображаемый в память;
  9. программа считывает информацию из локальной переменной (то есть из памяти), которую она только что записала.

В какой момент мы можем быть уверены, что данные не могут оказаться невалидными? Я считаю, что совершенно невозможен случай, в котором файл с невалидными данными продолжает генерировать верную контрольную сумму (см. сценарий 6). Тем не менее, если данные обладают повышенной критичностью с точки зрения безопасности, необходимо учесть и вероятность того, что файл был специально подправлен для получения «верной» контрольной суммы. В таком случае придется использовать криптографическую контрольную сумму, например SHA1.

Правда, мне известно, что во многих программах предполагается, что все файлы с бинарными данными безусловно являются валидными (сценарий 4 или 5). Но при этом часто встречаются программы, которые начинают вести себя непредсказуемо, если получат поврежденные файлы с бинарными данными.

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

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

Классический пример защитного программирования можно найти практически в любой программе, когда-либо написанной на C. Речь о случаях, когда условие завершения пишется не как тест на неравенство ( Текст Oleg Sivchenko Теги программисты, программирование, программы, перевод, программист

Тема 3.2. Защитное программирование

Читайте также:

  1. Выпуклое программирование.
  2. Государственное экономическое программирование.
  3. Действие электрического тока на организм человека. Защитное заземление
  4. Динамическое программирование.
  5. Защитное действие растворов ВМС
  6. ЗАЩИТНОЕ ЗАЗЕМЛЕНИЕ
  7. Защитное заземление есть преднамеренное электрическое соединение с землей или ее эквивалентом металлических нетоковедущих частей, которые могут оказаться под напряжением.
  8. Защитное заземление, зануление и отключение
  9. Защитное заземление.
  10. Защитное зануление
  11. Защитное зануление.
  12. Защитное программирование.

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

Как утверждает Майерс, «защитное программирование основано на важной предпосылке: худшее, что может сделать модуль, — это принять неправильные входные данные и затем вернуть неверный, но правдоподобный результат».

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

Защитное программирование — это встраивание отладочных средств в программу.

Примером защитного программирования может служить метод заглушек при кодировании сверху вниз. Защитное программирование применяется для повышения надежности ПС при программировании модуля в более широком смысле.

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


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

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

Эта глава рассказывает, как защититься от беспощадного мира неверных данных, событий, которые «никогда» не могут случиться, и других программистских ошибок.

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

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

Вы, возможно, слышали в школе выражение: «Мусор на входе — мусор на выходе»

1. Это вариант предостережения потребителю от разработчиков ПО: пусть пользователь остерегается.

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

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

| следующая лекция ==>
Тема 2.9. Оптимизация программ. Оптимизирующие компиляторы | Проверяйте все данные из внешних источников

Дата добавления: 2014-01-07 ; Просмотров: 707 ; Нарушение авторских прав? ;

Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет

Безопасное программирование

Данная статья не претендует на роль всеобъемлющего руководства на тему «как сделать так, чтобы меня никто не поломал». Так не бывает. Единственная цель этой статьи — показать некоторые используемые мной приемы для защиты веб-приложений типа WWW-чатов, гостевых книг, веб-форумов и других приложений подобного рода. Итак, давайте рассмотрим некоторые приемы программирования на примере некоей гостевой книги, написанной на PHP.

Первой заповедью веб-программиста, желающего написать более-менее защищенное веб-приложение, должно стать «Никогда не верь данным, присылаемым тебе пользователем». Пользователи — это по определению такие злобные хакеры, которые только и ищут момента, как бы напихать в формы ввода всякую дрянь типа PHP, JavaScript, SSI, вызовов своих жутко хакерских скриптов и тому подобных ужасных вещей. Поэтому первое, что необходимо сделать — это жесточайшим образом отфильтровать все данные, присланные пользователем.

Допустим, у нас в гостевой книге существует 3 формы ввода: имя пользователя, его e-mail и само по себе тело сообщения. Прежде всего, ограничим количество данных, передаваемых из форм ввода чем-нибудь вроде:

На роль настоящей защиты, конечно, это претендовать не может — единственное назначение этого элемента — ограничить пользователя от случайного ввода имени длиннее 20-ти символов. А для того, чтобы у пользователя не возникло искушения скачать документ с формами ввода и подправить параметр maxlength, установим где-нибудь в самом начале скрипта, обрабатывающего данные, проверку переменной окружения web-сервера HTTP-REFERER:

Теперь, если данные переданы не из форм документа, находящегося на сервере www.myserver.com, хацкеру будет выдано деморализующее сообщение. На самом деле, и это тоже не может служить 100%-ой гарантией того, что данные ДЕЙСТВИТЕЛЬНО переданы из нашего документа. В конце концов, переменная HTTP_REFERER формируется браузером, и никто не может помешать хакеру подправить код браузера, или просто зайти телнетом на 80-ый порт и сформировать свой запрос. Так что подобная защита годится только от Ну Совсем Необразованных хакеров. Впрочем, по моим наблюдениям, около 80% процентов злоумышленников на этом этапе останавливаются и дальше не лезут — то ли IQ не позволяет, то ли просто лень. Лично я попросту вынес этот фрагмент кода в отдельный файл, и вызываю его отовсюду, откуда это возможно. Времени на обращение к переменной уходит немного — а береженого Бог бережет.

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

Не дадим пользователю использовать пустое поле имени — просто так, чтобы не давать писать анонимные сообщения:

Запретим пользователю использовать в своем имени любые символы, кроме букв русского и латинского алфавита, знака «_» (подчерк), пробела и цифр:

Я предпочитаю везде, где нужно что-нибудь более сложное, чем проверить наличие паттерна в строке или поменять один паттерн на другой, использовать Перл-совместимые регулярные выражения (Perl-compatible Regular Expressions). То же самое можно делать и используя стандартные PHP-шные ereg() и eregi(). Я не буду приводить здесь эти примеры — это достаточно подробно описано в мануале.

Для поля ввода адреса e-mail добавим в список разрешенных символов знаки «@» и «.», иначе пользователь не сможет корректно ввести адрес. Зато уберем русские буквы и пробел:

Поле ввода текста мы не будем подвергать таким жестким репрессиям — перебирать все знаки препинания, которые можно использовать, попросту лень, поэтому ограничимся использованием функций nl2br() и htmlspecialchars() — это не даст врагу понатыкать в текст сообщения html-тегов. Некоторые разработчики, наверное, скажут: «а мы все-таки очень хотим, чтобы пользователи _могли_ вставлять теги». Если сильно неймется — можно сделать некие тэгозаменители, типа «текст, окруженный звездочками, будет высвечен bold’ом.». Но никогда не следует разрешать пользователям использование тегов, подразумевающих подключение внешних ресурсов — от тривиального до супернавороченного .

Как-то раз меня попросили потестировать html-чат. Первым же замеченным мной багом было именно разрешение вставки картинок. Учитывая еще пару особенностей строения чата, через несколько минут у меня был файл, в котором аккуратно были перечислены IP-адреса, имена и пароли всех присутствовавших в этот момент на чате пользователей. Как? Да очень просто — чату был послан тег , в результате чего браузеры всех пользователей, присутствовавших в тот момент на чате, вызвали скрипт myscript.pl с хоста myserver.com. (там не было людей, сидевших под lynx’ом :-) ). А скрипт, перед тем как выдать location на картинку, свалил мне в лог-файл половину переменных окружения — в частности QUERY_STRING, REMOTE_ADDR и других. Для каждого пользователя. С вышеупомянутым результатом.

Посему мое мнение — да, разрешить вставку html-тегов в чатах, форумах и гостевых книгах — это красиво, но игра не стоит свеч — вряд ли пользователи пойдут к Вам на книгу или в чат, зная, что их IP может стать известным первому встречному хакеру. Да и не только IP — возможности javascript’a я перечислять не буду :-)

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

Допустим, вся система модерирования книги также состоит из двух частей — страницы со списком сообщений, где можно отмечать подлежащие удалению сообщения, и непосредственно скрипта, удаляющего сообщения. Назовем их соответственно admin1.php и admin2.php.

Простейший и надежнейший способ аутентикации пользователя — размещение скриптов в директории, защищенной файлом .htaccess. Для преодоления такой защиты нужно уже не приложение ломать, а web-сервер. Что несколько сложнее и уж, во всяком случае, не укладывается в рамки темы этой статьи. Однако не всегда этот способ пригоден к употреблению — иногда бывает надо проводить авторизацию средствами самого приложения.

Первый, самый простой способ — авторизация средствами HTTP — через код 401. При виде такого кода возврата, любой нормальный браузер высветит окошко авторизации и попросит ввести логин и пароль. А в дальнейшем браузер при получении кода 401 будет пытаться подсунуть web-серверу текущие для данного realm’а логин и пароль, и только в случае неудачи потребует повторной авторизации. Пример кода для вывода требования на такую авторизацию есть во всех хрестоматиях и мануалах:

Разместим этот кусочек кода в начале скрипта admin1.php. После его выполнения, у нас будут две установленные переменные $PHP_AUTH_USER и PHP_AUTH_PW, в которых соответственно будут лежать имя и пароль, введенные пользователем. Их можно, к примеру, проверить по SQL-базе:

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

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

Итак, раскрываю секрет: допустим, хакер вводит заведомо несуществующее имя пользователя и пустой пароль. При этом в результате выборки из базы переменная $rpassword принимает пустое значение. А алгоритм шифрования паролей при помощи функции СУБД MySQL Password(), так же, впрочем, как и стандартный алгоритм Unix, при попытке шифрования пустого пароля возвращает пустое значение. В итоге — $password == $rpassword, условие выполняется и взломщик получает доступ к защищенной части приложения. Лечится это либо запрещением пустых паролей, либо, на мой взгляд, более правильный путь — вставкой следующего фрагмента кода:

То есть — проверкой наличия одного и только одного пользователя в базе. Ни больше, ни меньше.

Точно такую же проверку на авторизацию стоит встроить и в скрипт admin2.php. По идее, если пользователь хороший человек — то он приходит к admin2.php через admin1.php, а значит, уже является авторизованным и никаких повторных вопросов ему не будет — браузер втихомолку передаст пароль. Если же нет — ну, тогда и поругаться не грех. Скажем, вывести ту же фразу «hacker? he-he. «.

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

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

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

Такая модель называется сессионной — после прохождения авторизации открывается так называемая «сессия», в течение которой пользователь имеет доступ к защищенной части системы. Сессия закрылась — доступ закрывается. На этом принципе, в частности, строится большинство www-чатов: пользователь может получить доступ к чату только после того, как пройдет процедуру входа. Основная сложность данной схемы заключается в том, что все скрипты защищенной части приложения каким-то образом должны знать о том, что пользователь, посылающий данные, успешно авторизовался. Рассмотрим несколько вариантов, как это можно сделать:

  • После авторизации все скрипты защищенной части вызываются с неким флажком вида adminmode=1. (Не надо смеяться — я сам такое видел). Ясно, что любой, кому известен флажок adminmode, может сам сформировать URL и зайти в режиме администрирования. Кроме того — нет возможности отличить одного пользователя от другого.
  • Скрипт авторизации может каким-нибудь образом передать имя пользователя другим скриптам. Распространено во многих www-чатах — для того, чтобы отличить, где чье сообщение идет, рядом с формой типа text для ввода сообщения, пристраивается форма типа hidden, где указывается имя пользователя. Тоже ненадежно, потому что хакер может скачать документ с формой к себе на диск и поменять значение формы hidden. Некоторую пользу здесь может принести вышеупомянутая проверка HTTP_REFERER — но, как я уже говорил, никаких гарантий она не дает.
  • Определение пользователя по IP-адресу. В этом случае, после прохождения авторизации, где-нибудь в локальной базе данных (sql, dbm, да хоть в txt-файле) сохраняется текущий IP пользователя, а все скрипты защищенной части смотрят в переменную REMOTE_ADDR и проверяют, есть ли такой адрес в базе. Если есть — значит, авторизация была, если нет — «hacker? he-he. » :-)Это более надежный способ — не пройти авторизацию и получить доступ удастся лишь в том случае, если с того же IP сидит другой пользователь, успешно авторизовавшийся. Однако, учитывая распространенность прокси-серверов и IP-Masquerad’инга — это вполне реально.
  • Единственным, известным мне простым и достаточно надежным способом верификации личности пользователя является авторизация при помощи random uid. Рассмотрим ее более подробно.

После авторизации пользователя скрипт, проведший авторизацию, генерирует достаточно длинное случайное число:

Это число он:а) заносит в локальный список авторизовавшихся пользователей;б) Выдает пользователю.

Пользователь при каждом запросе, помимо другой информации (сообщение в чате, или список сообщений в гостевой книге), отправляет серверу свой uid. При этом в документе с формами ввода будет присутствовать, наряду с другими формами, тег вида:

Форма uid невидима для пользователя, но она передается скрипту защищенной части приложения. Тот сличает переданный ему uid с uid’ом, хранящимся в локальной базе и либо выполняет свою функцию, либо. «hacker? he- he. «.

Единственное, что необходимо сделать при такой организации — периодически чистить локальный список uid’ов и/ или сделать для пользователя кнопку «выход», при нажатии на которую локальный uid пользователя сотрется из базы на сервере — сессия закрыта.

Некоторые программисты используют в качестве uid не «одноразовое» динамически генерирующееся число, а пароль пользователя. Это допустимо, но это является «дурным тоном», поскольку пароль пользователя обычно не меняется от сессии к сессии, а значит — хакер сможет сам открывать сессии. Та же самая модель может быть использована везде, где требуется идентификация пользователя — в чатах, веб-конференциях, электронных магазинах.

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

При ведении лог-файлов, необходимо помнить, что доступ к ним должен быть только у Вас. Лучше всего, если они будут расположены за пределами дерева каталогов, доступного через WWW. Если нет такой возможности — создайте отдельный каталог для лог-файлов и закройте туда доступ при помощи .htaccess (Deny from all).

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

Илон Маск рекомендует:  Что такое код hw_getobjectbyquery
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL