Информация об уязвимости
Судя по описанию уязвимости, это по-прежнему уязвимость внедрения выражения OGNL. Затронутые версии следующие:- с 1.3.0 до 7.4.17
- с 7.13.0 до 7.13.7
- с 7.14.0 до 7.14.3
- с 7.15.0 до 7.15.2
- с 7.16.0 до 7.16.4
- с 7.17.0 до 7.17.4,
- с 7.18.0 до 7.18.1
Описание патча:
Основная модификация - это xwork-1.0.3-atlassian-10.jar. Ниже приводится углубленный анализ уязвимости и попытка обойти "песочницу" для построения обратного отображения результата выполнения команды.
Анализ уязвимости
Новая версия в основном является модификацией xwork-1.0.3-atlassian-10.jar. Сначала краткое сравнение патчей.
Было внесено много изменений, но самое важное - в функции ActionChainResult#execute, которая обновляет процесс извлечения finalNamespace и finalActionName.
Confluence основан на архитектуре Struts. Мы начнем с запроса на вход в систему в качестве примера для динамической отладки потока обработки запросов Confluence. Происходит обращение к файлу /login.action, и после серии процессов Filter он попадает в ServletDispatcher (который по сути является подклассом объекта ConfluenceServletDispatcher).
Используя getNameSpace、 getActionName、 getRequestMap、 getSessionMap、 getApplicationMap извлеките соответствующие параметры, соответствующие отношения выглядят следующим образом:
- getNameSpace(request)-> namespace
- getActionName(request)-> actionName
- getRequestMap(request)-> requestMap
- getParameterMap(request)-> parameterMap
- getSessionMap(request)-> sessionMap
- getApplicationMap()-> applicationMap
а потом вызовем функцию serviceActionфункция, в подкласс ConfluenceServletDispatcher из serviceActionФункция:
Создадим экземпляр объекта DefaultActionProxy и сделаем его execute:
Перейдем к DefaultActionInvocation#invoke.
Здесь вызывается объект Struts Interceptor для обработки запроса. Всего у объекта DefaultActionInvocation 32 перехватчика.
Функция invoke пытается получить следующий объект перехватчика next и затем вызывает его метод intercept. Формат функции intercept для большинства объектов Interceptor следующий.
И дальше продолжаем вызывать DefaultActionInvocation#invoke, формируя таким образом итерационный цикл. Однако при отладке мы обнаружим, что существуют специальные перехватчики, такие как ConfluenceAccessInterceptor.
Вместо того чтобы продолжать вызывать DefaultActionInvocation#invoke при выполнении определенных условий, возвращается строка notpermitted, и мы анализируем функцию isAccessPermitted.
В основном это делается для того, чтобы определить, имеет ли текущий пользователь, currentUser, права доступа, глядя на запрошенное *.action и methdName. То есть, при обращении к *.action, не имеющему прав доступа, DefaultActionInvocation#invoke вернет notpermitted и присвоит resultCode, когда в итерации будет вызван ConfluenceAccessInterceptor#intercept. что отменяет итерацию. Мы заменяем тестовый запрос на /index.action.
Когда перехватчик ConfluenceAccessInterceptor будет обработан, он не будет продолжать итерацию для вызова следующего перехватчика, а продолжит ее до функции executeResult.
Перейдите к ActionChainResult#execute.
Извлеките параметр пространства имен и вызовите функцию translateVariables
Типичный процесс разбора выражения OGNL, как видно из предыдущего анализа, параметр пространства имен получается через функцию ServletDispatcher#getNameSpace, (см. определение)
Видно, что namespace принимает часть запроса servletPath перед последним /.
Основываясь на правилах регулярных выражений, приведенных выше, легко построить соответствующий URL-адрес для запуска разбора OGNL: the
Успешный запуск инъекции экспрессии OGNL.
Обход песочницы и выполнение команд
Некоторые из эксплойтов, которые сейчас находятся в открытом доступе в сети, просты и грубы, и работают только для v7.14 и ниже, поскольку, начиная с серии v7.15, Confluence добавил настройку песочницы для разбора выражений OGNL: the
Введите функцию isSafeExpression
Основные черные списки следующие: (1) unsafePropertyNames
(2) unsafePackageNames
(3) unsafeMethodNames
Код:
0 = "getClass"
1 = "getClassLoader"
белый список allowedClassNames выглядит следующим образом:
Кроме того, проверяются входящие функции и т.д. (функция containsUnsafeExpression)
Когда вы увидите это, вам должно быть легко придумать множество способов обойти его. Один из способов реализации обратного отображения результата выполнения команды выглядит следующим образом (для всех затронутых версий).
Перевод с китайского.