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. Кстати, эта функция как раз примеров того, что программист просто взял значение по умолчанию, оттуда, где оно есть — из сетевого пакета.

Комментарии (44)


  1. Evengard
    07.04.2018 18:43

    А что это за дизассемблер с визуальным отображением ветвления? Я думал из таких сейчас только IDA есть


    1. Mixaill
      07.04.2018 20:05

      это и есть IDA


      1. Evengard
        09.04.2018 20:48

        Шо-то как-то она странно выглядит, привык видимо к другому оформлению.


        1. Mixaill
          09.04.2018 21:03

          Это она такую штуку по F12 рисует.


    1. Readme
      07.04.2018 20:25

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


  1. xjesus666christx
    07.04.2018 21:00
    +1

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

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


    1. VolCh
      07.04.2018 22:00
      +2

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

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


      1. khim
        08.04.2018 17:39

        Вот как раз из-за «лучше перебдеть, чем недобдеть» мы имеем кучу дыр.

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

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

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

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


        1. VolCh
          10.04.2018 05:52

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


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


  1. interprise
    07.04.2018 22:14
    -15

    Давно очевидно что на c/c++ невозможно написать софт без уязвимость, используйте rust.


    1. TimsTims
      08.04.2018 01:57
      +2

      Из вашего утверждения следует, что весь софт написанный на С и С++ является уязвимым, и уязвимость проявляется в самом языке. Значит бесчисленное множество программ являются уязвимыми, из-за плохого языка, а не из-за рукожопости таланта разработчиков. Значит, для верности утверждения, вам попросту нужно доказать, что любая программа написанная на С/С++ уязвима по умолчанию. До этих пор, ваше утверждение ложно.


      1. tgz
        08.04.2018 08:38
        -1

        А много вы найдете известных демонов на сях где ни разу не было RCE?


      1. interprise
        08.04.2018 10:06
        +1

        В розовом мире поней, вы правы. Давайте посмотрим на факты, у google не получилось написать софт без «дырок» и у Microsoft не получилось, и у apple не получилось, у VMware не получилось и даже у opensource сообщества Linux не получилось. Ладно, виноваты разработчики, но сам факт того, что ни у одной крупной компании не получилось наводит на мысль, что если это и возможно, то только в шаровидном мире в вакууме, если не использовать библиотеки и писать софт уровня hello world.


        1. reversecode
          08.04.2018 11:24

          Дайте определение «не получилось»? что бы не получилось — нужно хотя бы пробовать, а никто из озвученных у вас даже не пытались.


          1. struvv
            08.04.2018 13:54

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

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

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


            1. reversecode
              08.04.2018 14:31
              -1

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


              1. Grox Автор
                08.04.2018 14:45

                Язык/компилятор всё же могут значительно помочь с тем, чтобы не плодить дыры. Для примера, те же JavaScript в лице TypeScript и PHP обзавелись поддержкой «сильной», на сколько возможно, типизации. И это сильно помогает писать сложные крупные системы.


                1. WarFair
                  08.04.2018 15:41

                  Я не знаток TypeScript, но тем не менее (это более вопрос для саморазвития нежели остальные негативные интерпретации, но) разве строгая типизация поможет защититься от XSS или же от SQL Injection в голом но типизированном PHP?


                  1. Grox Автор
                    08.04.2018 15:48

                    От SQL инъекций вас должны защитить Prepared Statements в PDO.

                    Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL-инъекций случиться не может (однако, если другие части текста запроса речь идет именно о параметрах).


                    1. Grox Автор
                      08.04.2018 16:40

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


                  1. Grox Автор
                    08.04.2018 15:53

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


                    1. WarFair
                      08.04.2018 16:17
                      +1

                      Конечно, я не требую от ЯП такой защиты. ибо как уже сказали это дело архитектуры. Как я понимаю, лучшее что в случае XSS или SQL Injection можно сделать, это не доверять входным данным, а то как проверка будет делаться под капотом зависит от языка и инструментов. Тоже самое будет работать в случае статьи —

                      из-за того, что при копировании данных в буфер фиксированного размера их размер не проверяется. Размер данных и они сами напрямую берутся из сетевого пакета.
                      — не доверяй тому что прислали и перепроверяй. В известных мне ЯП все позволяли определить размер полученных данных, но даже если и такого сделать нельзя, то всегда можно написать нечто вроде
                      byte *buffer = new byte [sizeFromOtherSide];
                      memcpy(buffer, dataFromOtherSide, sizeFromOtherSide);
                      

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


                1. slashd
                  09.04.2018 10:39

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

                  PHP
                  JavaScript


                  1. khim
                    09.04.2018 19:19

                    Заметите, что в обоих языках нет указателей и вообще они как бы от многих проблем C/C++ защищены на уровне дизайна… что не мешает массе веб-сайтов иметь массу дыр в их простеньких скриптах на PHP/JavaScript… в десятки раз больше, чем количество дыр в миллионах строк C/C++ кода, над которым их поделие сооружено.


                  1. Grox Автор
                    09.04.2018 22:23

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


                    1. slashd
                      09.04.2018 23:36

                      Вы похоже не понимаете того, что люди пишут бажный код не из-за собственной глупости или желания писать плохо?
                      Может быть код был слишком сырым для внедрения в готовый продукт, но программиста поторопили? Мб программист который его писал и должен был довести его до нормального состояния уволился? Может быть код начали писать ещё в начале нулевых, когда всё это не было на слуху? Тут куча «может быть». Винить людей в том, что они «не проверяют входящие значения» не обладая фактами… ну это как минимум недальновидно… Баги будут всегда, и не только «buffer overflow». Предоставьте свой достаточно сложный проект без багов или… Ну в общем «boot up or shut up» :)


                      1. Grox Автор
                        09.04.2018 23:38

                        Моя статья это напоминание. Никак не обвинение.


                      1. Grox Автор
                        09.04.2018 23:39

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


              1. interprise
                08.04.2018 17:44

                я не хочу вступать в эту тупую демагогию. Покажите мне хотябы 1 крупный проект на плюсах без уязвимость? О чем речь вообще? всегда можно сказать «не пытались».


                1. khim
                  08.04.2018 21:58

                  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. struvv
                09.04.2018 00:00
                +1

                Ad hominem.

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

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


                1. DmitriyDev
                  10.04.2018 09:15

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

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


        1. cyberzx23
          09.04.2018 00:29

          У NASA получилось. Думаю, есть ещё куча компаний, которые пишут софт повышенной надёжности, у которого нет уязвимостей. В том числе и на языке С.


        1. iCpu
          09.04.2018 07:48

          В розовом мире поней и вы правы. А в реальном мире везде есть нюансы.
          Взять, например, ваше строгое утверждение. Для того, чтобы его опровергнуть, достаточно привести 1 (одну) программу, написанную на c++ и не имеющую уязвимости, и 1 (одну) на rust, имеющую в себе уязвимость.
          Первое условие выполняется очень просто, достаточно написать
          int main() { return 0; }
          Второе сделать так же не сложно: открываем hg.mozilla.org и делаем фильтр по ".rs", получаем ненулевое число ошибок. Строгое утверждение опровергнуто. Там же можно посмотреть сводку файлов и обнаружить достаточно компонент на c++ без уязвимостей.


    1. a0fs
      08.04.2018 14:17
      +1

      Можно, но нужно всё контролировать, потому что этого не делает машина, а язык С и С++, теми частями которыми он С, даёт кодеру всего лишь машину, не влезая со своими тараканами между ними (за то и высоко ценится, отлично портируется, и нежно любим). А попыток решить проблемы кодеров языком была масса и Rust здесь не пионер и даже не крайний. И да, когда всё будет писаться на Rust, ещё нужно будет посмотреть, что легче, искать проблемы в более или менее читаемом C или в хитросплетениях архитектурных изысков Rust. Да на С можно писать «красиво», но тогда на Rust можно писать «божественно», ибо там макросами можно намутить такой дичи, в которой и с дебагером и днём с огнём логику искать можно долго и развлекательно. А пока контролировать размер объектов не научится машина, этот мир не спасёт ничто.


  1. potan
    07.04.2018 23:15

    Хорошая система типов не позволит использовать непроверенные данные. Но типами программисты леняться пользоваться.


  1. reversecode
    08.04.2018 11:21
    -1

    Дешевая раб сила с индии…


  1. KorDen32
    08.04.2018 12:27

    при копировании данных в буфер фиксированного размера их размер не проверяется

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


  1. Sly_tom_cat
    08.04.2018 13:37

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

    Проблема ведь в том, что принимающая сторона принимает эти данные от доверенной, и на той стороне уже вполне «естественно» доверять им… там принимающая процедура принимает данные и с FE (который старательно все валидирует и фильтрует) и от системы обмена данными с контрагентами.


    1. reversecode
      08.04.2018 14:37

      Разработчикам ничего не надо объяснять, вы видимо с кем другим общались


      1. Grox Автор
        08.04.2018 14:46

        Разработчики они разные, у кого какие в наличии.


      1. Sly_tom_cat
        08.04.2018 14:53
        +1

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


  1. Sabubu
    08.04.2018 14:18

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


    1. Grox Автор
      08.04.2018 14:20
      +1

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

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