Проверяй входящие данные. Исходная причина уязвимости и атаки на Cisco IOS

    Cisco IOS function weak

    В пятницу 6 апреля 2018 началась мощная атака на оборудование Cisco.

    Много пишут о том, что главная причина, по которой эта атака успешна, это открытые во внешние сети сервисные порты Cisco Smart Install.

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

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

    Вы лишь можете заставить изменить эти значения с помощью каких либо ограничивающих использование приёмов. Чему многие будут не рады. «Защита от дурака» это один из примеров этих обязывающих ограничений.

    Про выбор по умолчанию
    Есть исследование 2003 года «Спасает ли жизни выбор по умолчанию?», в котором есть диаграмма

    image

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

    Я хочу обратить внимание на корень самой уязвимости. В отчёте есть такая часть:
    Переполнение буфера происходит в функции smi_ibc_handle_ibd_init_discovery_msg

    Cisco IOS function weak
    из-за того, что при копировании данных в буфер фиксированного размера их размер не проверяется. Размер данных и они сами напрямую берутся из сетевого пакета.
    Т.е. при получении данных из вне не происходит проверки на их корректность.

    Я считаю, что это то главное напоминание, которое нужно сделать в очередной раз.

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

    P.S. Кстати, эта функция как раз примеров того, что программист просто взял значение по умолчанию, оттуда, где оно есть — из сетевого пакета.

    Only registered users can participate in poll. Log in, please.

    В вашем программном продукте используется проверка входящих данных?

    • 47%Да, на уровне фреймворка/системы47
    • 53%Да, вручную53
    • 19%Нет, продукт внутренний19
    • 5%Нет, продукт для стороннего использования5
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 45

      0
      А что это за дизассемблер с визуальным отображением ветвления? Я думал из таких сейчас только IDA есть
        0
        это и есть IDA
          0
          Шо-то как-то она странно выглядит, привык видимо к другому оформлению.
            0
            Это она такую штуку по F12 рисует.
          0

          Radare2 тоже это умеет (а ещё он open source и просто вкусняшка). Да и вообще, ужель кто-то с гордым именем "дизассемблер" сейчас не сможет ветвление нарисовать?

          +1
          Программист должен проверять данные, поступающие из вне

          Это очень правильная и ёмкая формулировка. Именно поступающие извне. К сожалению очень часто встречался с ситуациями, когда этот совет воспринимается «черезчур», и код из логики превращается в череду проверок на валидность данных.
            +2
            Корректнее «из неконтролируемого окружения», а таковым может быть и сидящий рядом коллега через 5 минут, и ты сам через пару лет.

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

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

              А юниттесты на все проверки тем более никто не пишет.

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

              Внутри же — лучше (== надёжнее) применять принцип GIGO.
                0

                Есть проверка — есть вероятность дыры, нет проверки — нет дыры, так что ли?


                Я о том, что считать "извне". Вот пишу я библиотеку какую-то или ядро какой-то системы, для внутреннего пользования чисто. Могу я рассчитывать, что коллеги сделают все необходимые проверки, если я явно вижу возможную дыру? Да, я её задокументирую, даже юнит-тест напишу testDangerousCanInjectCode. Есть у меня гарантии, что коллеги проверку сделают, что ни один из сотен разработчиков компании не забудет? Не должен ли я на своём уровне позаботиться?

            –17
            Давно очевидно что на c/c++ невозможно написать софт без уязвимость, используйте rust.
              +3
              Из вашего утверждения следует, что весь софт написанный на С и С++ является уязвимым, и уязвимость проявляется в самом языке. Значит бесчисленное множество программ являются уязвимыми, из-за плохого языка, а не из-за рукожопости таланта разработчиков. Значит, для верности утверждения, вам попросту нужно доказать, что любая программа написанная на С/С++ уязвима по умолчанию. До этих пор, ваше утверждение ложно.
                –3
                А много вы найдете известных демонов на сях где ни разу не было RCE?
                  +1
                  В розовом мире поней, вы правы. Давайте посмотрим на факты, у google не получилось написать софт без «дырок» и у Microsoft не получилось, и у apple не получилось, у VMware не получилось и даже у opensource сообщества Linux не получилось. Ладно, виноваты разработчики, но сам факт того, что ни у одной крупной компании не получилось наводит на мысль, что если это и возможно, то только в шаровидном мире в вакууме, если не использовать библиотеки и писать софт уровня hello world.
                  • UFO just landed and posted this here
                      –2
                      Позволю ответить себе — Не получилось написать софт, в котором в длительный период времени нуль уязвимостей, позволяющих произвольно выполнить код.

                      Представь, так дом, в котором ты живёшь, бы строили — рухнул, так бы мы выяснили, что рандомный строитель — рукожоп

                      Только тебе от этого ни жарко, ни холодно, не так ли? Поэтому есть определённые ограничения, мешающие рандомному строителю привести к обрушению дома.
                      • UFO just landed and posted this here
                          0
                          Язык/компилятор всё же могут значительно помочь с тем, чтобы не плодить дыры. Для примера, те же JavaScript в лице TypeScript и PHP обзавелись поддержкой «сильной», на сколько возможно, типизации. И это сильно помогает писать сложные крупные системы.
                            +1
                            Я не знаток TypeScript, но тем не менее (это более вопрос для саморазвития нежели остальные негативные интерпретации, но) разве строгая типизация поможет защититься от XSS или же от SQL Injection в голом но типизированном PHP?
                              0
                              От SQL инъекций вас должны защитить Prepared Statements в PDO.
                              Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL-инъекций случиться не может (однако, если другие части текста запроса речь идет именно о параметрах).
                                0
                                Ну и если вы из данных от пользователя формируете сами команды запроса, то без вашей проверки PDO вас уже не спасёт.
                                0
                                Касательно XSS не поможет. Но это вполне нормально. Это задача архитектуры проекта, чтобы наставить ограничений и защиты от дурака. Вы же не можете требовать, чтобы язык защитил вас от логических ошибок?
                                  +1
                                  Конечно, я не требую от ЯП такой защиты. ибо как уже сказали это дело архитектуры. Как я понимаю, лучшее что в случае XSS или SQL Injection можно сделать, это не доверять входным данным, а то как проверка будет делаться под капотом зависит от языка и инструментов. Тоже самое будет работать в случае статьи —
                                  из-за того, что при копировании данных в буфер фиксированного размера их размер не проверяется. Размер данных и они сами напрямую берутся из сетевого пакета.
                                  — не доверяй тому что прислали и перепроверяй. В известных мне ЯП все позволяли определить размер полученных данных, но даже если и такого сделать нельзя, то всегда можно написать нечто вроде
                                  byte *buffer = new byte [sizeFromOtherSide];
                                  memcpy(buffer, dataFromOtherSide, sizeFromOtherSide);
                                  

                                  Хотя я бы тут тоже сделал проверку на максимальный размер буффера, который можно создать…
                                0
                                Язык/компилятор всё же могут значительно помочь с тем, чтобы не плодить дыры.

                                PHP
                                JavaScript
                                  0
                                  Заметите, что в обоих языках нет указателей и вообще они как бы от многих проблем C/C++ защищены на уровне дизайна… что не мешает массе веб-сайтов иметь массу дыр в их простеньких скриптах на PHP/JavaScript… в десятки раз больше, чем количество дыр в миллионах строк C/C++ кода, над которым их поделие сооружено.
                                    0
                                    Не нужно смешивать уязвимость в вашем коде и уязвимость в чужом коде. Ваша ответственность за ваш код. Ответственность за безопасную работу проекта в целом, должна лежать на соответствующей команде.
                                      0
                                      Вы похоже не понимаете того, что люди пишут бажный код не из-за собственной глупости или желания писать плохо?
                                      Может быть код был слишком сырым для внедрения в готовый продукт, но программиста поторопили? Мб программист который его писал и должен был довести его до нормального состояния уволился? Может быть код начали писать ещё в начале нулевых, когда всё это не было на слуху? Тут куча «может быть». Винить людей в том, что они «не проверяют входящие значения» не обладая фактами… ну это как минимум недальновидно… Баги будут всегда, и не только «buffer overflow». Предоставьте свой достаточно сложный проект без багов или… Ну в общем «boot up or shut up» :)
                                        0
                                        Моя статья это напоминание. Никак не обвинение.
                                          0
                                          Кстати, нулевые ничем не отличались от десятков предыдущих лет. Входные данные так же надо было проверять.
                                    –2
                                    я не хочу вступать в эту тупую демагогию. Покажите мне хотябы 1 крупный проект на плюсах без уязвимость? О чем речь вообще? всегда можно сказать «не пытались».
                                      +2
                                      Only 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'у. Но очень не люблю его фанатиков, которые пытаются представить его как «серебрянную пулю». Мозги — ни один язык программирования не заменит, извините…
                                      +1
                                      Ad hominem.

                                      Я тоже намекнул, что дома строят ещё более дешёвой раб силой, но они как-то не рушатся массово, кроме случаев совсем диких нарушений.

                                      Строить и программировать будут и далее настолько дешёвыми ресурсами, какие есть это реалии жизни и под них нужно и выбирать/делать инструменты
                                        0
                                        Извините, но про дома, которые рушаться, сравнение не корректное. Дыры — это скорее как окна — которые можно разбить, или двери с замками вскрываемые за минуту профессионалом.

                                        Рушащиеся дома таки присутствуют, как и приложения, которые крешаться сразу после запуска, но это скорее исключения.
                                          0
                                          Я совсем забыл напомнить, что мы в контексте циски.

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

                                          Вот в цисках недопустимо писать код, в котором могут возникать такие дыры, ценник не соответствует качеству, это как не закрывающаяся дверь в порше
                                  0
                                  У NASA получилось. Думаю, есть ещё куча компаний, которые пишут софт повышенной надёжности, у которого нет уязвимостей. В том числе и на языке С.
                                    +2
                                    В розовом мире поней и вы правы. А в реальном мире везде есть нюансы.
                                    Взять, например, ваше строгое утверждение. Для того, чтобы его опровергнуть, достаточно привести 1 (одну) программу, написанную на c++ и не имеющую уязвимости, и 1 (одну) на rust, имеющую в себе уязвимость.
                                    Первое условие выполняется очень просто, достаточно написать
                                    int main() { return 0; }
                                    Второе сделать так же не сложно: открываем hg.mozilla.org и делаем фильтр по ".rs", получаем ненулевое число ошибок. Строгое утверждение опровергнуто. Там же можно посмотреть сводку файлов и обнаружить достаточно компонент на c++ без уязвимостей.
                                    А теперь, если серьёзно, разработка безопасного ПО сегодня приближается к искусству чёрной магии. Совершенно не ясно, откуда тебе прилетит в следующую минуту, можно только быть уверенным в том, что будет больно. Примеры?
                                    Как Rust защитит, например, от Meltdown? Что делать, если твой sha1 скурвился быстрее, чем ты ожидал? Как подготовиться к тому, что опять Symantec? Как предусмотреть KRACK? А никак. Говно случается. И в этом никто не виноват. Кроме Symantec, конечно.

                                    Но вы утверждаете, что во всём виноват C++. Нашли, блин, евреев мира IT! Не нужно вести себя, как неофит. Нравится rust — ржавите потихоньку, но не сходите с ума.
                                  +2
                                  Можно, но нужно всё контролировать, потому что этого не делает машина, а язык С и С++, теми частями которыми он С, даёт кодеру всего лишь машину, не влезая со своими тараканами между ними (за то и высоко ценится, отлично портируется, и нежно любим). А попыток решить проблемы кодеров языком была масса и Rust здесь не пионер и даже не крайний. И да, когда всё будет писаться на Rust, ещё нужно будет посмотреть, что легче, искать проблемы в более или менее читаемом C или в хитросплетениях архитектурных изысков Rust. Да на С можно писать «красиво», но тогда на Rust можно писать «божественно», ибо там макросами можно намутить такой дичи, в которой и с дебагером и днём с огнём логику искать можно долго и развлекательно. А пока контролировать размер объектов не научится машина, этот мир не спасёт ничто.
                                  0
                                  Хорошая система типов не позволит использовать непроверенные данные. Но типами программисты леняться пользоваться.
                                  • UFO just landed and posted this here
                                      +1
                                      при копировании данных в буфер фиксированного размера их размер не проверяется

                                      Heartbleed был ровно четыре года назад.

                                        +2
                                        Буквально неделю назад объяснял разработчикам, что проверка входных данных в системе обмена данных с контрагентами — не блажь.
                                        А аргумент «их все равно проверит принимающая сторона» — это из разряда «русского авось».

                                        Проблема ведь в том, что принимающая сторона принимает эти данные от доверенной, и на той стороне уже вполне «естественно» доверять им… там принимающая процедура принимает данные и с FE (который старательно все валидирует и фильтрует) и от системы обмена данными с контрагентами.
                                        • UFO just landed and posted this here
                                            +1
                                            Разработчики они разные, у кого какие в наличии.
                                              +1
                                              Да вы правы, отчасти…
                                              Объяснял я это ведущему разработчику, который в частности играет роль технического-эксперта, через которого проводятся все доработки в системе. И именно в роли технического эксперта ему и пришлось вдалбливать эти прописные истины.
                                            0

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

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

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

                                            Only users with full accounts can post comments. Log in, please.