уязвимости в программном коде и борьба с ними
Контроль уязвимостей в программных приложениях
Дефекты программного кода
Задача высококлассного менеджера состоит в умении не только подбирать команду, но и укладываться в бюджеты. Зачастую они не позволяют нанимать специалистов с безупречной квалификацией. В этой ситуации необходимо создавать такие условия работы и процессы ее выполнения, которые даже при среднем уровне компетенций исполнителей позволяли бы получать результаты, превышающие аналогичные показатели по рынку. Тем самым достигаются конкурентные преимущества.
Какие дефекты присутствуют в ПО и все ли они одинаковы? На этот вопрос можно отвечать по-разному, строя различные теории их классификации. Здесь мы приведем разделение дефектов программного обеспечения на классы с точки зрения различий в управлении ими в процессе повышения качества ПО в соответствии с требованиями информационной безопасности.
Самый распространенный дефект – это ошибки программистов при разработке кода. Зачастую причиной их появления является дефицит времени или потеря внимания во время работы. Например, программист разрабатывает код, который в определенных условиях должен выполнять одни действия, а во всех остальных случаях – другие. Программист уделяет большое внимание разработке кода, который будет выполняться в 90% случаях исполнения ПО. Когда же дело доходит до обработки альтернативы, он устает, его внимание рассеивается, и какие-то важные аспекты, такие как оператор, определяющий выполнение данного фрагмента кода, только если условие выполнения основного фрагмента не выполнилось, теряются.
Другая характерная причина появления ошибок в программном коде – внесение в него изменений. Разработчик меняет один кусок кода, который может влиять на функциональность другого фрагмента программы. Тогда та функциональность, трансформация которой не предполагалась, становится измененной.
Обычно такие ошибки обнаруживаются на этапе тестирования либо самими разработчиками, либо специальной группой тестировщиков. Для обнаружения таких ошибок существуют различные теории и успешные практики разработки наборов тестов по техническому заданию, регрессионные тесты и другие методы, позволяющие написать качественный набор исходных данных, чтобы проверить больший процент возможных сценариев выполнения программы.
Другие дефекты, которые в большей степени интересуют специалистов по информационной безопасности, нежели разработчиков, – это уязвимости. Уязвимость – ошибка разработчика, которая потенциально может эксплуатироваться злоумышленниками с целью получения несанкционированного доступа к управлению программным приложением. Уязвимость – это код, который выполняет правильные действия с точки зрения требуемого функционала, но его исполнение имеет побочный эффект, о наличии которого программист зачастую может не знать. Наличие таких фрагментов кода не является следствием усталости, невнимательности или отсутствия достаточного времени на тестирование у разработчика, как в случае ошибки. Нередко причиной появления уязвимостей является незнание программистов о наличии побочных возможностей тех языковых конструкций, которые они используют для реализации задуманного функционала.
Уязвимости выявляют эксперты в области анализа кода, знающие о наличии побочных эффектов у тех или иных языковых конструкций. Также многие уязвимости можно обнаруживать в результате тестирования ПО по требованиям информационной безопасности специальными тестами на проникновение. Однако более эффективный метод их обнаружения – это полуавтоматический статический анализ кода, который выполняется экспертами с применением специальных инструментальных средств.
Самые неприятные с точки зрения возможности обнаружения дефекты – недекларированные возможности ПО (НДВ). Недекларированные возможности – это правильный код с точки зрения и функциональности, и информационной безопасности, поэтому его трудно обнаружить автоматическими методами. Однако этот код реализует функциональность, которая не была задумана заказчиком – ее для своих целей привнес разработчик. Обычно НДВ разделяют на закладки и секретный вход (back door).
Закладка – это функциональность, которая выполняется при наступлении определенных условий и выполняет действия, задуманные разработчиком. Часто закладки используются для того чтобы неявно манипулировать программным обеспечением. Один из наиболее известных случаев наличия закладки – история разработчика City Bank. Программист не знал, что делать с разницей, возникающей при округлении результатов арифметических операций при начислении процентов на вклады клиентов, и не придумал ничего лучше, чем накапливать ее на своем персональном счете.
Секретный вход – это код, позволяющий программисту получать контроль над ПО в обход правил, указанных в техническом задании. Наиболее часто секретными входами наполняют программное обеспечение, которое разрабатывается на заказ, для того, чтобы можно было выполнять удаленную диагностику ошибок при эксплуатации программного приложения заказчиком.
Обнаружить недекларированные возможности полностью в автоматическом режиме нельзя, так как такой код является правильным. Подобные дефекты эксперты в области информационной безопасности находят посредством ручного анализа кода или с помощью программных инструментов, позволяющих обнаруживать в исходном коде шаблоны языковых конструкций, характерных для построения НДВ.
Откуда берутся дефекты в программном коде?
Ошибки и уязвимости в программном коде обычно появляются не только вследствие того, что технологии меняются, а разработчики не успевают к ним адаптироваться, но также по причине неправильного построения процесса разработки ПО.
Зачастую требования к программному обеспечению меняются быстрее, чем ИТ-команда успевает их реализовывать. Дается одно техническое задание, оно прорабатывается архитектором, конструкторами и передается в работу. Но в процессе заказчик разработки понимает: новые условия рынка требуют, чтобы разрабатываемое ПО выполняло другой функционал. Несмотря на возражения ИТ-команды, вносятся изменения в проектную документацию, а зачастую и непосредственно в код, ломая при этом проработанную архитектуру.
Другой причиной появления ошибок и уязвимостей является сложность технологий, использующихся в современной ИТ-индустрии.
Разработчики вынуждены использовать технологии, которые сами по себе могут содержать ошибки и уязвимости, а также способствовать появлению новых в результате их неправильного внедрения в разрабатываемое ПО. Современные программные продукты многоязычные, кроссплатформенные, связи между компонентами, из которых они состоят, настолько обширны, что программист просто не в состоянии удерживать все особенности в поле своего внимания. Помимо этого, поскольку программные системы разрабатываются командой специалистов, ошибки и уязвимости часто прячутся на стыке компонент, за которые отвечают разные люди.
Появление в коде недекларированных возможностей носит исключительно личностный характер и с трудом контролируется посредством внедрения современных технологий разработки ПО. Хотя практика перекрестного контроля разработки (прежде чем код попадает в основную ветку разработки, его обязательно проверяет другой программист) и другие организационные меры имеют определенный успех. Обнаружить недекларированные возможности в коде, который разрабатывался на заказ и куда НДВ были внедрены специально, можно только посредством его анализа.
Можно ли контролировать наличие дефектов в программном коде?
На сегодняшний день на рынке представлено несколько инструментальных систем анализа кода, как статического (по исходному коду методом «белого ящика»), так и динамического (без исходного кода методом «черного ящика»). Помимо этого, ведущие инструментальные системы анализа кода от таких производителей, как HP и IBM, предлагают комбинированный статический и динамический анализ, который позволяет отображать результаты динамического анализа на исходный код. Можно сказать, что в настоящее время наиболее эффективным инструментальным средством анализа кода, которое предлагает статический, динамический, а также гибридный анализ в сочетании с удобным интерфейсом и хорошей библиотекой правил поиска уязвимостей, является инструментальное средство HP Fortify.
Если программное обеспечение разрабатывается на заказ, то при приемке оно обязательно должно подвергаться проверке на наличие дефектов. Это может сделать внутренняя команда по контролю качества программных продуктов в части функциональности и требований информационной безопасности. Проверка также может быть сторонней, что подразумевает привлечение независимых экспертов.
Контролировать уязвимости в программном обеспечении, которое поставляется на заказ, сложно, так как информация о наличии дефектов проходит долгий путь проверок, а затем следует не менее длительный процесс их устранения. Однако это не значит, что такое ПО не нужно проверять и стоит эксплуатировать как «кота в мешке». Рекомендуется выполнять контроль уязвимостей посредством правильной настройки защиты периметра эксплуатации.
Можно ли справиться с уязвимостями в программном обеспечении?
Вот еще один риторический вопрос кибербезопасности. Можно ли победить то, что существует столько же, сколько и само программное обеспечение? В компьютерной безопасности в целом «уязвимостью» называется слабое место, которое позволяет
Вот еще один риторический вопрос кибербезопасности. Можно ли победить то, что существует столько же, сколько и само программное обеспечение?
В компьютерной безопасности в целом «уязвимостью» называется слабое место, которое позволяет злоумышленнику снизить уровень достоверности информации системы. Сочетаются три элемента: восприимчивость или недостаток системы, доступ злоумышленника к бреши и возможность злоумышленника ей воспользоваться. Что касается программного обеспечения, то «ошибка» в нем есть неисправность, заставляющая его выдавать неверный или неожиданный результат либо провоцирующая на непреднамеренное поведение (для своих разработчиков и пользователей). Другими словами, уязвимое программное обеспечение обычно работает исправно, но когда к нему подступают «иным образом» (т.е. со злым умыслом и соответствующими инструментами), может случиться всякое. И случается.
Если бы не ошибки, то распространение вирусов, троянов, несанкционированных бэкдоров и рост ботнетов осложнились бы существенно. Так что уместно говорить, что ошибки являются основой проблем информационной безопасности. Или, по крайней мере, одной из них. Потому что, кроме уязвимостей в программном обеспечении, всегда есть «человеческий фактор» и возможность использовать социальную инженерию, для того чтобы проникнуть даже в самую защищенную систему.
В «идеальном мире» от неуязвимого программного обеспечения индустрия информационной безопасности выглядела бы совсем по-другому, и, скорее всего, была бы гораздо меньшей, чем сегодня. На самом деле это классическая дилемма: если бы не было войны, не было бы потребности в армии; если бы не было преступлений, не нужна была бы полиция. Не будь заболеваний, и доктора ни к чему. Однако есть и войны, и преступления, и болезни, поэтому есть военные, полицейские и врачи. Все они тоже ошибаются, а порой и совершают преступления.
Можно ли победить программные #vulnerabilities? #security #notgonnahappen
Уязвимости в программном обеспечении наиболее сопоставимы с заболеваниями, или если точнее, с предрасположенностью к болезням (так что эксперты по безопасности подобны врачам). В живом организме в одних случаях предрасположенность определяется генетически, в других является следствием родовой травмы и/или загрязненной окружающей среды.
А что порождает недостатки в программном обеспечении? Как правило, уязвимости — результаты ошибок разработчиков, недостаточного контроля качества и/или прямо неверного подхода к написанию кода, когда программа пишется с первого же дня без оглядки на безопасность. Позднее могут выходить ворохи патчей, от которых размер оригинального пакета вырастает раза в два, а баги все продолжают и продолжают находить. Просто потому, что программное обеспечение «генетически» уязвимо.
В некоторых религиозных сектах отвергают помощь медицины, провозглашая болезни наказанием свыше. Интересно было бы взглянуть на их «коллег» в киберпространстве, однако вряд ли их существование возможно, хоть это был бы и крутой поворот сюжета в киберпанке.
Так можно ли полностью изжить баги?
Да, конечно, как только древняя максима errare humanum est изживет себя и перестанет быть применима в отношении человечества. Как скоро это произойдет?
На самом деле, всегда есть соблазн возложить вину на разработчиков, то есть тех, кто ошибается в написании кода. Время от времени раздаются «требования» привлечь разработчиков к ответственности за ошибки, которые они не смогли исправить до того, как программное обеспечение поступило в продажу. Но программные уязвимости – это, скорее, организационная проблема, которая имеет мало общего с квалификацией программистов. Кроме того, некоторые ошибки могут оставаться «вне поля зрения» несколько лет, как показали случаи с #heartbleed, багом Stuxnet и, вот буквально только что — с брешью Bash Bug/Shellshock, которая «кошмарит» специалистов ничуть не меньше, а то и больше, чем обнаруженная в апреле многолетняя дыра в OpenSSL. Ни разработчики, ни конечные пользователи не знали о них ничего, пока эти уязвимости не обнаружили эксперты по безопасности или преступники. Так что вопрос о том, кто виноват, интересен, но, в конечном счете, не уместен. Скажем, мало, что можно сделать, чтобы полностью извести ошибки в программном обеспечении, это, очевидно, просто невозможно.
Некоторые #bugs могут оставаться незамеченным годами. #security
Тем не менее, «оглядка на безопасность», хороший контроль качества и ответственное обращение с новооткрытыми изъянами могут резко уменьшить проблемы, снижая восприимчивость систем к вредоносным программам и прочим попыткам использовать их злонамеренно. Под «ответственным обращением» мы понимаем просто адекватную реакцию на сообщения об ошибках и быстрый выпуск патчей. Сегодня у большинства разработчиков программного обеспечения присутствуют багтрекинг и инструменты сообщения о найденных ошибках. Без них все было бы гораздо хуже. Это нечто вроде профилактики простуды, гриппа и других заболеваний, которая помогает нам сохранить здоровье даже в плохую погоду и в переполненном общественном транспорте, где особенно легко простудиться или подхватить некоторые другие заболевания, распространяющиеся воздушно-капельным путем.
А предприятия и конечные пользователи должны использовать защитные решения, потому что, да, в программном обеспечении бывают уязвимости, которыми пользуются злоумышленники и вредоносные программы, и, к сожалению, они никуда скоро не исчезнут.
Каковы требования предъявляются к эффективному корпоративному решению безопасности, чтобы оно справлялось с уязвимостями? Прежде всего, решение должно уметь выявлять уязвимые программы, предлагать для них обновления или даже обновлять их автоматически. Конечно, это должно происходить автоматически у всех конечных пользователей. Это особенно важно на уровне предприятий, когда ИТ-отделы вынуждены иметь дело с сотнями (если не тысячами) конечных точек с широким спектром установленного на них программного обеспечения.
Во-вторых, защитное решение имеет должно выявлять и блокировать вредоносные атаки, использующие уязвимости, в том числе «нулевого дня» — дыры в безопасности, которые еще не исправлены. В «Лаборатории Касперского» это достигается с помощью ряда технологий, включая интеллектуальную систему Automatic Exploit Prevention, занятую поиском и блокированием необычной и потенциально вредной активности обычных приложений.
Так же в рубрике «Можно ли победить»:
Уязвимости программ
Уязвимости программ — ошибки, допущенные программистами на этапе разработки программного обеспечения. Они позволяют злоумышленникам получить незаконный доступ к функциям программы или хранящимся в ней данным. Изъяны могут появиться на любом этапе жизненного цикла, от проектирования до выпуска готового продукта. В ряде случаев программисты нарочно оставляют лазейки для проведения отладки и настройки, которые также могут рассматриваться в качестве бекдоров или недекларированных возможностей.
В некоторых случаях возникновение уязвимостей обусловлено применением средств разработки различного происхождения, которые увеличивают риск появления в программном коде дефектов диверсионного типа.
Уязвимости появляются вследствие добавления в состав ПО сторонних компонентов или свободно распространяемого кода (open source). Чужой код часто используется «как есть» без тщательного анализа и тестирования на безопасность.
Не стоит исключать и наличие в команде программистов-инсайдеров, которые преднамеренно вносят в создаваемый продукт дополнительные недокументированные функции или элементы.
Классификация уязвимостей программ
Уязвимости возникают в результате ошибок, возникших на этапе проектирования или написания программного кода.
В зависимости от стадии появления этот вид угроз делится на уязвимости проектирования, реализации и конфигурации.
Согласно статистике, особенно часто уязвимости обнаруживают в популярных и распространенных продуктах — настольных и мобильных операционных системах, браузерах.
Риски использования уязвимых программ
Программы, в которых находят наибольшее число уязвимостей, установлены практически на всех компьютерах. Со стороны киберпреступников имеется прямая заинтересованность в поиске подобных изъянов и написании эксплойтов для них.
Поскольку с момента обнаружения уязвимости до публикации исправления (патча) проходит довольно много времени, существует изрядное количество возможностей заразить компьютерные системы через бреши в безопасности программного кода. При этом пользователю достаточно только один раз открыть, например, вредоносный PDF-файл с эксплойтом, после чего злоумышленники получат доступ к данным.
Заражение в последнем случае происходит по следующему алгоритму:
Исследования, проводимые различными компаниями («Лаборатория Касперского», Positive Technologies), показывают, что уязвимости есть практически в любом приложении, включая антивирусы. Поэтому вероятность установить программный продукт, содержащий изъяны разной степени критичности, весьма высока.
Чтобы минимизировать количество брешей в ПО, необходимо использовать SDL (Security Development Lifecycle, безопасный жизненный цикл разработки). Технология SDL используется для снижения числа багов в приложениях на всех этапах их создания и поддержки. Так, при проектировании программного обеспечения специалисты по ИБ и программисты моделируют киберугрозы с целью поиска уязвимых мест. В ходе программирования в процесс включаются автоматические средства, сразу же сообщающие о потенциальных изъянах. Разработчики стремятся значительно ограничить функции, доступные непроверенным пользователям, что способствует уменьшению поверхности атаки.
Чтобы минимизировать влияние уязвимостей и ущерб от них, необходимо выполнять некоторые правила:
Уязвимости в коде. Как отличить опасную брешь от незначительной ошибки?
Как обычно выглядит проверка кода приложений на уязвимости? Специалист по безопасности инициирует процедуру, код сканируется, в приложении обнаруживаются тысячи уязвимостей. Все — и безопасник, и разработчики — в шоке. Естественная реакция разработчика: «Да наверняка половина — это ложные срабатывания, а другая — некритичные уязвимости!»
Что касается ложных срабатываний, здесь все просто: можно взять и посмотреть непосредственно те места кода, где обнаружены уязвимости с подозрением на false positive. Действительно, какая-то их часть может оказаться ложными срабатываниями, (хотя явно не половина от общего числа).
А вот о том, что критично, а что нет, хотелось бы поговорить более предметно. Если вы понимаете, почему сейчас уже нельзя использовать SHA-1 и зачем экранировать «;», возможно, эта статья не откроет вам чего-то нового. Но если по итогам сканирования от найденных уязвимостей рябит в глазах, добро пожаловать под кат – расскажем, какие «дыры» чаще всего встречаются в мобильных и веб-приложениях, как они работают, как их исправить, а главное — как понять, что перед вами — опасная брешь или незначительная ошибка в коде.
Внедрение
Ну ооочень распространенный тип уязвимости. Куда только не внедряются: в запросы SQL, LDAP, XML, XPath, XSLT, Xquery… Все эти внедрения отличает использование недоверенных данных, благодаря которому злоумышленник получает доступ к информации или изменяет поведение приложения. Например, с помощью пользовательского ввода, который недостаточно валидируется.
Согласно международной классификации уязвимостей OWASP, атаки с использованием метода «Внедрение» занимают первое место по уровню критичности угроз безопасности веб-приложений. Рассмотрим наиболее типичные виды внедрений.
Внедрение в SQL-запрос. Недоверенные данные попадают в SQL-запрос к базе данных.
Если в запросе к базе данных не реализована корректная проверка подлинности вводимых данных, злоумышленник может испортить SQL-запрос:
Если злоумышленник может записывать данные в XML-документ, то он может изменять и его семантику. В таком случае самый безобидный сценарий позволит внедрить в документ лишние теги, в результате чего XML-парсер завершит работу с ошибкой. Но можно столкнуться и с инцидентом посерьезнее: например, с подменой аутентификационных данных в базе клиентов или ценой в базе товаров магазина. Внедрение в XML также может привести и к межсайтовому скриптингу (XSS) — внедрению вредоносного кода, который выполнится в браузере пользователя при открытии страницы.
Что можем посоветовать?
В примере ниже приложение создаёт и выполняет XQuery-выражение на основе параметров username и password из HTTP-запроса (недоверенный источник):
В случае корректных данных запрос вернёт информацию о пользователе с соответствующими именем и паролем:
Если злоумышленник задаст в качестве параметра строку, содержащую специальные символы (например, admin’ or 1=1 or »=’ ), семантика запроса изменится:
Полученный запрос вернёт данные обо всех пользователях.
Безопасный вариант (использует prepared statements ):
Внедрение в XSLT (язык преобразования XML-документов) возможно, если приложение использует данные из недоверенного источника при работе с XSL.
Приложения используют XSL для преобразования XML-документов. Стилевые XSL-файлы содержат функции, которые описывают трансформацию, и при неправильной реализации могут включать в себя уязвимости. В таком случае возрастает риск осуществления сценариев атак, при которых злоумышленник меняет структуру и содержимое стилевого XSL-файла, а значит, и соответствующего XML-файла. Что можем получить на выходе?
Во-первых, XSS-атаку: внедрение в страницу, которую выдает веб-система, вредоносного кода и взаимодействие этого кода с сервером злоумышленника. Во-вторых, получение хакером доступа к системным ресурсам. В-третьих, выполнение произвольного кода. И на десерт – XXE-атаку (XML eXternal Entity — внедрение внешней сущности в XML).
Внедрение в команды LDAP (Lightweight Directory Access Protocol — «легкорасширяемый протокол доступа к каталогам») может привести к утрате конфиденциальности данных или их модификации. В данном случае недоверенные данные попадают в LDAP-запрос.
Внедрение вредоносной команды интерпретатора. Недоверенные данные попадают в команду интерпретатора. Злоумышленник может подобрать такой ввод, чтобы команда выполнилась успешно и ему стали доступны дополнительные полномочия в приложении.
В примере ниже приложение выполняет скрипт, предназначенный для создания резервной копии базы данных. Приложение принимает тип резервной копии в качестве параметра и запускает скрипт с повышенными привилегиями:
Небезопасное включение внешнего файла в HTML. Уязвимости типа «file inclusion» возникают, когда пользователь вводит путь к подключаемому файлу. Дело в том, что современные скриптовые языки позволяют динамически подключать код из сторонних файлов, чтобы использовать его повторно. Этот механизм применяют для единого внешнего вида страниц или для разделения кода на небольшие модули. Однако таким включением может воспользоваться злоумышленник, подменив путь и подключив свой файл.
Рекомендуем специалистам в области корпоративной информационной безопасности составить «белый список» допустимых путей подключения файлов, чтобы сотрудники могли добавлять файлы только по сценариям из этого списка.
Закладки
Закладками именуют преднамеренно внесённые в код приложения части, с помощью которых при определённых условиях можно выполнить не заложенные в приложении действия. Рассмотрим самые распространенные виды закладок.
Специальные учётные записи. Если приложение сравнивает значение переменной пароля или логина с неизменным значением, стоит насторожиться: эта учётная запись может быть частью закладки. Посмотрим, как это происходит.
Разработчик приложения использует специальную учётную запись (возможно, с повышенными привилегиями) при отладке и оставляет соответствующие участки кода в финальной версии, сохранив за собой доступ к приложению. Злоумышленник может восстановить исходный код приложения, извлечь константные значения специальной учётной записи и получить доступ к приложению.
Хранить логины, пароли, ключи в исходном коде приложения категорически нельзя.
Скрытая функциональность (НДВ). Код скрытой функциональности запускается, когда срабатывает определенный триггер. В веб-приложениях триггером часто служит «невидимый» параметр запроса. Иногда дополнительно осуществляется проверка, с какого IP пришел запрос с триггером, чтобы активировать закладку мог только её автор. Такие проверки служат сигналом к возможным закладкам.
Недокументированная сетевая активность. К такому виду активности относятся: соединение со сторонними ресурсами в фоновом режиме, прослушивание недокументированных портов, передача информации по протоколами SMTP, HTTP, UDP, ICMP.
Если вы обнаружили в коде подозрительное соединение с адресом, который не входит в список заведомо безопасных, настоятельно рекомендуем вам его удалить.
Изменение параметров безопасности. Приложение содержит код, который изменяет значение переменной, хранящей успешность аутентификации. Распространённая ошибка — использование присваивания (=) вместо сравнения (==). В методах, связанных с аутентификацией, она особенно опасна, поскольку может быть частью бэкдора:
Временной триггер (timebomb). Закладка, которая срабатывает в определенный момент времени. Приложение сравнивает текущую дату с конкретными годом, месяцем и днём: 1 января 2021 года всех ждёт сюрприз:
А может быть и нет… На практике при поиске временных триггеров часто происходят ложные срабатывания. Например, если API времени используют и по назначению: запись в лог, вычисление времени выполнения, временные метки для ответов сервера на HTTP-запросы.
Но! Мы все же рекомендуем не закрывать глаза на все подобные срабатывания, так как знаем реальные примеры реализации таких уязвимостей.
Мёртвый код. Куски внедренного кода, которые ничего полезного не делают. Сам по себе мёртвый код не опасен, однако он может быть частью закладки, которую распределили по нескольким файлам. Или же триггер срабатывания закладки планируется внедрить позже. В любом случае, мёртвый код должен вызывать подозрения.
Отсутствие шифрования и использование слабых алгоритмов шифрования
Основные проблемы с шифрованием заключаются в том, что его либо не используют вовсе, либо применяют слабые алгоритмы, а ключи и соль слишком просты или хранятся небезопасно. Последствие у всех этих уязвимостей одно — конфиденциальные данные проще украсть.
В примере показана инициализация шифрования по устаревшему алгоритму DES:
Примеры уязвимых алгоритмов шифрования: RC2, RC4, DES. Безопасный вариант:
Согласно международной классификации OWASP, уязвимости типа «утечка конфиденциальных данных» занимают третье место по уровню критичности угроз безопасности веб-приложений.
Наши рекомендации разработчикам: обязательно используйте шифрование с учётом требований безопасности.
Применение незащищённого протокола HTTP вместо HTTPS чревато атакой типа Man in the middle.
Безопасный протокол HTTPS основан на HTTP, но также поддерживает шифрование через криптографические протоколы SSL/TLS. HTTPS шифрует все передаваемые по нему данные, в частности, страницы ввода логина и пароля или данные банковских карт пользователя, защищая их от несанкционированного доступа и изменения. В отличие от HTTP, который не защищает передаваемые данные. В результате злоумышленник может подменить информационный сайт по HTTP и заставить пользователя ввести данные на поддельной странице (фишинговая атака).
Ключ шифрования задан в исходном коде. В результате такие ключи доступны каждому разработчику приложения. Кроме того, после установки приложения удалить ключ из кода можно только с помощью обновления.
В целом, константные строки легко извлекаются из исполняемого файла с помощью программы для восстановления исходного кода (декомпилятора). Поэтому злоумышленнику необязательно иметь доступ к исходному коду, чтобы узнать значение используемого ключа. В нашей практике мы нередко сталкиваемся со случаями, когда в качестве значения ключа разработчики задают null или пустую строку, что просто недопустимо.
Наш совет: генерируйте ключи криптостойкими генераторами псевдослучайных чисел (ГПСЧ) и храните их с помощью специальных модулей.
Небезопасный алгоритм дополнения при шифровании. Если алгоритм шифрования RSA используется без OAEP-дополнения, зашифрованные данные становятся уязвимыми.
Алгоритм OAEP нужен, чтобы обработать сообщения перед использованием RSA. Сначала сообщение дополняется до фиксированной длины с помощью OAEP, затем шифруется с помощью RSA. Такая схема шифрования называется RSA-OAEP и является частью действующего стандарта.
Это пример инициализации RSA-шифрования без дополнения:
Недостаточный размер ключа шифрования. Если вы используете ключ малой длины, такое шифрование уязвимо для атаки методом перебора.
Криптоанализ не стоит на месте, постоянно возникают новые алгоритмы атак, компьютеры обретают бОльшие мощности. Параметры шифрования, которые раньше считались безопасными, устаревают и уже не рекомендуются к использованию. Так, RSA с длиной ключа 1024 бит перестал считаться безопасным в 2010–2015 годах.
Слабый алгоритм хеширования. По описанным в предыдущем пункте причинам хеш-функции MD2, MD5, SHA1 являются небезопасными. Чтобы найти коллизии для функций MD2 и MD5, существенных ресурсов не требуется.
Для SHA1 есть примеры двух разных файлов с одинаковыми хешами. Алгоритм взлома предложили сотрудники Google и Центра математики и информатики в Амстердаме.
Если пароли пользователей хранятся в виде хешей, но с использованием небезопасной хеш-функции, злоумышленник вполне может получить к ним доступ, реализовав следующий сценарий. Зная хеш пароля и используя уязвимость алгоритма хеширования, можно вычислить строку, для которой хеш такой же, как и для пароля. С помощью вычисленной строки злоумышленник проходит аутентификацию.
Хеш-функция для хранения паролей должна быть устойчивой к коллизиям и не слишком быстрой, чтобы нельзя было реализовать атаку методом перебора. Следует использовать безопасные алгоритмы PBKDF2, bcrypt, scrypt.
Несколько интересных цифр: с помощью PBKDF2 скорость перебора ключей сократили до 70 штук в секунду для Intel Core2 и около 1 тысячи на ПЛИС Virtex-4 FX60. Для сравнения, классические функции хеширования пароля LANMAN имеют скорость перебора около сотен миллионов вариантов в секунду.
Слабый алгоритм шифрования. Как и в случае алгоритмов хеширования, безопасность алгоритма шифрования определяется временем и ресурсами, которые придется потратить на его дешифровку. Уязвимыми алгоритмами считаются RC2, RC4, DES. Последний из-за небольшой длины ключа (56 бит) можно взломать методом полного перебора.
Слабый генератор псевдослучайных чисел (ГПСЧ) порождает предсказуемые последовательности. Хакер может обойти аутентификацию и захватить сессию пользователя.
Статистические ГПСЧ порождают предсказуемые последовательности, которые по статистическим характеристикам похожи на случайные. Их нельзя использовать для обеспечения безопасности.
Слабое зерно генератора псевдослучайных чисел. Использовать в качестве seed значение из недоверенного источника небезопасно, так как это порождает предсказуемую последовательность.
Работа многих криптографических алгоритмов основана на использовании устойчивого к криптоанализу ГПСЧ. Некоторые алгоритмы могут принимать в качестве дополнительного аргумента значение seed и для каждого значения этого параметра порождать предсказуемую последовательность. В таком случае безопасность системы основана на предположении о том, что значения seed будут непредсказуемы.
Соль задана в исходном коде. Вспомним, для чего нужна соль. Чтобы взломать пароль методом перебора, используют заранее составленные таблицы со значениями хеш-функций от популярных паролей. Соль — произвольная строка, которая подаётся на вход хеш-функции вместе с паролем, чтобы затруднить такую атаку.
Если соль хранится в исходном коде, возникают ровно те же самые проблемы, что и с паролями и ключами. Значение соли доступно разработчикам и легко могут получить злоумышленники, а убрать соль из финальной версии приложения можно только вместе с очередным обновлением приложения.
Манипуляции с логами
Различные ошибки в логах чреваты внедрением в приложения вредоносного кода. Чаще всего встречаются такие связанные с логированием уязвимости, как подделка файла лога и неструктурированное логирование.
Подделка файла лога происходит, когда приложение записывает недоверенные данные в журнал событий (лог). Хакер может подделать записи лога или внедрить в них вредоносный код.
Как правило, приложения записывают в лог историю транзакций для дальнейшей обработки, отладки или сбора статистики. Логи можно разбирать вручную или автоматически.
Если записывать в лог данные «как есть», злоумышленник может внедрить в лог фальшивые записи, нарушить структуру файла, вызвав сбои обработчика логов, или же внедрить вредоносный код, эксплуатирующий известные уязвимости в обработчике.
В этом примере web-приложение пытается считать целочисленное значение из параметра запроса. Если введённое значение не удалось конвертировать в целое число, приложение записывает в лог это значение вместе с сообщением об ошибке:
Злоумышленник может добавить в лог произвольную запись, например, строка twenty-one%0a%0aINFO:+User+logged+out%3dbadguy отразится в логе так:
Аналогичным образом в лог можно внедрить произвольные записи.
Безопасный вариант (использует NumberFormatException ):
Неструктурированное логирование, то есть вывод сообщений об ошибках в стандартные потоки out или err является небезопасным методом. Рекомендуется вместо него использовать структурированное логирование. Последнее позволяет генерировать лог с уровнями, метками времени, стандартным форматированием. Если в программе реализован механизм структурированного логирования, но при этом сообщения об ошибках выводятся в стандартные потоки, то в логе может не оказаться критически важной информации.
Выводить сообщения об ошибках в стандартные потоки допустимо только на ранних стадиях разработки.
Небезопасная работа с куки
Уязвимости, связанные со сбором пользовательских куки, весьма разнообразны.
Небезопасная работа с куки. Приложение включает в куки данные из недоверенного источника, что может привести к атакам типа «отравление кэша», XSS (межсайтовый скриптинг) и «расщепление ответа».
Если в приложение внедряется вредоносный код (межсайтовый скриптинг), то злоумышленник сможет изменять куки пользователя.
Содержимое второго ответа полностью контролируется злоумышленником, что приводит к отравлению кэша, XSS, вредоносным перенаправлениям и другим атакам.
Пример создания куки без флага httpOnly :
N.B. Согласно международной классификации OWASP, уязвимости типа «утечка конфиденциальных данных» занимают третье место по уровню критичности угроз безопасности веб-приложений.
В следующем примере приложение создаёт куки без флага secure :
Если приложение использует как HTTPS, так и HTTP, то при отсутствии флага secure куки, созданные в рамках HTTPS-запроса, будут передаваться в незашифрованном виде при последующих HTTP-запросах, что может привести к компрометации приложения. Это особенно опасно, если куки содержит ценные данные, в частности, идентификатор сессии.
Куки с неограниченным сроком действия. Если хранить ценные куки слишком долго, злоумышленник может успеть получить к ним доступ.
По умолчанию используются непостоянные (сессионные) куки, которые не сохраняются на диск и удаляются после закрытия браузера. Однако разработчик веб-приложения может указать срок хранения куки – в этом случае они будут записаны на диск и сохранены между перезапусками браузера и перезагрузками компьютера. Так мы даем злоумышленнику продолжительное время для разработки плана атаки.
Рекомендации разработчикам: убедитесь, что приложение не создаёт куки с длительным сроком хранения:
Указывайте разумный максимальный срок, следуя рекомендациям OWASP.
Утечка информации
Пожалуй, наиболее чувствительный для пользователей приложения вид уязвимостей.
Внешняя утечка информации через страницы ошибок. Приложение использует стандартные страницы ошибок, в которые может попасть информация о конфигурации системы.
Сообщения об ошибках и отладочная информация записываются в лог, выводятся в консоль или передаются пользователю. Из сообщений об ошибках злоумышленник может узнать об уязвимостях системы, что облегчит ему жизнь. Например, ошибка базы данных может говорить о незащищённости от SQL-инъекции. Информация о версии операционной системы, сервера приложений и конфигурации системы упростят хакеру задачу планирования атаки на приложение.
Внешняя утечка ценной информации. В данном случае речь идёт об утечке технической информации о приложении путем ее передачи по сети на другой компьютер. В целом, внешние утечки опаснее внутренних.
Внутренняя утечка ценной информации. Механизм эксплуатации схож с предыдущими двумя видами утечек, но в данном случае информация о системе записывается в лог или выводится на экран пользователя.
Утечка конфиденциальных данных. Ценные персональные данные пользователей попадают в приложение из разных источников: от самого пользователя, из различных баз данных, из сторонних хранилищ. Иногда эти данные не помечены как конфиденциальные либо оказываются ценными не сами по себе, а только в определённом контексте.
Это как раз тот самый случай, когда безопасность приложения и конфиденциальность персональных данных противоречат друг другу. Для обеспечения безопасности целесообразно подробно записывать информацию о действиях в системе, чтобы выявлять вредоносные действия. С точки зрения приватности данных, наоборот, при логировании конфиденциальной информации риск её утечки больше. В целом же обеспечение конфиденциальности персональных данных пользователей приложения является более приоритетной задачей.
Послесловие
Рассмотренные в статье виды уязвимостей охватывают бОльшую часть «универсальных» брешей в приложениях, написанных на разных языках программирования. Однако для некоторых языков встречаются свои, специфические уязвимости. Но это уже тема для отдельной статьи. А напоследок, напомним: при создании приложений не забывайте следовать вышеизложенным рекомендациям, внимательно читайте документацию и проверяйте приложения на уязвимости с помощью специализированного ПО.
Автор: Елизавета Харламова, руководитель отдела аналитики Solar appScreener