Вопрос

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

Каков "минимальный" уровень качества, который вы всегда будете применять к своему коду?

Это было полезно?

Решение

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

  1. Тестирование
  2. Обзоры кода

Они приносят домой деньги.

Другие советы

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

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

Я бы рекомендовал защищать данные, которые входят в "компонент" или фреймворк.В рамках "компонента" или фреймворка следует думать, что данные "правильные".

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

  1. Всегда проверяйте данные из внешних источников, пользователей и т. Д
  2. "Компонент" или фреймворк всегда должен проверять входящие вызовы.

Если обнаружена ошибка и в вызове используется неправильное значение.Что на самом деле нужно сделать?У одних есть только указание на то, что "данные", с которыми работает программа, неверны, и некоторым нравится это УТВЕРЖДАТЬ, но другие хотят использовать расширенные отчеты об ошибках и возможное восстановление после них.В любом случае данные оказываются ошибочными, и в некоторых случаях полезно продолжить работу над ними.(обратите внимание, что хорошо, если серверы хотя бы не умрут)

Изображение, отправленное со спутника, может быть поводом для использования расширенного восстановления после ошибок on...an изображение, загруженное из Интернета, для отображения значка ошибки...

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

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

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

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

inline const Vector3 Normalize( Vector3arg vec )
{
    const float len = Length(vec);
    ASSERTMSG(len > 0.0f "Invalid Normalization");
    return len == 0.0f ? vec : vec / len;
}

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

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

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

С этого момента это зависит от конкретного приложения.

К счастью, если вы работаете с такими фреймворками, как .Net, в них встроено множество средств защиты.

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

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

Хотя я не делаю ничего формального, я обычно провожу некоторое время, просматривая каждый класс и убеждаясь, что:

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

Это зависит от обстоятельств.

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

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

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

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

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

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

Я твердо придерживаюсь мнения, что правильное программирование защитит от этих рисков.Такие вещи, как отказ от устаревших функций, которые (по крайней мере, в библиотеках Microsoft C ++) обычно не рекомендуются из-за уязвимостей в системе безопасности, и проверка всего, что пересекает внешнюю границу.

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

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

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

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

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

Java, подписанный JARs и JAAS.

Java для предотвращения переполнения буфера и эксплойтов, связанных с взломом указателя / стека.

Не используйте JNI.(Собственный интерфейс Java) он предоставляет вам доступ к DLL / разделяемым библиотекам.

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

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

J2EE имеет (по общему признанию, ограниченную) встроенную поддержку безопасности на основе ролей.

Для некоторых из них требуются некоторые накладные расходы, но дыры в безопасности устраняются.

Простой ответ: Это зависит.Слишком много защитного кодирования может вызывают серьезные проблемы с производительностью.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top