В пятницу 6 апреля 2018 началась мощная атака на оборудование Cisco.
Много пишут о том, что главная причина, по которой эта атака успешна, это открытые во внешние сети сервисные порты Cisco Smart Install.
Эти порты открыты по умолчанию. А люди в массе своей оставляют то, что сконфигурировано/выбрано/настроено таким, каким оно было по умолчанию. Как видим, на примере этого случая, это касается не только домашних роутеров, но и серьёзного оборудования в крупных компаниях, где цена ошибки значительно выше.
При создании системы вы не имеете права расчитывать на то, что значения по умолчанию, которые следует изменить будут изменены, причём в нужную сторону.
Вы лишь можете заставить изменить эти значения с помощью каких либо ограничивающих использование приёмов. Чему многие будут не рады. «Защита от дурака» это один из примеров этих обязывающих ограничений.
На русском подробнее.
В ней видно, что число тех, кто готов участвовать в программе донорства органов сильно зависит от того, какой выбор по умолчанию уже сделан в медицинской анкете.
Я хочу обратить внимание на корень самой уязвимости. В отчёте есть такая часть:
Переполнение буфера происходит в функции smi_ibc_handle_ibd_init_discovery_msgТ.е. при получении данных из вне не происходит проверки на их корректность.
из-за того, что при копировании данных в буфер фиксированного размера их размер не проверяется. Размер данных и они сами напрямую берутся из сетевого пакета.
Я считаю, что это то главное напоминание, которое нужно сделать в очередной раз.
Программист должен проверять данные, поступающие из вне. Никаким данным, поступившим в систему со стороны пользователя(кто бы и что бы им ни было), нельзя доверять.
P.S. Кстати, эта функция как раз примеров того, что программист просто взял значение по умолчанию, оттуда, где оно есть — из сетевого пакета.
Комментарии (44)
xjesus666christx
07.04.2018 21:00+1Программист должен проверять данные, поступающие из вне
Это очень правильная и ёмкая формулировка. Именно поступающие извне. К сожалению очень часто встречался с ситуациями, когда этот совет воспринимается «черезчур», и код из логики превращается в череду проверок на валидность данных.VolCh
07.04.2018 22:00+2Корректнее «из неконтролируемого окружения», а таковым может быть и сидящий рядом коллега через 5 минут, и ты сам через пару лет.
И по умолчанию лучше перебдеть, чем недобдеть. Лишние проверки уберутся при профайлинге, когда начнётся этап оптимизации, а вот отсутствующие заметить гораздо сложнее по их сути.khim
08.04.2018 17:39Вот как раз из-за «лучше перебдеть, чем недобдеть» мы имеем кучу дыр.
Потому что каждая проверка — это потенциальная ошибка. Если не сегодня — то завтра.
А юниттесты на все проверки тем более никто не пишет.
Потому проверять нужно именно данные поступающие извне и вашей программой не контролирующиеся.
Внутри же — лучше (== надёжнее) применять принцип GIGO.VolCh
10.04.2018 05:52Есть проверка — есть вероятность дыры, нет проверки — нет дыры, так что ли?
Я о том, что считать "извне". Вот пишу я библиотеку какую-то или ядро какой-то системы, для внутреннего пользования чисто. Могу я рассчитывать, что коллеги сделают все необходимые проверки, если я явно вижу возможную дыру? Да, я её задокументирую, даже юнит-тест напишу testDangerousCanInjectCode. Есть у меня гарантии, что коллеги проверку сделают, что ни один из сотен разработчиков компании не забудет? Не должен ли я на своём уровне позаботиться?
interprise
07.04.2018 22:14-15Давно очевидно что на c/c++ невозможно написать софт без уязвимость, используйте rust.
TimsTims
08.04.2018 01:57+2Из вашего утверждения следует, что весь софт написанный на С и С++ является уязвимым, и уязвимость проявляется в самом языке. Значит бесчисленное множество программ являются уязвимыми, из-за плохого языка, а не из-за
рукожопоститаланта разработчиков. Значит, для верности утверждения, вам попросту нужно доказать, что любая программа написанная на С/С++ уязвима по умолчанию. До этих пор, ваше утверждение ложно.interprise
08.04.2018 10:06+1В розовом мире поней, вы правы. Давайте посмотрим на факты, у google не получилось написать софт без «дырок» и у Microsoft не получилось, и у apple не получилось, у VMware не получилось и даже у opensource сообщества Linux не получилось. Ладно, виноваты разработчики, но сам факт того, что ни у одной крупной компании не получилось наводит на мысль, что если это и возможно, то только в шаровидном мире в вакууме, если не использовать библиотеки и писать софт уровня hello world.
reversecode
08.04.2018 11:24Дайте определение «не получилось»? что бы не получилось — нужно хотя бы пробовать, а никто из озвученных у вас даже не пытались.
struvv
08.04.2018 13:54Позволю ответить себе — Не получилось написать софт, в котором в длительный период времени нуль уязвимостей, позволяющих произвольно выполнить код.
Представь, так дом, в котором ты живёшь, бы строили — рухнул, так бы мы выяснили, что рандомный строитель — рукожоп
Только тебе от этого ни жарко, ни холодно, не так ли? Поэтому есть определённые ограничения, мешающие рандомному строителю привести к обрушению дома.reversecode
08.04.2018 14:31-1Еще раз повторяю, никто из компаний перечисленных вами не пытался писать безглючный софт. Если бы вы были знакомы со сферой разработки ПО не по слухам, вы бы такой дичи не писали. Я ниже дал намек на дешевую раб силу с индии… но мало кто понял мой намек. Продолжайте дальше верить что проблема дырявого софта, в языке на котором он разрабатывается.
Grox Автор
08.04.2018 14:45Язык/компилятор всё же могут значительно помочь с тем, чтобы не плодить дыры. Для примера, те же JavaScript в лице TypeScript и PHP обзавелись поддержкой «сильной», на сколько возможно, типизации. И это сильно помогает писать сложные крупные системы.
WarFair
08.04.2018 15:41Я не знаток TypeScript, но тем не менее (это более вопрос для саморазвития нежели остальные негативные интерпретации, но) разве строгая типизация поможет защититься от XSS или же от SQL Injection в голом но типизированном PHP?
Grox Автор
08.04.2018 15:48От SQL инъекций вас должны защитить Prepared Statements в PDO.
Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL-инъекций случиться не может (однако, если другие части текста запроса речь идет именно о параметрах).
Grox Автор
08.04.2018 16:40Ну и если вы из данных от пользователя формируете сами команды запроса, то без вашей проверки PDO вас уже не спасёт.
Grox Автор
08.04.2018 15:53Касательно XSS не поможет. Но это вполне нормально. Это задача архитектуры проекта, чтобы наставить ограничений и защиты от дурака. Вы же не можете требовать, чтобы язык защитил вас от логических ошибок?
WarFair
08.04.2018 16:17+1Конечно, я не требую от ЯП такой защиты. ибо как уже сказали это дело архитектуры. Как я понимаю, лучшее что в случае XSS или SQL Injection можно сделать, это не доверять входным данным, а то как проверка будет делаться под капотом зависит от языка и инструментов. Тоже самое будет работать в случае статьи —
из-за того, что при копировании данных в буфер фиксированного размера их размер не проверяется. Размер данных и они сами напрямую берутся из сетевого пакета.
— не доверяй тому что прислали и перепроверяй. В известных мне ЯП все позволяли определить размер полученных данных, но даже если и такого сделать нельзя, то всегда можно написать нечто вроде
byte *buffer = new byte [sizeFromOtherSide]; memcpy(buffer, dataFromOtherSide, sizeFromOtherSide);
Хотя я бы тут тоже сделал проверку на максимальный размер буффера, который можно создать…
slashd
09.04.2018 10:39khim
09.04.2018 19:19Заметите, что в обоих языках нет указателей и вообще они как бы от многих проблем C/C++ защищены на уровне дизайна… что не мешает массе веб-сайтов иметь массу дыр в их простеньких скриптах на PHP/JavaScript… в десятки раз больше, чем количество дыр в миллионах строк C/C++ кода, над которым их поделие сооружено.
Grox Автор
09.04.2018 22:23Не нужно смешивать уязвимость в вашем коде и уязвимость в чужом коде. Ваша ответственность за ваш код. Ответственность за безопасную работу проекта в целом, должна лежать на соответствующей команде.
slashd
09.04.2018 23:36Вы похоже не понимаете того, что люди пишут бажный код не из-за собственной глупости или желания писать плохо?
Может быть код был слишком сырым для внедрения в готовый продукт, но программиста поторопили? Мб программист который его писал и должен был довести его до нормального состояния уволился? Может быть код начали писать ещё в начале нулевых, когда всё это не было на слуху? Тут куча «может быть». Винить людей в том, что они «не проверяют входящие значения» не обладая фактами… ну это как минимум недальновидно… Баги будут всегда, и не только «buffer overflow». Предоставьте свой достаточно сложный проект без багов или… Ну в общем «boot up or shut up» :)Grox Автор
09.04.2018 23:39Кстати, нулевые ничем не отличались от десятков предыдущих лет. Входные данные так же надо было проверять.
interprise
08.04.2018 17:44я не хочу вступать в эту тупую демагогию. Покажите мне хотябы 1 крупный проект на плюсах без уязвимость? О чем речь вообще? всегда можно сказать «не пытались».
khim
08.04.2018 21:58Only two remote holes in the default install, in a heck of a long time!
А если вы начнёте выступать на тему «что вот — у них всё таки пара дыр нашлась», то я напомню вам что лет 15 назад фраза звучала как five years without a remote hole in the default install! и потребую какую-нибудь вещь на rust'е, в которой за 5 лет ничего не нашли и за 10 — не более одной дыры… так, для сравнения.
P.S. Я, кстати, очень благожелательно отношусь к rust'у. Но очень не люблю его фанатиков, которые пытаются представить его как «серебрянную пулю». Мозги — ни один язык программирования не заменит, извините…
struvv
09.04.2018 00:00+1Ad hominem.
Я тоже намекнул, что дома строят ещё более дешёвой раб силой, но они как-то не рушатся массово, кроме случаев совсем диких нарушений.
Строить и программировать будут и далее настолько дешёвыми ресурсами, какие есть это реалии жизни и под них нужно и выбирать/делать инструментыDmitriyDev
10.04.2018 09:15Извините, но про дома, которые рушаться, сравнение не корректное. Дыры — это скорее как окна — которые можно разбить, или двери с замками вскрываемые за минуту профессионалом.
Рушащиеся дома таки присутствуют, как и приложения, которые крешаться сразу после запуска, но это скорее исключения.
cyberzx23
09.04.2018 00:29У NASA получилось. Думаю, есть ещё куча компаний, которые пишут софт повышенной надёжности, у которого нет уязвимостей. В том числе и на языке С.
iCpu
09.04.2018 07:48В розовом мире поней и вы правы. А в реальном мире везде есть нюансы.Взять, например, ваше строгое утверждение. Для того, чтобы его опровергнуть, достаточно привести 1 (одну) программу, написанную на c++ и не имеющую уязвимости, и 1 (одну) на rust, имеющую в себе уязвимость.
Первое условие выполняется очень просто, достаточно написать
Второе сделать так же не сложно: открываем hg.mozilla.org и делаем фильтр по ".rs", получаем ненулевое число ошибок. Строгое утверждение опровергнуто. Там же можно посмотреть сводку файлов и обнаружить достаточно компонент на c++ без уязвимостей.int main() { return 0; }
a0fs
08.04.2018 14:17+1Можно, но нужно всё контролировать, потому что этого не делает машина, а язык С и С++, теми частями которыми он С, даёт кодеру всего лишь машину, не влезая со своими тараканами между ними (за то и высоко ценится, отлично портируется, и нежно любим). А попыток решить проблемы кодеров языком была масса и Rust здесь не пионер и даже не крайний. И да, когда всё будет писаться на Rust, ещё нужно будет посмотреть, что легче, искать проблемы в более или менее читаемом C или в хитросплетениях архитектурных изысков Rust. Да на С можно писать «красиво», но тогда на Rust можно писать «божественно», ибо там макросами можно намутить такой дичи, в которой и с дебагером и днём с огнём логику искать можно долго и развлекательно. А пока контролировать размер объектов не научится машина, этот мир не спасёт ничто.
potan
07.04.2018 23:15Хорошая система типов не позволит использовать непроверенные данные. Но типами программисты леняться пользоваться.
KorDen32
08.04.2018 12:27при копировании данных в буфер фиксированного размера их размер не проверяется
Heartbleed был ровно четыре года назад.
Sly_tom_cat
08.04.2018 13:37Буквально неделю назад объяснял разработчикам, что проверка входных данных в системе обмена данных с контрагентами — не блажь.
А аргумент «их все равно проверит принимающая сторона» — это из разряда «русского авось».
Проблема ведь в том, что принимающая сторона принимает эти данные от доверенной, и на той стороне уже вполне «естественно» доверять им… там принимающая процедура принимает данные и с FE (который старательно все валидирует и фильтрует) и от системы обмена данными с контрагентами.reversecode
08.04.2018 14:37Разработчикам ничего не надо объяснять, вы видимо с кем другим общались
Sly_tom_cat
08.04.2018 14:53+1Да вы правы, отчасти…
Объяснял я это ведущему разработчику, который в частности играет роль технического-эксперта, через которого проводятся все доработки в системе. И именно в роли технического эксперта ему и пришлось вдалбливать эти прописные истины.
Sabubu
08.04.2018 14:18"Никаким данным нельзя доверять" — это выглядит конечно красиво, но практически малополезно, так как не говорит программисту, что ему делать. Или говорит, что надо вообще не принимать данные от пользователя. Вместо этой фразы должны быть болеет подробные пояснения. Ну, хотя бы, "в данных от пользователя могут быть недостоверные сведения", "длина буфера в пакете может быть указана неверно".
Grox Автор
08.04.2018 14:20+1Программист должен проверять данные, поступающие из вне.
Там же это написано первым предложением. Ну и чуть выше слова про корректность.
И если программист обладает логическим мышлением и задумается о необходимости проверки, решение задачи как именно проверить он найдёт.
Evengard
А что это за дизассемблер с визуальным отображением ветвления? Я думал из таких сейчас только IDA есть
Mixaill
это и есть IDA
Evengard
Шо-то как-то она странно выглядит, привык видимо к другому оформлению.
Mixaill
Это она такую штуку по F12 рисует.
Readme
Radare2 тоже это умеет (а ещё он open source и просто вкусняшка). Да и вообще, ужель кто-то с гордым именем "дизассемблер" сейчас не сможет ветвление нарисовать?