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

Я всегда стараюсь предотвратить такие вещи, как инъекции. Однако, когда вы работаете на сайте внутренней интрасети, большинство функций безопасности кажутся потраченными впустую. Я до сих пор их делаю, может быть, просто не так хорошо.
Что ж, есть определенный набор лучших практик по безопасности. Как минимум, для приложений баз данных вам нужно остерегаться внедрения SQL.
Другие вещи, такие как хеширование паролей, шифрование строк подключения и т. д., Также являются стандартом.
С этого момента это зависит от конкретного приложения.
К счастью, если вы работаете с такими фреймворками, как .Net, многие средства защиты уже встроены.
Вы должны всегда программировать защитно, я бы сказал, даже для внутренних приложений, просто потому, что пользователи могут просто по счастливой случайности написать что-то, что сломает ваше приложение. Конечно, вам, вероятно, не нужно беспокоиться о том, чтобы попытаться обмануть вас, но все же. Всегда программируйте защитно и предполагайте, что приложение откажет.
В моей работе наш код должен быть высокого качества. Итак, акцентируем внимание на двух основных вещах:
Те приносят домой деньги.
Как и в случае с abyx, в моей команде разработчиков всегда используются модульные тесты и обзоры кода. В дополнение к этому, я также стремлюсь убедиться, что я не включаю код, который используют люди май - я обычно пишу код только для базового набора методов, необходимых для работы данного объекта, как было указано в спецификации. . Я обнаружил, что включение методов, которые, возможно, никогда не будут использоваться, но которые предоставляют функциональные возможности, может непреднамеренно ввести «бэкдор» или непреднамеренное / непредвиденное использование в системе.
Гораздо проще вернуться позже и ввести методы, атрибуты и свойства, которые запрашиваются, чем ожидать чего-то, что может никогда не появиться.
Использование разработки через тестирование, безусловно, помогает. Вы пишете по одному компоненту за раз, а затем перечисляете все возможные варианты входных данных (с помощью тестов) перед написанием кода. Это гарантирует, что вы охватили все основы и не написали код прохладно, который никто не будет использовать, но может сломаться.
Хотя я не делаю ничего формального, я обычно провожу некоторое время, просматривая каждый класс и удостоверяясь, что:
По-разному.
Если я действительно взламываю что-то для себя, я напишу лучший код, о котором мне не нужно думать. Пусть компилятор будет моим другом для предупреждений и т. д., Но я не буду автоматически создавать типы для этого.
Чем больше вероятность того, что код будет использоваться, даже изредка, я увеличиваю уровень проверок.
Я возьму другое определение защитного программирования, такое как то, которое поддерживает Эффективная Java Джоша Блоха. В книге он рассказывает о том, как обрабатывать изменяемые объекты, которые вызывающие объекты передают вашему коду (например, в сеттерах), и изменяемые объекты, которые вы передаете вызывающим объектам (например, в геттерах).
Главное сообщение - убедиться, что никакой внешний код не может содержать псевдоним для любых изменяемых объектов, которые вы используете внутри, чтобы вы могли поддерживать свои инварианты.
Я бы рекомендовал защищать данные, которые входят в «компонент» или структуру. В рамках «компонента» или структуры следует думать, что данные «правильные».
Думая так. Вызывающий должен предоставить правильные параметры, в противном случае ВСЕ функции и методы должны проверять каждый входящий параметр. Но если проверка выполняется только для вызывающего абонента, проверка требуется только один раз. Таким образом, параметр должен быть «правильным» и, таким образом, может передаваться на более низкие уровни.
Если есть ошибка и в вызове используется неправильное значение. Что действительно нужно делать? У одного есть только указание на то, что «данные», над которыми работает программа, неверны, и некоторым нравится ASSERTS, но другие хотят использовать расширенный отчет об ошибках и возможное восстановление после ошибок. В любом случае обнаруживается, что данные ошибочны, и в некоторых случаях полезно продолжить работу над ними. (учтите, хорошо, если серверы хотя бы не умирают)
Изображение, отправленное со спутника, может быть случаем, чтобы попробовать расширенное восстановление после ошибок на ... изображении, загруженном из Интернета, чтобы добавить значок ошибки для ...
Я очень считаю, что правильное программирование защитит от этих рисков. Такие вещи, как избегание устаревших функций, которые (по крайней мере, в библиотеках Microsoft C++) обычно не рекомендуются из-за уязвимостей безопасности, и проверка всего, что пересекает внешние границы.
Функции, которые вызываются только из вашего кода, не должны требовать чрезмерной проверки параметров, потому что вы управляете вызывающим, то есть никакие внешние границы не пересекаются. Функции, вызываемые чужим кодом, должны предполагать, что входящие параметры в какой-то момент будут недопустимыми и / или вредоносными.
Мой подход к работе с открытыми функциями состоит в том, чтобы просто аварийно завершить работу с полезным сообщением, если это возможно. Если вызывающий абонент не может правильно получить параметры, значит, проблема в их коде, и они должны исправить это, а не вы. (Очевидно, вы предоставили документацию для своей функции, поскольку она доступна.)
Внедрение кода является проблемой только в том случае, если ваше приложение способно повысить уровень текущего пользователя. Если процесс может внедрить код в ваше приложение, он может легко записать код в память и в любом случае выполнить его. Без возможности получить полный доступ к системному вводу кода атаки бессмысленны. (Вот почему приложения, используемые администраторами, не должны быть доступны для записи меньшими пользователями.)
По моему опыту, позитивное использование защитного программирования не обязательно означает, что вы в конечном итоге улучшаете качество своего кода. Не поймите меня неправильно, вам нужно защищать программу, чтобы улавливать виды проблем, с которыми могут столкнуться пользователи - пользователям не нравится, когда ваша программа вылетает на них - но это вряд ли упростит сопровождение кода, тест и др.
Несколько лет назад мы установили политику использования утверждений на всех уровнях нашего программного обеспечения, и это - наряду с модульным тестированием, обзорами кода и т. д., А также нашими существующими наборами тестов приложений - оказало значительное положительное влияние на качество нашего кода.
Я рекомендую людям писать фашистский код в среде разработки и доброжелательный в производственной среде.
Во время разработки вы хотите как можно раньше выявлять плохие данные / логику / код, чтобы предотвратить проблемы, которые либо останутся незамеченными, либо приведут к последующим проблемам, причину которых трудно отследить.
На производстве решайте проблемы максимально изящно. Если что-то действительно является неисправимой ошибкой, обработайте ее и предоставьте эту информацию пользователю.
В качестве примера приведем наш код для нормализации вектора. Если вы скармливаете ему плохие данные в разработке, он будет кричать, в производстве он возвращает безопасное значение.
inline const Vector3 Normalize( Vector3arg vec )
{
const float len = Length(vec);
ASSERTMSG(len > 0.0f "Invalid Normalization");
return len == 0.0f ? vec : vec / len;
}
Мы используем аналогичный способ «увеличить» обнаружение проблем в устаревшем коде. Макрос легко добавить, его единственный эффект - это окно сообщения отладки во время тестирования. Это не чудо, но оно лучше, чем «return FALSE»; никто никогда не проверяет
Java, подписанные JAR-файлы и JAAS.
Java для предотвращения переполнения буфера и взлома указателя / стека.
Не используйте JNI. (Java Native Interface) он предоставляет вам DLL / общие библиотеки.
Подписанные JAR-файлы, чтобы загрузка класса перестала быть проблемой безопасности.
JAAS может позволить вашему приложению не доверять никому, даже самому себе.
J2EE имеет (по общему признанию, ограниченную) встроенную поддержку безопасности на основе ролей.
Для некоторых из них есть некоторые накладные расходы, но дыры в безопасности исчезнут.
Простой ответ: По-разному. Слишком много защитного кода может вызывает серьезные проблемы с производительностью.
То, что вы описываете, также известно как YAGNI - en.wikipedia.org/wiki/YAGNI