25 самых опасных ошибок в программировании

Автор оригинала: Jeff Atwood
  • Перевод
Всем привет.
Под катом — перевод статьи Джеффа Атвуда, в которой он приводит список 25 наиболее опасных ошибок в программировании от Common Weakness Enumeration со своими комментариями.

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

Если вы занимаетесь разработкой в любом качестве, как минимум прочтите этот список по диагонали. Если вам что-то незнакомо или вызывает интерес, рекомендую пройти по ссылке для более детального описания (английский)
  1. Недостаточная проверка ввода
    Убедитесь, что ваши входные данные правильны. Если вы ожидаете число, там не должно быть букв. Равно как и цена нового автомобиля не может быть равна доллару. Неправильная проверка ввода может привести к уязвимости, когда злоумышленник может изменять вводимые данные неожиданным способом. Многих наиболее общих уязвимостей известных сегодня можно избежать или хотя бы сократить с помощью строгой проверки ввода.

  2. Недостаточное кодирование или экранирование вывода
    Недостаточное кодирование вывода — корень большинства атак, основанных на инъекциях. Атакующий может изменять команды, которые вы должны переслать другим компонентам, что может привести к полной компрометации вашего приложения — я уже не говорю о выполнении эксплойтов на других компонентах, которые злоумышленник не может запустить напрямую. Когда ваша программа генерирует вывод для других компонентов в виде структурированных сообщений, таких как запросы, убедитесь, что управляющая информация и метаданные отделены от непосредственно данных.

  3. Нарушение структуры SQL запроса (aka «SQL инъекция»)
    Если злоумышленники могут влиять на SQL, который вы отправляете базе данных, они могут изменить ваши запросы чтобы украсть, повредить или изменить данные в ней. Если вы используете SQL запросы для управления безопасностью, например, аутентификации, злоумышленники могут изменить логику этих запросов и обойти защиту.

  4. Нарушение структуры веб-страницы (aka «Межсайтовый скриптинг», «XSS»)
    Межсайтовый скриптинг (XSS) — результат объединения HTTP, который по своей природе не сохраняет состояние, смеси данных и скриптов в HTML, больших объемов данных, передаваемых между веб-сайтами, многообразных схем кодирования и многофункциональных веб-браузеров. Если вы недостаточно внимательны, злоумышленники могут внедрить Javascript или другой исполнимый в браузере код в страницу, которую генерирует ваше приложение. Затем вашу страницу посещают другие пользователи, чьи браузеры выполняют этот мошеннический скрипт так, будто он пришел от вас — потому что, в конце концов, он действительно пришел от вас! Нежданно-негаданно, ваш веб-сайт предоставляет код, который вы не писали. Злоумышленники могут использовать различные приемы, чтобы внедрить такой код на ваш сервер непосредственно или с использованием ничего не подозревающей жертвы как посредника.

  5. Нарушение структуры команд ОС (aka «Инъекция команд OS»)
    Ваша программа работает как мост между посторонним человеком в сети и внутренностями вашей операционной системы. Если вы запускаете другую программу в операционной системе, позволяя передать сомнительные параметры в командную строку, вы приглашаете злоумышленников в вашу операционную систему.

  6. Передача важной информации открытым текстом
    Информация, передаваемая по сети, проходит множество разных узлов по пути к конечной цели. Если ваша программа отсылает важную, личную информацию или данные аутентификации, берегитесь: злоумышленники могут перехватить ее по пути. Все, что им нужно — получить контроль над одним из узлов на пути к конечной цели, любым узлом в той же подсети транзитных узлов, или подключиться к доступному интерфейсу. Обфускация траффика с помощью Base64 или кодирования URL не дает никакой защиты.

  7. Подделка межсайтовых запросов (XSRF)
    Подделка межсайтовых запросов — это как принять посылку от кого попало — с той разницей, что злоумышленник вынуждает пользователя активировать HTTP запрос, который идет на ваш сайт. Пользователь может даже не догадываться, что запрос послан, однако когда тот попадает на сервер, он выглядит как будто пришел о пользователя, не злоумышленника. Злоумышленник маскируется под легитимного пользователя и получает все возможные права, которые есть у пользователя. Это особенно действенно, когда пользователь имеет привилегии администратора, полностью компрометируя функциональность вашего приложения.

  8. Состояние гонки
    Состояние гонки подразумевает множественные процессы, в которых злоумышленник имеет полный контроль над одним из них; злоумышленник использует процесс для создания хаоса, коллизий либо ошибок. Воздействие может быть локальным или глобальным, в зависимости от того, что затрагивает состояние гонки (например, состояние переменных или логику безопасности), а также возникает оно между несколькими потоками, процессами или системами.

  9. Утечка информации через сообщения об ошибках
    Чрезмерно «разговорчивые» сообщения об ошибках могут раскрыть секреты любому злоумышленнику, который неправильно использует вашу программу. Эти секреты могут покрывать широкий спектр значимых данных, включая персональную информацию, данные аутентификации и конфигурацию сервера. Эти данные могут выглядеть как невинные секреты, удобные пользователям и админам, например, полный путь установки вашей программы — но даже эти маленькие тайны могут упростить более спланированную атаку.

  10. Нарушения контроля за операциями у границ буфера памяти
    Бич приложений на С в течении десятилетий, переполнения буфера чрезвычайно устойчивы к истреблению. Способы атаки и обнаружения продолжают улучшаться, и сегодняшние методы переполнения буфера не очевидны на первый или даже на второй взгляд. Вы можете считать, что полностью защищены от переполнения буфера, потому что пишете свой код на более высокоуровневых языках, чем С. Но на чем написан интерпретатор вашего любимого «безопасного» языка? А что насчет native-кода, который вы вызываете? На каких языках написан API оперционной системы? Как насчет программ, обеспечивающих инфраструктуру Интернета?

  11. Внешний контроль критичных данных состояния
    Если вы сохраняете пользовательские данные состояния там, где злоумышленник может их изменить, это упрощает компрометацию. Данные могут быть сохранены в конфигурационных файлах,.профайлах, cookies, спрятанных полях форм, переменных окружения, ключах регистра, или других местах, где они могут быть изменены злоумышленником. В протоколах без сохранения состояния, таких как HTTP, некоторые формы пользовательской информации о состоянии могут быть перехвачены в каждом запросе, то есть они открыты злоумышленнику без необходимости. Если вы, основываясь на этих данных, производите любые критичные с точки зрения безопасности операции, можете поставить на то, что кто-то изменит эти данные так, чтобы обхитрить ваше приложение.

  12. Внешний контроль над именем файла или путем
    Когда вы используете введенные данные для построения имени файла, результирующий путь может указывать совсем не на предназначенную папку. Злоумышленник может скомбинировать несколько ".." или похожих последовательностей, чтобы выбраться из ограниченной директории. Другие атаки связанные с файлами упрощаются при внешнем контроле имени файла, например, переход по символьным ссылкам, что приводит к тому, что ваше приложение считывает или изменяет файлы, к которым злоумышленник не имеет прямого доступа. То же самое применимо, когда ваше приложение запущено с повышенными привилегиями и принимает имя файла в качестве входных данных. Похожие правила верны для URL адресов и разрешению постороннему указывать произвольные адреса.

  13. Ненадежный путь поиска
    Ваше приложение зависит от вас, или от своего окружения, в плане предоставления пути поиска (или рабочего пути) критичных ресурсов, таких как библиотеки кода или конфигурационные файлы. Если путь поиска находится под контролем злоумышленника, он может изменить его, чтобы тот указывал на ресурсы, выбранные злоумышленником.

  14. Неконтролируемая генерация кода (aka «Инъекция кода»)
    Несомненно, сложно отрицать сексуальность динамически генерированного кода, однако злоумышленники находят его не менее привлекательным. Серьезная уязвимость возникает, когда ваш код может быть напрямую вызван неавторизованными участниками, если внешние входные данные влияют на код, который будет выполняться или эти данные вставляются непосредственно в сам код.

  15. Скачивание кода без проверки целостности
    Если вы скачиваете код и выполняете его, вы верите, что источник этого кода не мошеннический. Но злоумышленники могут изменить этот код до того, как он достигнет вас. Они могут взломать сайт, с которого вы скачиваете, сымитировать его спуфингом DNS или «отравлением» кеша, убедить систему сделать перенаправление на другой сайт или даже изменить код по пути через сеть. Этот сценарий применим даже к случаям, когда ваш собственный продукт скачивает и устанавливает обновления.

  16. Неправильное закрытие или освобождение ресурсов
    Когда ваши системные ресурсы достигают «конца своей жизни», вы избавляетесь от них: память, файлы, cookies, структуры данных, сессии, каналы связи и так далее. Злоумышленники могут использовать неверное закрытие для удержания контроля над этими ресурсами, когда вы уже считаете, что избавились от них. Злоумышленники могут просеивать их в поисках важных данных. Они также теоретически могут использовать эти ресурс повторно.

  17. Неправильная инициализация
    Если вы не инициализируете ваши данные и переменные правильно, злоумышленник может иметь возможность инициализировать их за вас или получить важную информацию, которая осталась от прошлых сессий. Если эти переменные используются в критических с точки зрения безопасности операциях, таких как принятие решения об аутентификации, они могут быть изменены для обхода вашей защиты. Это — наиболее вероятная причина, почему ваш код вдруг проскакивает инициализацию при странных ошибках и условиях.

  18. Неправильные вычисления
    Когда злоумышленники контролируют входные данные для численных вычислений, математические ошибки могут иметь последствия для безопасности. Они могут заставить вас выделить значительно больше ресурсов, чем необходимо — или значительно меньше. Они могут нарушить бизнес-логику (вычисления, возвращающие отрицательную цену) или вызвать отказ в обслуживании (деление на ноль, приводящее к краху программы).

  19. Недостаточный контроль доступа (Авторизация)
    Если вы не проверяете, что пользователи приложения делают только то, что им позволено делать, злоумышленники попытаются использовать неверную авторизацию и поиграться с несанкционированной функциональностью.

  20. Использование взломанного или рискованного криптографического алгоритма
    Самопальная криптография — приглашение для злоумышленников. Криптография сложна. Если гениальные математики и компьютерные специалисты не могут дать ей ладу — а они периодически признают устаревшими свои собственные методы — и у вас не получится.

  21. Жестко закодированный пароль
    Прописывать в коде вашего приложения секретную учетную запись и пароль очень удобно — для искусных аналитиков. Если пароль один и тот же во всех ваших приложениях, каждый ваш клиент становится уязвимым, когда этот пароль неизбежно становится известным. А поскольку он жестко прописан в коде, исправить это — большая головная боль.

  22. Небезопасное назначение разрешений критичному ресурсу
    Берегитесь критичных программ, хранилищ данных и конфигурационных данных с читабельными разрешениями по умолчанию. Хотя эта проблема может и не рассматриваться во время реализации или разработки, она должна. Не требуйте от ваших клиентов делать ваше приложение безопасным за вас! Попробуйте обеспечить безопасность по умолчанию, из коробки.

  23. Использование недостаточно случайных значений
    Вы можете зависеть от случайности, даже когда не подозреваете об этом, например при генерации идентификаторов сессии или временных имен файлов. Генератор псевдослучайных чисел (ГПСЧ, PRNG) используются повсеместно, однако множество вещей может пойти неправильно. Как только злоумышленник может определить, какой алгоритм используется, он может угадывать следующее случайное число достаточно часто для проведения успешной атаки после относительно небольшого числа попыток.

  24. Выполнение с ненужными привилегиями
    Вашей программе могут потребоваться специальные привилегии для выполнения определенных операций; обладание этими привилегиями дольше, чем это необходимо, рискованно. При работе с экстра привилегиями ваше приложение имеет доступ к ресурсам, которые пользователи приложения не могут использовать напрямую. Каждый раз, когда вы запускаете отдельную программу с повышенными привилегиями, злоумышленники теоретически могут использовать эти привилегии.

  25. Обеспечение серверной безопасности на стороне клиента
    Не доверяйте клиенту производить проверку безопасности от имени сервера. Злоумышленники могут проанализировать ваше приложение и написать своих собственных клиентов. Последствия зависят от того, что защищают ваши проверки безопасности, но основные цели — это аутентификация, авторизация и проверка ввода.
Конечно, здесь нет ничего по-настоящему нового; я серьезно прошелся по такому же основному списку в книге «Sins of Software Security» почти два года назад. Разница лишь в относительных приоритетах, так как веб-приложения начинают преобладать в основном потоке.

Список ошибок безопасности приложений служит той же цели, что и классический список ошибок разработки МакКоннелла: повысить осведомленность. Удивительно большая часть успеха состоит в распознавании наиболее общих ошибок и состояний отказа. Так что вы можете — как минимум в теории — осознать, когда ваш проект двигается к одной из них. Неведение — самый страшный убийца программных проектов.

В переводе и оформлении текста мне помогали:


За что им огромное спасибо.
Поделиться публикацией

Комментарии 34

  • НЛО прилетело и опубликовало эту надпись здесь
      –6
      А я как раз занимаюсь «этим делом», не имея в этом особых навыков.
      А именно: как сделать, чтобы «отравленные» клиенты хотя бы не заглючивали сервер.
        +1
        Самое страшное это конечно 1, 10 и 24. Особенно если все вместе. Я бы еще добавил undefined behavior, он тоже может привести к дыре в безопасности.
          +1
          В 20 опечатка: СамопальнаЯ.
            +1
            Спасибо, подправил
            –1
            Статья — супер, перевод — уж простите…
              –1
              «сексуальность динамически генерированного кода» просто убило
                +2
                сори, в оригинале и правда так написано…
                +1
                Прощаю =)
                Но я старался.
                  0
                  Вы можете перечислить явные недочеты, которые бросаются в глаза?
                  Это поможет мне а) учесть на будущее б) улучшить английский.
                    +2
                    Перевод нормальный, GJ автор. Заметно немного, что вы переводили так, чтобы не пропустить ни слова из оригинала, я и сам так перевожу, поэтому стараюсь, после того, как перевел, написать пересказ на русском своего же перевода. Оно как-то оживляет, что ли, текст.
                      0
                      Спасибо, обязательно попробую
                      0
                      «Жестко закодированный пароль» — не звучит.
                      раз на то пошло — Присутствие паролей в исходном коде
                    0
                    спасибо за перевод отличной статьи :)
                      0
                      Двадцать пять причин использовать языки со строгой статической типизацией :)
                        +7
                        как то c++ это не спасало от buffer overflow+shell code execution и как бе инъекции/CSRF/XSS — лекго появляются и в строго типизированных языках :)
                          +1
                          В Си++ нестрогая типизация, а переполнение буфера возникает из-за прямого доступа к памяти (непроверяемая индексация массивов, etc.)
                            +1
                            пардон, мой фейл. но таки она статическая. :)
                          +1
                          Мне кажется, что статическая типизация языка в данном случае не слишком сильно влияет на возможность допустить ошибку, написав уязвимый код. Такого рода логические недочеты языком навряд ли смогут регулироваться без специальных средств. Так что нужно проверять себя, на каждом участке кода пытаясь узнать — возможно ли возникновение нештатной ситуации и каким образом её можно предотвратить.
                            0
                            > Так что нужно проверять себя, на каждом участке кода пытаясь узнать — возможно ли возникновение нештатной ситуации и каким образом её можно предотвратить.

                            Пишите чистые, полностью определенные функции и все будет замечательно.
                            0
                            двадцать пять причин не браться за работу, которую не можешь сделать хорошо(читать без ошибок).
                              +1
                              Я бы не был настолько критичен. Вы никогда не можете быть уверены, что можете сделать работу без ошибок. Так что если рассуждать подобным образом, ни за какую работу браться нельзя.

                              Я бы сказал, это 25 причин проверить свою работу на предмет ошибок лишний раз. Как говорится, кто предупрежден, тот вооружен.
                                0
                                Причем тут это?
                              0
                              Спасибо за информацию. Жаль только, что не описаны основные методы предотвращения таких ошибок. Интересующимся могу предложить пролистать книгу «Защищенный код» из боекомплекта разработчика microsoft. Недавно видел её в Pdf на русском языке, где-то на torrents.ru. Но в этой книге, по большей части, ориентация на Windows и платформу .NET.
                                –1
                                Без примеров не очень интересно, тем более, что куча пунктов дублируют друг-друга как, например, под пункт 2 попадают и пункты 3, 4, 5.
                                  0
                                  а Вы по ссылкам пройдите, там примеров хватает
                                  0
                                  Думаю, что примеры уже отдельная статья, а здесь просто список :).
                                  Спасибо, все эти правила, конечно, знать нужно и так, но неплохо было все перечитать заново. Спасибо.
                                    0
                                    А где остальные 75?!
                                      –2
                                      Почти ничего не понял.
                                      Такое чувство, что это промт-перевод.
                                        +1
                                        попробуйте перевести назад на английский этим же промтом, а потом самостоятельно перевести на русский :-)
                                          0
                                          Я это сказал не буквально, просто читать почему-то очень сложно.
                                        0
                                        никакого разнообразия. tot_ra.habrahabr.ru/blog/49163/ — было на главной тоже.
                                          +1
                                          Большинство указанных выше проблем можно свести к недостаточной проверке информации полученной от пользователя.
                                            0
                                            Теперь и анализтор PVS-Studio начинает смотреть в сторону CWE. PVS-Studio: поиск дефектов безопасности.

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое