Представляем интервью с ведущими экспертами в области безопасности: Владимиром Кочетковым (руководителем отдела исследований анализа защищенности приложений в Positive Technologies) и Михаилом Щербаковым (независимым разработчиком и консультантом в области информационной безопасности).
О чем эта статья? Процитирую одну из реплик Михаила:
«Разработка защищенного приложения – это частный случай разработки приложения, не содержащего ошибок вообще. Кроме этого, ваше приложение использует сторонние библиотеки, защищенность которых тоже не гарантируется, далее оно выполняется на ОС и железе. Часто мы даже не можем сказать, на какой именно ОС и на каком железе. И все это со временем изменяется!»
Владимир Кочетков — с 2006 года работал в предметной области информационной безопасности. В Positive Technologies пришел в 2012 году на должность ведущего эксперта группы анализа защищенности веб-приложений. Участвовал в проектах по анализу защищенности приложений, исследовал методики тестирования приложений. При участии Владимира реализован продукт PT Application Inspector. В 2014-2016 возглавлял группу разработки анализаторов компилируемых приложений и руководил проектом разработки модуля анализа бинарного кода. С сентября 2016 года руководит отделом исследований анализа защищенности приложений. Принимает непосредственное участие в теоретических изысканиях в направлении анализа защищенности приложений и прототипировании перспективных продуктов компании. Автор статей в журналах HITB Magazine, «Хакер» и RSDN Magazine. Неоднократно участвовал в международном форуме Positive Hack Days (в качестве организатора и докладчика) и конференции .NET-разработчиков DotNext, регулярно выступает на встречах user group-разработчиков. Принимает участие в развитии сообщества русскоязычных разработчиков RSDN. Один из организаторов Positive Development User Group — инициативы, направленной на погружение разработчиков в предметную область защиты приложений. Ведет блог kochetkov.github.io.
На DotNext 2017 Moscow приезжает с докладом «Побеждая инъекции».
Михаил Щербаков — Microsoft .NET MVP, участник .NET Core Bug Bounty Program, соорганизатор сообщества .NET программистов, независимый разработчик и консультант. Профессиональные интересы: статический и динамический анализ кода, информационная безопасность, автоматизация отладки кода, исследование внутреннего устройства .NET CLR.
На DotNext 2017 Moscow приезжает с докладом «ASP.NET Core: Механизмы предотвращения атак 2.0».
— Какие типы уязвимостей обычно находят в .NET Framework сейчас?
Михаил Щербаков: Здесь нужно разделять уязвимости в самом .NET Framework и в приложениях, которые написаны на основе .NET-платформы. .NET Framework — это платформа для разработки различных типов приложений: от веб-сайтов и сервисов до десктопных приложений. И это составная часть операционной системы Windows, поэтому и относиться к безопасности .NET Framework надо как к ОС. Основная часть уязвимостей в нем — это не привычные веб-разработчикам XSS, CSRF, SQL/XML/JSON и другие инъекции, а исполнение произвольного кода, повышение привилегий пользователя, раскрытие информации, отказ в обслуживании.
— Расскажите, пожалуйста, что вы знаете об уязвимостях, найденных за последнее время в ASP .NET и в .NET Core?
Михаил: Подробный рассказ получился бы не на один час :) Про уязвимости в «большом» .NET Framework я делал доклад год назад на DotNext Moscow. С демонстрацией примеров эксплойтов и разбором ошибок, которые приводят к этим уязвимостям. Конечно, в 45 минут получилось включить меньше, чем хотелось бы, я старался сосредоточиться на уязвимостях, которые разработчики могут допустить в своих продуктах, в первую очередь, в веб-приложениях, в ASP .NET. Там были примеры DoS, Elevation of Privileges, XXE, Information Disclosure, атаки на десериализацию данных.
Для .NET Core в этом году вышел большой патч, в котором исправлено несколько уязвимостей: DoS, Elevation of Privilege, обходы механизмов защиты. В том числе и найденная мной уязвимость CVE-2017-0256 в защите от Open Redirect. Проблема, как это часто бывает, была в недостаточной валидации входных данных пользователя. Также стоит обратить внимание на Kestrel, я сейчас в свободное время делаю review этого кода, и мое мнение совпадает с позицией Microsoft и .NET Foundation, что он еще не готов для использования на фронте. Обязательно закрывайте его каким-либо reverse proxy (Nginx, Apache, IIS). Думаю, скоро смогу рассказать об этом подробней.
Владимир Кочетков: За последние пару лет наблюдается очередной всплеск уязвимостей платформы, связанных с обработкой XML-документов. В 2013 года наши ребята уже делали доклад на конференции BlackHat EU об OOB-техниках атаки внедрения внешних сущностей XML, повлекший за собой устранение большого числа уязвимостей в самых различных XML-библиотеках, включая и дотнетовский System.Xml. Однако, прогресс не стоит на месте и, спустя несколько лет, мы снова наблюдаем в .NET набор вполне традиционных уязвимостей обработки XML: XXE (CVE-2016-3255), подделка подписи XML-документов (CVE-2016-0132), DoS через специально сформированные XSLT-документы, приводящие к рекурсивным преобразованиям (CVE-2016-0033). Не обошлось и без уязвимостей уровня ОС, непосредственно определяющего защищенность вышележащих уровней. Так, уязвимость CVE-2016-0145 в win32k.sys (по сути, ядре Windows) позволяла атакующему выполнить произвольный код в системе с помощью специально сформированного шрифта (!!), внедренного в какой-либо документ. Разумеется, с помощью этой уязвимости могли быть успешно атакованы и .NET-приложения, осуществляющие работу с документами подходящих форматов.
Отдельно стоит отметить сразу две уязвимости удаленного выполнения произвольного кода, обнаруженные в .NET в этом году: CVE-2017-0160 и CVE-2017-8759. С детальным разбором первой (как и с proof-of-concept кодом ее эксплуатации) можно ознакомиться по адресу https://www.exploit-db.com/exploits/41903/. Разбору второй посвящена отдельная статья в блоге компании FireEye. Примечательно, что данная уязвимость в числе прочих использовалась для внедрения правительственной шпионской системы FinSpy, о которой стало известно благодаря очередной публикации на WikiLeaks.
— Что может стать целью атакующего .NET Framework в первую очередь? Изменились ли цели злоумышленников за период, скажем, в пять лет?
Михаил: Основные цели — это компоненты, используемые в веб-приложениях, различные парсеры, работающие с входными данными, которыми может манипулировать атакующий. Так как .NET Framework есть на каждой современной версии Windows, то любой его компонент потенциально интересен исследователям ИБ для реализации атаки повышения привилегий локального пользователя. Например, CVE-2014-0257 использовалась для выхода из Internet Explorer 11 Sandbox, а CVE-2014-4073 из ClickOnce. Доступ к .NET-объекту из кода, выполняемого в песочнице, был реализован через Managed DCOM. В этом году история с DCOM повторилась, и была найдена CVE-2017-7293, аналогичная по технике атаки. Всю увлекательную историю можно почитать в блоге Google Project Zero team.
За последние несколько лет стали менее интересны в применении атаки по выходу из .NET Sandbox, потому что сама технология используется все в меньшем количестве продуктов. Ее не включили в .NET Core, команда ASP .NET окончательно отказалась от использования песочницы для изоляции приложений внутри IIS, Silverlight практически мертв, последние версии IE стали предупреждать пользователя о выполнении кода сторонних XBAP-приложений. Еще четыре года назад можно было, эксплуатируя CVE-2013-0073, провести атаку Remote Code Execution на компьютере пользователя просто при открытии специально подготовленной страницы в браузере. Я показывал пример этого эксплойта на DotNext Moscow 2014.
Я упомянул про .NET Core, так при работе над ним были исправлены уязвимости в RyuJIT компиляторе: CVE-2015-2479, CVE-2015-2480, CVE-2015-2481. Сейчас открыта бессрочная Bug Bounty программа по поиску уязвимостей в .NET Core с вознаграждениями до $15000, и компоненты .NET Core, конечно же, сейчас являются отличными целями для исследователей ИБ.
Владимир: Это зависит, прежде всего, от того, кем является злоумышленник и атаку какого рода он проводит. В случае автоматизированной массовой атаки целью может являться, к примеру, захват управления как можно большим числом сетевых хостов. Соответственно, в этом случае наугад атакуются свежие уязвимости платформы, популярных фреймворков, движков и библиотек, а также осуществляется подбор учетных данных для известных точек входа по небольшому словарю.
В случае грамотной таргетированной атаки сценарий развивается в лучших традициях пресловутого киллчейна: проводится разведка, подготавливаются эксплоиты, осуществляется внедрение в систему, закрепление в ней и выполнение действий, направленных на достижение цели атакующего. Целью в данном случае, как правило, является разовое получение какой-либо конфиденциальной информации или ее постоянный мониторинг. Применительно к .NET это означает скрупулезный анализ атакующим любых доступных ему исходников, относящихся к атакуемому приложению (включая и исходники самой платформы), использование выявленных уязвимостей нулевого дня, возможно, с упором на код, непосредственно взаимодействующий с базами данным (System.Data, ORM) или другими внешними хранилищами добываемой информации.
В сугубо техническом плане цели атакующих за последние 5 лет мало изменились – все тот же набор уязвимостей, атак и угроз, варьируемый из года в год в незначительных пределах (см. OWASP Top 10, если говорить о веб-приложениях). Из заметных изменений – в последние два-три года наблюдается тенденция к существенному развитию техник закрепления в Windows-системах, что неизбежно влияет на последствия успешной эксплуатации уязвимостей в .NET-приложениях, пока еще традиционно относимым к данной ОС в большинстве случаев.
— Может ли знание основных типов атак помочь разрабатывать защищенные приложения, и если да, то каким образом?
Михаил: Это может помочь. Часто взгляд разработчиков замылен знаниями о «шаблонных» веб-уязвимостях: XSS, Path Traversal, всевозможных инъекциях, и они уделяют мало внимания логическим ошибках, приводящим к нарушению защищенности приложений. Поэтому примеры успешных атак на платформу, под которую вы разрабатываете, расширяет кругозор и позволяет по-новому взглянуть на ваш код. Но для разработки защищенных приложений нужен системный подход. Мы с Владимиром проводили одну из первых встреч SPB .NET Community, посвященную безопасности .NET-приложений, и постарались раскрыть тему как со стороны теории, так и со стороны практики. В сети есть видео этой встречи.
Владимир: Если говорить о принципе «hack-yourself-first», то он попросту не работает. Для того чтобы разработчик мог эффективно защищать приложение, мысля категориями атакующего, он должен быть настолько же профессионален в этом плане, насколько профессиональным является хотя бы среднестатистический предполагаемый атакующий. Для разработчиков это фактически означает получение второй специализации. Борьба с атаками – не их зона ответственности. Основной задачей этапа разработки, с точки зрения обеспечения защищенности приложения, является борьба с недостатками – неэффективной реализацией контролей предметной области защищенности приложений, приводящая к возникновению уязвимостей к атакам различного рода. Достаточно подробно эта тема раскрывалась на встрече сообщества CodeFreeze в Москве, в апреле прошлого года. Там же рассматривались несколько примеров того, как борьба разработчиков с атаками вместо недостатков может привести к появлению уязвимостей в их приложениях.
Безусловно, знать основные типы атак разработчикам стоит, хотя бы для общего развития. Но использовать эти знания для принятия решений, касающихся защиты разрабатываемых ими приложений, не стоит. Разработчиков, интересующимся спецификой проведения атак на приложения ASP.NET, возможно, заинтересует моя статья «Взломать сайт на ASP.NET? Сложно, но можно!», опубликованная в 165-ом номере журнала «Хакер» (стр.63).
— На каких аспектах безопасности .NET Framework стоит акцентировать внимание разработчика и почему?
Михаил: Для разработчика это, прежде всего, валидация всех входных данных, санитизация выходных данных. Про валидацию входных данных говорят еще со школы. Все, что приходит от пользователя, должно быть проверено на соответствие требованиям (в том числе и требованиям модели безопасности). И главное – делать это правильно: использовать проверку по «белым» спискам там, где это возможно, правильно описывать грамматику формата входных данных (это я к тому, что не надо парсить XML или HTML регулярными выражениями). Это и следование всем приевшимся принципам Secure by Design/Default/Deployment.
Плюс есть набор best practice по разработке защищенных приложений, например OWASP Developer Guide, What not to do in ASP.NET, and what to do instead. Знание и следование им не менее важно, чем знание архитектурных паттернов и принципов SOLID.
Владимир: Прежде всего, акцентировать внимание стоит на предварительной обработке входных и выходных данных. Применительно к .NET это означает:
а) Строгую типизацию всех данных, получаемых извне. Любые внешние данные, получаемые в виде System.String, должны преобразовываться в конкретные сущности бизнес-логики и далее использоваться именно в таком виде (если, конечно, семантика входных данных не подразумевает, что это и есть сущности-строки, типа «текст сообщения на форуме»). Однако, несмотря на необходимость типизации всех входных данных, нужно помнить о том, что применительно к любым непримитивным типам, она может повлечь за собой серьезные проблемы безопасности, такие как SSRF, уязвимости десериализации и т.п.
б) Семантическую валидацию всех типизированных внешних данных. В идеале, необходимо определить инварианты для каждой сущности и обеспечить их соблюдение средствами контрактного программирования, такими как CodeContracts или PostSharp Contracts.
в) Синтаксическую санитизацию всех данных, отдаваемых наружу в соответствии с грамматикой принимающей стороны. Здесь необходимо помнить, что необходимость применения тех или иных санитизаторов зависит не только от грамматики принимающей стороны, но и от контекста, в котором передаются данные. Так, например, использование HttpUtility.UrlEncode
для данных, передающихся, например, в JavaScript-код, оставит приложение уязвимым к атаке XSS. Большинство санитизаторов в .NET сосредоточены в классах HttpUtility
, HttpServerUtility
, WebUtility
и System.Web.Security.AntiXss
. Также стоит обратить внимание на нашу библиотеку LibProtection, первый публичный релиз которой запланирован на 13 ноября этого года и которой посвящен мой доклад на предстоящей DotNext Moscow 2017.
— Какие типы уязвимостей .NET Framework, мешающие (или мешавшие раньше) вашей работе, вы могли бы назвать?
Михаил: Любые уязвимости больше помогают моей работе, чем мешают :) Разбирая уязвимости в .NET FW, можно изучать новые типы атак и (анти)паттерны написания кода. Это помогает разрабатывать защищенные приложения и проводить анализ защищенности систем.
Владимир: Характер моей работы таков, что любая уязвимость в .NET ей скорее способствует, нежели мешает. Но если говорить о любимых уязвимостях .NET, то такой однозначно является нашумевшая в 2010 году подверженность атаке на оракул дополнения в реализации паттерна encrypted token в ASP.NET WebForms (CVE-2010-3332), позволявшая читать произвольные файлы веб-сервера и подделывать аутентификационные токены. С детальным разбором этой атаки можно ознакомиться в презентации.
— Какие ошибки в аспекте безопасности чаще всего допускают разработчики приложений .NET Framework?
Михаил: По моему опыту проведения security review веб-проектов – это всевозможные инъекции «в широком смысле слова»: XSS, SQLi, XXE, Path Traversal и проблемы конфигурации приложений. Это же подтверждают данные, на основе которых составлен известный рейтинг OWASP Top 10 этого года и отчеты ИБ компаний.
Инъекции возможны только при недостаточной валидации входных данных и неправильной санитизации выходных, я про это говорил выше. Ошибки в конфигурации решаются следованием лучшим практикам и использованием сканеров уязвимостей.
Владимир: Как я уже сказал выше, весьма значительная часть проблем безопасности связана с неэффективной предварительной обработкой данных. Это подтверждает и ежегодная статистика уязвимых веб-приложений, публикуемая компанией Positive Technologies. Так, по данным за 2016 год, наиболее характерными для приложений ASP.NET являются уязвимости к атакам межсайтового скриптинга, подбора учетных данных и утечки информации.
— Какие наиболее эффективные методы борьбы с атаками на .NET приложения вы можете назвать?
Михаил: Обычно цель любого производителя ПО — это не борьба с атаками, а разработка защищенных приложений, гарантия конфиденциальности пользовательских данных. Поэтому к безопасности нужно подходить с точки зрения защиты, а не атаки.
Разработка защищенных приложений — это, в первую очередь, продуманный риск-менеджмент. Нельзя разработать максимально защищенное приложение «случайно», только благодаря квалификации разработчиков. Уровень защищенности каждого компонента приложения — это такое же требование, на выполнение которого необходимы ресурсы как на этапе разработки, так и на этапе тестирования. Необходимо понимать цену риска атаки на каждый компонент и исходя из этого принимать решение, сколько усилий тратить на предотвращение этого риска. И в любом случае иметь план действий, если риск был реализован, т.е. ваше приложение было успешно атаковано.
Если вы все-таки готовы к дополнительным затратам, то тут важен системный подход. Необходимо планомерно внедрять техники Secure Development Lifecycle (SDL) в процесс разработки, совершенствовать культуру разработки в компании: добавить этап security review в процесс выпуска продукта, разработать и внедрить best practices по написанию защищенных приложений, заниматься обучением разработчиков в компании, уделять внимание безопасности на этапе тестирования, проводить тесты на проникновение (как внутренние, так и внешние), постоянно использовать «white box» и «black box» сканеры, чтобы максимально автоматизировать процесс поиска уязвимостей, принимать превентивные меры защиты, например, использовать Web Application Firewall (WAF).
Владимир: Безотносительно специфики .NET, общими принципами обеспечения безопасности приложений являются:
- встраивание SSDL (Secure Software Developent Lifecycle) в общий цикл разработки ПО;
- акцентирование разработчиков на борьбу с недостатками в коде;
- использование межсетевых экранов уровня приложения на этапе эксплуатации.
Кроме того, конкретно разработчикам .NET-приложений стоит обратить внимание на шпаргалку по безопасности .NET от OWASP и замечательную книгу Стэна Драпкина «Security Driven .NET», раскрывающую специфику обеспечения безопасности .NET-приложений с уклоном в криптографию.
— Сталкивались ли вы со взломом собственных .NET-приложений? Если да, можете рассказать об этом подробнее? Может быть, можете рассказать пару случаев об аналогичных ситуациях с приложениями знакомых разработчиков?
Михаил: У меня интересных примеров не было. Первое, что приходит в голову, — это исследование команды SCADA Strangelove, в котором они «смоделировали» атаку на SCADA/HMI-систему компании Siemens WinCC. Сервер WinCC Web Navigator написан на платформе .NET, и исследователи нашли целый ворох уязвимостей в нем: XPath Injection, Path Traversal, больше 20 XSS, CSRF, SQLi и другие. Используя эти уязвимости, ребята предположили, как могла бы выглядеть атака на реальные SCADA-системы, если злоумышленник находится за периметром атакуемой сети, как в реальном мире. Можно посмотреть доклад с PHDays об этой атаке.
Владимир: Самым запомнившимся случаем стала атака на пользователей форумов сайта RSDN.org в мае 2014, движок которого в настоящий момент работает на ASP.NET MVC. Один из завсегдатаев, обидевшись на политику модерирования, стал методично брутфорсить учетные данные других пользователей и использовать их для публикации лавины бессмысленных либо оскорбительных сообщений. На тот момент движок сайта не использовал какие-либо средства контроля сложности используемых паролей, и в результате атакующему удалось подобрать пароли к более чем десятку учетных записей, прежде чем атака была остановлена. В формах регистрации и смены пароля был реализован контроль его сложности и сброшены пароли пользователей, чьи учетные записи успел заполучить злоумышленник.
После этого мы взяли базу хэшей паролей пользователей и осуществили оффлайн-атаку подбора паролей по словарю из ~250K элементов. В результате на 83165 зарегистрированных на тот момент пользователей пришлись 11017, чьи пароли удалось подобрать в разумное время. Их пароли также были сброшены, а на почту отправлены уведомления о необходимости пройти процедуру восстановления пароля.
Примечательно, что после всего этого у атакующего по-прежнему осталась возможность использовать учетные записи, под которыми он уже успел осуществить вход и чьи авторизационные cookies использовал для организации атаки. Дело в том, что аутентификационный токен ASP.NET реализует концепцию т.н. «отсоединенной аутентификации» и, в силу дизайна ASP.NET, является пожизненно валидным, без возможности отозвать его у конкретного пользователя.
Таким образом, даже после изменения паролей пострадавших пользователей, у атакующего остались на руках рабочие токены аутентификации, используя которые он мог беспрепятственно входить под этими пользователями и в дальнейшем. Для того чтобы сделать невалидными все имеющиеся у него токены, нам пришлось изменить machine key, используемый для шифрования билетов аутентификации, что привело в негодность абсолютно все ранее выданные токены и стало причиной принудительной массовой реаутентификации всех пользователей сайта.
— Возможно ли сделать на 100% защищенное приложение при помощи .NET Framework? Что для этого требуется?
Михаил: Нет. Невозможно сделать на 100% защищенное приложение на любой платформе. Все даже еще хуже, если вы при помощи магии и сделки с дьяволом создадите 100% защищенное приложение, вы не сможете доказать, что оно на 100% защищено! Теоретически невозможно верифицировать любой нетривиальный алгоритм за адекватное время, в том числе на требования защищенности.
Разработка защищенного приложения – это частный случай разработки приложения, не содержащего ошибок вообще. Думаю, каждый разработчик интуитивно понимает, что это недостижимый идеальный результат, к которому мы все бесконечно стремимся. Кроме этого, ваше приложение использует сторонние библиотеки, защищенность которых тоже не гарантируется, далее оно выполняется на ОС и железе.
Часто мы даже не можем сказать, на какой именно ОС и на каком железе. И все это со временем изменяется! Я думаю, любая попытка достичь 100% обречена на провал при таком количестве неизвестных.
На мой взгляд, .NET Framework — это хороший выбор для построения защищенных приложений. Я бы уже делал ставку на .NET Core. Это небольшой, кроссплатформенный open source-фреймворк, поддерживаемый крупной компанией, имеющей огромный опыт в разработке защищенных систем. Предвижу скепсис линуксоидов по поводу последней фразы :) Если не вдаваться в статистику найденных и исправленных уязвимостей, для меня был показательным батл «Windows vs. Linux» на одном из ZeroNights, где в конце аудитория решала, что является более защищенной платформой… За Windows проголосовало большинство!
Владимир: Давайте чуть-чуть пофантазируем и представим, что это действительно возможно. Иными словами, мы допускаем, что существует некоторое конечное множество правил, следуя которым разработчик гарантированно получит на выходе безопасное приложение. Что из себя представляет каждое такое правило? Это некий алгоритм, пошагово описывающий действия разработчика для создания им безопасного приложения. Как мы уже условились, множество всех таких алгоритмов конечно, а, следовательно, перечислимо и разрешимо. Рассмотрим дополнение этого множества, т.е. множество всех остальных теоретически возможных алгоритмов, не влияющих на безопасность приложения. Очевидно, что оно бесконечно и включает в себя алгоритмы по признаку наличия у них вполне конкретного нетривиального и инвариантного свойства. А это значит, что по теореме Райса оно является неразрешимым. Но, поскольку оно неразрешимо, то его дополнение (т.е. то самое множество правил разработки безопасного приложения) по следствию из теоремы Поста не является перечислимым. А следовательно, быть конечным, ну никак не может.
Если же перейти из теоретической плоскости к прикладной, то концепция управляемого кода и строгого контроля типов избавляет .NET-разработчиков от необходимости задумываться о низкоуровневых проблемах безопасности, связанных с повреждениями памяти, разыменованием нулевых указателей, форматными строками, смешения типов и т.п. Однако все высокоуровневые недостатки защищенности, связанные с предварительной обработкой данных, контролем доступа и многопоточным доступом к ресурсам по-прежнему остаются возможными. Не говоря уже о недостатках бизнес-логики, для которых в настоящий момент не существует даже внятной классификации или формальной модели, а следовательно, и рекомендаций о том, как их избежать.
— Чего, по вашему мнению, не хватает в .NET с точки зрения безопасности?
Михаил: Я бы хотел видеть более прозрачный для разработчика процесс санитизации данных, чтобы программист не думал о контексте, куда эти данные будут вставлены. Частично это можно реализовать при текущем подходе. Например, парсер cshtml страниц знает про контекст, в который будут вставлены данные, а именно, знает все вложенные грамматики текущей ноды в дереве разбора. Значит, он может полностью корректно санитизировать данные в этом контексте, чтобы избежать даже теоретической возможности инъекции. Сейчас об этом нужно заботиться программисту и выбирать правильный алгоритм санитизации, т.е. верный вызов encoder’а или последовательность вызовов.
Так как .NET Core — это полностью открытый проект, надеюсь, что у меня дойдут руки хотя бы до proof-of-concept-реализации этой идеи в ближайшее время. Или я буду счастлив, если кто-нибудь из читателей подхватит эту идею и реализует ее.
Следующая вещь — это защита сессионных данных. Это проблема известна со времен «большого» .NET Framework. В .NET Core она несколько усугубилась, и у злоумышленника есть больше возможностей на проведение атаки Session Fixation. Я буду подробно рассказывать в том числе и про это через несколько дней в докладе «ASP.NET Core: Механизмы предотвращения атак 2.0» на DotNext 2017 Moscow.
И третье, на мой взгляд, ASP.NET-шаблоны по умолчанию должны навязывать best security patterns в написании веб-приложений, чтобы прививать правильные подходы в разработке защищенных систем. В основном необходимы мелкие изменения, такие как включенный и правильно настроенный CSP, защита от CSRF для всех POST/PUT/DELETE-запросов, добавленные security headers в ответы сервера. Но часто именно отсутствие этих мелочей может являться причиной успешной атаки на ваше приложение.
Владимир: В первую очередь, устранение «детских болезней», связанных с безопасностью и тянущихся еще с первых версий фреймворка. Взять хотя бы BinarySerializer (используемый в том же Remoting). При десериализации этот сериализатор не проверяет соответствие ожидаемого и десериализуемого типов перед созданием экземпляра. Это позволяет атакующему передать десериализатору произвольный тип, в результате чего будет выполнен конструктор этого типа, заполнены все его свойства и позднее выполнен его финализатор. Этого достаточно, чтобы любое приложение, десериализующее входные данные с помощью BinarySerializer, оказалось безусловно подвержено атакам на удаление произвольных файлов и SSRF на контролируемый атакующим SMB-сервер, а также (при выполнении определенных условий) – и атакам на выполнение произвольного кода: https://blog.scrt.ch/2016/05/12/net-serialiception/. Ничего не мешает реализовать в BinarySerializer предварительную проверку соответствия ожидаемого типа десериализуемому ДО создания экземпляра. А нынешнее поведение сделать опциональным для обратной совместимости.
Если же говорить о C#, то, с точки зрения безопасности, в нем очень не хватает встроенных средств контрактного программирования. Хотя бы на том уровне, на котором это реализовано в языке Nemerle, где для любого метода или класса могут быть определены функции, подтверждающие выполнение пред- и постусловий для методов или обеспечивающие контроль инвариантов в случае классов. В C# можно было бы пойти дальше и позволить определять эдакие «строгие» методы и классы, отмечая их ключевым словом типа «strict», для которых явные проверки их контрактов были бы обязательными. Это закрыло бы значительную часть проблем, связанных как с недостатками предварительной обработки данных, так и с уязвимостями бизнес-логики.
Комментарии (10)
icepro
08.11.2017 03:36Что такое «отсоединенная аутентификация»? Где почитать можно?
VladimirKochetkov
08.11.2017 11:58Сходу дать ссылки затрудняюсь. Это также называют stateless- или token-аутентификацией. Её суть в том, что после успешной аутентификации на сторону клиента отдаётся зашифрованный токен, содержащий достаточную информацию для его последующей аутентификации без обращения к базе данных или данным сессии. Ранее таким токеном являлась кука .ASPXAUTH, сейчас — .AspNet.ApplicationCookie.
RainbowJose
08.11.2017 07:52У вас приложения декомпилируются, господа. Вы что там вообще защищать собрались?
VladimirKochetkov
08.11.2017 12:01Возможность декомпилирования здесь не играет никакой роли. Принцип Керкгоффса-Шеннона в полной мере распространяется и на предметную область безопасности приложений.
eugenebb
Интересно, был ли опыт использования инструментов статического и динамического анализа (типа HP Fortify, Veracode, IBM AppScan и т.п.) и какова оценка их эффективности и необходимости?
olegchir Автор
попробую связаться с Владимиром и Михаилом и спросить. Но тут надо понимать, что в ближайшее время они скорей всего не ответят, учитывая что DotNext на носу (12-13 число), надо готовиться к нему и лететь в Москву, и вероятно, писать поэмы в комментариях просто некогда
ARG89
Вопрос к yu5k3 и VladimirKochetkov
VladimirKochetkov
У нас с Михаилом есть существенный опыт разработки таких инструментов :) Фактически, мы являемся авторами первой релизной версии модуля анализа .NET приложений в PT Application Inspector. Кроме того, в настоящий момент, я занимаюсь исследованиями технологий анализа приложений, которые в дальнейшем реализуются, в том числе, в этом анализаторе.
Анализатор (безотносительно конкретного продукта) не делает ничего такого, чего бы не смог сделать человек, имеющий опыт анализа защищённости приложений и ревью безопасности их кода. Разница тут только во времени анализа в пользу анализатора и в точности получаемых результатов в пользу человека. Если такого человека в команде или на аутсорсе нет, то иметь анализатор необходимо. Иначе непонятно, кто и каким образом будет оценивать защищённость проекта на регулярной основе, т.к. эта задача определённо лежит вне компетенций и зоны ответственности его разработчиков.