
CVE-2020-2551 POC для использования в Интернете
Тестовый POC (можно использовать для внешнего тестирования)
python CVE-2020-2551.py [HOST] [IP]
Попытка изменить codebase для удалённой загрузки классов (провал)
python CVE-2020-TEST.py [HOST] [IP]
(Впервые опубликовано на Anquanke, ссылка на оригинал)
Для изучения этой уязвимости требуются некоторые предварительные знания, например CORBA и RMI.
Кратко опишу:
CORBA — это технический стандарт, разработанный OMG, для распределённых приложений; в нём используется IDL для обеспечения кросс-языковой поддержки, а взаимодействие между клиентом и сервером осуществляется по протоколу IIOP.
RMI — это другая технология распределённых приложений; в Java её можно упростить с помощью JNDI. Клиент и сервер общаются по протоколу JRMP, однако в WebLogic RMI использует протокол T3, о котором ранее уже было немало уязвимостей.
RMI-IIOP объединяет преимущества RMI и CORBA, позволяя развёртывать RMI-приложения через протокол IIOP.
В официальной документации также упоминается:
Серверные объекты RMI могут использовать протокол IIOP и взаимодействовать с CORBA-клиентскими объектами, написанными на любом языке.
Пока оставим WebLogic в стороне и сосредоточимся на том, как написать пример RMI-IIOP.
Код клиента можно посмотреть в тестовом проекте из статьи Заметки о RMI, JNDI, LDAP, JRMP, JMX, JMS в Java (часть 1). Можно самостоятельно скомпилировать HelloClient и HelloServer, либо использовать уже скомпилированные версии из тестового проекта.
Запустите сервер имён в командной строке (входит в состав Java):
start orbd -ORBInitialPort 1050
Запустите серверный HelloServer из командной строки и настройте удалённую отладку. О том, как настроить удалённую отладку в IDEA, можно посмотреть в методе, описанном в начале этой статьи.
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 HelloServer
Конечно, можно не использовать удалённую отладку, а просто запустить и посмотреть результат:
java HelloServer
Запустите клиент в командной строке:
Java HelloClient
В этот момент появится калькулятор; при успешной удалённой отладке можно увидеть следующий стек вызовов:

Команды выполняются в EvilMessage.readObejct():

Кстати, статьи по установке и отладке WebLogic.
Что насчёт RMI-IIOP в WebLogic? В статье О RMI-IIOP в Java упоминается эксплуатация RMI-IIOP в WebLogic; на её основе я провёл некоторые исследования. Using WebLogic’s RMI over IIOP описывает несколько способов использования WebLogic в качестве клиента RMI-IIOP, включая:
Разница между первыми двумя способами, судя по всему, лишь в настройке JNDI_FACTORY.

Ранее при изучении T3-десериализации в WebLogic я разворачивал приложение Helloserver, у которого был доступный метод sayhello(). Я попробовал использовать оба JNDI_FACTORY и через второй JNDI_FACTORY успешно вызвал метод sayHello().

Тогда я немного изменил POC для протокола T3 в WebLogic — фактически просто заменил RMI на IIOP — и обнаружил, что цепочка эксплуатации jtaTransactionManager успешно сработала и отправила jrmp-запрос локальному jrmplisten.

Посмотрим на трафик: при вызове метода remove() отправляется запрос remove__java_lang_Object, в трафике есть вредоносные данные, но магического заголовка aced не найдено.

Предполагаю, что на сервере данные сначала проходят специальный разбор, а затем десериализуются. Если взглянуть на стек вызовов, видно, что вторая половина цепочки выполнения очень похожа на цепочку из ранее рассмотренного нативного RMI-IIOP: в том случае запуск происходил из CDRInputStream.read_value(), а здесь — из IIOPInputStream.read_value() в WebLogic (эта точка read_value также упоминалась в докладе 2019 года).

Здесь запрос сначала обрабатывается в clusterableServerRef.invoke(), который в зависимости от типа invoker вызывает this.invoker.invoke(). В данном случае вызывается Mejb_dj5nps_HomeImpl_WLSkel.invoke(), и поскольку операция — "remove", выполняется ветвь case 6, где вызывается IIOPInputStream.readObject(); в методе read_value() разбираются данные IIOPInputStream и запускается десериализация. Это и есть POC с использованием метода remove().
В [статье Lucifaer](https://lucifaer.com/2020/02/25/WebLogic WLS核心组件RCE分析(CVE-2020-2551)/?from=timeline&isappinstalled=0#2-2-Weblogic解析流程) упоминается использование метода bind() — это также основной способ эксплуатации в интернете. Проследим стек вызовов.

Как и раньше, запрос сначала обрабатывается в clusterableServerRef.invoke(), который в зависимости от типа invoker вызывает this.invoker.invoke(); в данном случае вызывается CobraServerRef.invoke(), а затем в _NamingContextAnyImplBase._invoke(), поскольку va1 равно "bind_any", выполняется ветвь case 0, где вызывается IIOPInputStream.read_any(); далее снова вызывается IIOPInputStream.read_value(), что запускает десериализацию. Ранее я говорил, что в трафике не видно магического заголовка aced — это потому, что в IIOPInputStream есть собственный способ разбора. Hex-value форма IIOPInputStream выглядит следующим образом и содержит имя класса и информацию о полях:

В итоге вызывается метод readObejct() вредоносного класса.