Всем привет! Тут многие просили нас писать больше; собственно, выкроив времечко между перелётами, я вспомнил про парочку старых уязвимостей в… впрочем, вы уже догадались в чём.
Прошло уже немало времени с момента первой публикации информации о данных багах. А точнее, целый год. Ровно год назад я ездил на BlackHat с докладом по теме безопасности J2EE движка SAP. Почему бы и не поведать о той баге, тем более что до сих пор не дошли руки подробно описать в рунете всё, что было представлено на BlackHat, ну не считая небольшого видео с ZeroNights, где вышло довольно сумбурно.
Исследование посвящалось платформе SAP NetWeaver J2EE Engine, о которой по сравнению с ABAP Engine существует крайне мало информации, а по ее безопасности практически не было исследований во всём мире. А ведь Digital Security Research Group хлебом не корми, только дай разломать что-нибудь, куда ещё никто не совался. В общем, сперва будет немножко общих слов о том, что такое SAP и как это важно для бизнеса, так что циники могут пролистать вниз – к кускам кода, ну а все остальные могут читать дальше.
Немного воды
Все бизнес-приложения от SAP основаны на одной из двух платформ, не считая старых решений и всяких вспомогательных приложений. Точнее говоря, есть ещё третья платформа – SAP Business Objects, на которой работает ряд систем, но в целом она менее распространена и в какой-то степени схожа с NetWeaver J2EE Engine.
Платформа номер один, самая старая, известная и более или менее изученная c точки зрения безопасности – это SAP NetWeaver ABAP. На основе данного сервера приложений работают такие системы, как ERP, CRM, SRM, PLM и прочие трёхбуквенные аббревиатуры, которые принято перечислять, чтобы придать себе веса в глазах умных людей. Все эти приложения объединены единой целью – автоматизировать бизнес-процессы. Что это значит, многие до сих пор не в курсе, но для данной статьи это неважно.
Вторая платформа – это SAP NetWeaver J2EE Engine (далее «J2EE-движок»; под J2EE-движком в статье имеется в виду вся платформа сервера приложений полностью, со всеми приложениями, а не ядро виртуальной машины JAVA). Данная платформа, по сути, предназначена для того, чтобы объединять бизнес-приложения, то есть сама по себе она зачастую не содержат никакой критичной информации, но выступает так называемым посредником. В список таких приложений, основанных на платформе NetWeaver J2EE, входит в том числе SAP Portal – этакий универсальный портал предприятия, который обеспечивает единый доступ к различным ресурсам, к примеру, через SSO. На портале нередко можно встретить линк на интерфейс какой-нибудь внутренней SCADA-системы, которая напрямую не доступна, но часть функционала транслируется в портал. Чем это грозит, думaю, понятно. Помимо портала, на J2EE-движке основано, например, приложение SAP XI/PI, которое является интеграционной шиной предприятия и обеспечивает обмен между различными бизнес-приложениями, да и немало других приложений. В общем, к чему я это всё?
Предположим, вам надо получить контроль над бизнес-потоками в отдельно взятой компании (я не буду спрашивать, зачем вам это, а вы не будете спрашивать, откуда мне в голову пришёл этот пример). Для того чтобы это сделать, гораздо проще взломать сервер, который является связующим звеном, чем кучу серверов, обрабатывающих данные. Тем более что по части безопасности ABAP-движка было уже немало исследований, и он постепенно становится более защищённым, чего не скажешь о JAVA-движке, который разрабатывался чуть более чем полностью индусами.
Итак, решено было препарировать J2EE-часть. Наши исследования безопасности JAVA-движка, начатые где-то в 2009 году, привели к тому, что было обнаружено порядка 200 уязвимостей, большая часть из которых на данный момент закрывается производителем. Помимо массы XSS-ок, уязвимостей разглашения информации и прочих относительно банальных проблем, встречались и более интересные баги, о которых, собственно, и поведаю подробнее.
Читать отсюда
Всем известно, что намного круче обнаружить целый класс (ну или хотя бы подкласс) уязвимостей, чем отдельную проблему, так как, обнаружив новый класс, можно будет найти массу примеров. А с примерами в J2EE-движке проблем и подавно не возникнет, ибо платформа SAP NetWeaver J2EE Engine представляет собой сервер приложений стандарта J2EE, который позволяет размещать на себе приложения, написанные на JAVA. Это что-то типа Apache Tomcat, только в 100 раз больше, и сложнее, и непонятнее – а там, где есть сложность, непременно появляются уязвимости. На данном сервере, собственно, и располагаются сами бизнес-системы, такие как SAP Portal, SAP XI, SAP PI, в виде отдельных приложений или набора приложений, а также приложения собственной разработки. Такие крупные системы состоят из более мелких приложений (applications), каждое из которых по сложности и размеру кода сопоставимо зачастую с небольшим web-проектом. Таких приложений по умолчанию устанавливается огромное множество. Так, в версии NetWeaver 6.40 их порядка 500, а в версии 7.2 их уже 1200. Естественно, каждое приложение содержит свои баги, но их там искать – не переискать, и все они довольно специфичны. Мы же хотели найти что-нибудь более общее, какую-нибудь уязвимость массового характера, а значит, она должна потенциально присутствовать во всех приложениях.
А лучше отсюда
Люди, знакомые с J2EE-приложениями, наверное, знают, что всех их объединяет как минимум один файл – web.xml. Люди, ещё ближе знакомые с этим файлом и с SAP, скорее всего, уже догадываются, о чём речь. Но сначала глянем на структуру типичного файлика WEB.XML:
<servlet>
<servlet-name>CriticalAction</servlet-name>
<servlet-class>com.sap.admin.Critical.Action</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Critical</</servlet-name>
<url-pattern>/admin/criticalfunc</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Restrictedaccess</web-resource-name>
<url-pattern>/admin/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
Кто-то уже, наверное, понял, где могла быть ошибка… нет, не спешите тыкать пальцем в незакрытый тег, я имею в виду не просто опечатку, а уязвимость, которая может привести к печальным последствиям. Не нашли? Тогда рекомендую читать дальше. В движке J2EE есть такой механизм, как Invoker Servlet. Он позволяет вызвать любой сервлет (часть приложения, выполняющая функционал на сервере) напрямую, по имени класса, для того чтобы разработчикам было удобно в режиме отладки обращаться к классу напрямую. Во всяком случае, это объясняется так, так что спорить не буду, может, и вправду удобно. Но особенно удобно обходить настройки безопасности, набрав в строке URL имя класса для данного сервлета вот таким образом: /servlet/<servlet-name-or-class>.
А вот тут вообще самый смак
Проблема же начинается в тот момент, когда вы делаете сервлет, выполняющий опасное действие, размещаете его в какой-либо директории типа /admin и закрываете к ней доступ при помощи <auth-constraint> для всех, кроме юзеров с ролью admin. Фейл заключается в том, что к сервлету можно всё равно обратиться напрямую через механизм Invoker по ссылке /servlet/<servlet-name-or-class> и получить необходимые данные без аутентификации, так как прямой доступ к директории /servlet не заблокирован никак (если бы защита стояла на /*, то всё бы было ОК). Вот так просто и лаконично, и не беда, что в J2EE-приложениях нет переполнения буфера и что JAVA типа безопаснее Си, когда встречаются такие архитектурные баги.
Основная проблема для нас заключалась в том, что надо было найти среди всех 500 приложений те, что не фильтровали доступ к Invoker Servlet и выполняли через этот сервлет опасные действия – ведь нужно же показать реальный риск, а не просто ткнуть пальцем в кривую архитектуру со словами: «это теоретически, в особых ситуациях, при условии a+b-c*d может привести к чему-то не очень хорошему».
Один забавный веб-сервис, к примеру, позволяет читать произвольный файл с ОС, и он уязвим к данной баге, а значит, можно читать файлы, хранящиеся на сервере. При желании можно даже выкачать напрямую данные из СУБД и покопаться в финансовых транзакциях… главное, чтобы не завис браузер от открытия и скачки файлов по несколько гигабайт, но это уже совсем другая история.
Я обманул, на самом деле самый смак тут
Что-то мало нам было этой уязвимости, да и не комильфо как-то без шелла на BlackHat ехать. А посему я начал искать дальше: что же ещё можно сотворить с WEB.XML? И тут мне вспомнилась старая статейка об уязвимости типа Verb Tampering. довольно зачётная бага, описанная в теории, а практических примеров на реальных системах вроде и не было. Естественно, я решил попробовать: а вдруг это сработает, и, особо не надеясь на удачу, чуть не подавился утренним пончиком… Оно реально работает – нет, ну не может быть! Шикарно!
После того, как страсти улеглись, я осознал, что мне на самом деле предстоит, поскольку одно дело – обнаружить проблему в архитектуре, а другое – найти реальный пример того, что такие уязвимости существуют. Однако расскажу, в чём же, собственно дело. Итак, вот опять пример горячо любимого нами WEB.XML, а точнее, его часть, отвечающая за разграничение доступа:
<url-pattern>/admin/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
В нашем примере указано, что к приложениям, находящимся в директории /admin, может обращаться только пользователь с ролью admin и выполнять только метод GET. Безопасно? Как бы не так: оказалось, всё, что явно не запрещено – то разрешено, то есть, к примеру, обращение методом HEAD, который делает ровно то же самое, что и GET, только не показывает результат пользователю, может быть реализовано анонимно, без пользователя и без роли вообще. Почему? Да потому, что так написано в файле: в директорию /admin методом GET можно только админам. А другими методами – кому угодно! То есть, если бы название метода не было явно указано, это бы значило, что всеми методами можно ходить только админу, и всё бы было ОК. А раз указал один метод, то уж изволь все остальные перечислить.
Прикажете радоваться? Да не тут-то было: теперь надо опять искать иголку в стоге сена, а точнее, хоть какое-нибудь приложение из установленных на J2EE-движке, которое:
• Уязвимо к Verb Tampering
• Поддерживает HEAD-запрос и обрабатывает его так же, как GET
• Выполняет критичное действие, причём нам не важно тело ответа, поскольку это HEAD
• Желательно присутствует во всех инсталляциях, а не просто как демо-пример
Да, устал. Да, нашёл.
В общем, это приложение называется… а впрочем, это вы можете узнать, внимательно перечитав этот пост. И является оно ни много ни мало управлялкой для J2EE-движка с веб-интерфейсом. То есть можно создать юзера в системе, да что там юзера! Можно ему назначить любую роль, можно выполнить команду ОС, можно удалённо остановить сервер, и всё это одним простеньким HEAD-запросом.
В то же время SAP Portal, который использует J2EE-движок, можно с лёгкостью нагуглить в Интернете. К примеру, вот так: inurl:/irj/portal
Самая классная часть истории заключается в том, что, когда я ездил в Бангалор на конференцию SecurityByte (так называемая «индийская силиконовая долина», вот прямо пишу и сдерживаю хохот), рассказывать презентацию по данной теме, ко мне подошёл ни много ни мало один из разработчиков того самого уязвимого интерфейса, тем самым мои подозрения оправдались. Разработчик, кстати, оказался классным парнем, и я, конечно же, поблагодарил его за то, что помогло мне попасть на BlackHat, так что, если вы ещё гадаете, как это сделать, могу порекомендовать отличную идею. Шучу.
Вот, собственно, и всё на сегодня, дописываю я эти строки в самолёте, несущемся в Лас-Вегас на BlackHat 2012, где собираюсь представлять одну очень изящную багу – кстати, тоже в SAP и тоже по части JAVA, так что ждите отчёт…
Автор: AlexandrPolyakov