Comments 45
Программист должен проверять данные, поступающие из вне
Это очень правильная и ёмкая формулировка. Именно поступающие извне. К сожалению очень часто встречался с ситуациями, когда этот совет воспринимается «черезчур», и код из логики превращается в череду проверок на валидность данных.
И по умолчанию лучше перебдеть, чем недобдеть. Лишние проверки уберутся при профайлинге, когда начнётся этап оптимизации, а вот отсутствующие заметить гораздо сложнее по их сути.
Потому что каждая проверка — это потенциальная ошибка. Если не сегодня — то завтра.
А юниттесты на все проверки тем более никто не пишет.
Потому проверять нужно именно данные поступающие извне и вашей программой не контролирующиеся.
Внутри же — лучше (== надёжнее) применять принцип GIGO.
Есть проверка — есть вероятность дыры, нет проверки — нет дыры, так что ли?
Я о том, что считать "извне". Вот пишу я библиотеку какую-то или ядро какой-то системы, для внутреннего пользования чисто. Могу я рассчитывать, что коллеги сделают все необходимые проверки, если я явно вижу возможную дыру? Да, я её задокументирую, даже юнит-тест напишу testDangerousCanInjectCode. Есть у меня гарантии, что коллеги проверку сделают, что ни один из сотен разработчиков компании не забудет? Не должен ли я на своём уровне позаботиться?
Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL-инъекций случиться не может (однако, если другие части текста запроса речь идет именно о параметрах).
из-за того, что при копировании данных в буфер фиксированного размера их размер не проверяется. Размер данных и они сами напрямую берутся из сетевого пакета.— не доверяй тому что прислали и перепроверяй. В известных мне ЯП все позволяли определить размер полученных данных, но даже если и такого сделать нельзя, то всегда можно написать нечто вроде
byte *buffer = new byte [sizeFromOtherSide];
memcpy(buffer, dataFromOtherSide, sizeFromOtherSide);
Хотя я бы тут тоже сделал проверку на максимальный размер буффера, который можно создать…
Может быть код был слишком сырым для внедрения в готовый продукт, но программиста поторопили? Мб программист который его писал и должен был довести его до нормального состояния уволился? Может быть код начали писать ещё в начале нулевых, когда всё это не было на слуху? Тут куча «может быть». Винить людей в том, что они «не проверяют входящие значения» не обладая фактами… ну это как минимум недальновидно… Баги будут всегда, и не только «buffer overflow». Предоставьте свой достаточно сложный проект без багов или… Ну в общем «boot up or shut up» :)
А если вы начнёте выступать на тему «что вот — у них всё таки пара дыр нашлась», то я напомню вам что лет 15 назад фраза звучала как five years without a remote hole in the default install! и потребую какую-нибудь вещь на rust'е, в которой за 5 лет ничего не нашли и за 10 — не более одной дыры… так, для сравнения.
P.S. Я, кстати, очень благожелательно отношусь к rust'у. Но очень не люблю его фанатиков, которые пытаются представить его как «серебрянную пулю». Мозги — ни один язык программирования не заменит, извините…
Первое условие выполняется очень просто, достаточно написать
int main() { return 0; }
Второе сделать так же не сложно: открываем hg.mozilla.org и делаем фильтр по ".rs", получаем ненулевое число ошибок. Строгое утверждение опровергнуто. Там же можно посмотреть сводку файлов и обнаружить достаточно компонент на c++ без уязвимостей.Как Rust защитит, например, от Meltdown? Что делать, если твой sha1 скурвился быстрее, чем ты ожидал? Как подготовиться к тому, что опять Symantec? Как предусмотреть KRACK? А никак. Говно случается. И в этом никто не виноват. Кроме Symantec, конечно.
Но вы утверждаете, что во всём виноват C++. Нашли, блин, евреев мира IT! Не нужно вести себя, как неофит. Нравится rust — ржавите потихоньку, но не сходите с ума.
при копировании данных в буфер фиксированного размера их размер не проверяется
Heartbleed был ровно четыре года назад.
А аргумент «их все равно проверит принимающая сторона» — это из разряда «русского авось».
Проблема ведь в том, что принимающая сторона принимает эти данные от доверенной, и на той стороне уже вполне «естественно» доверять им… там принимающая процедура принимает данные и с FE (который старательно все валидирует и фильтрует) и от системы обмена данными с контрагентами.
Объяснял я это ведущему разработчику, который в частности играет роль технического-эксперта, через которого проводятся все доработки в системе. И именно в роли технического эксперта ему и пришлось вдалбливать эти прописные истины.
"Никаким данным нельзя доверять" — это выглядит конечно красиво, но практически малополезно, так как не говорит программисту, что ему делать. Или говорит, что надо вообще не принимать данные от пользователя. Вместо этой фразы должны быть болеет подробные пояснения. Ну, хотя бы, "в данных от пользователя могут быть недостоверные сведения", "длина буфера в пакете может быть указана неверно".
Проверяй входящие данные. Исходная причина уязвимости и атаки на Cisco IOS