FlawOpen

flawopen.com/Incidents/postgresql-psql-injection-beyondtrust-treasury-december-2024

● PostgreSQL / BeyondTrust · CVE-2025-1094 · December 2024 – February 2025 · CVSS 8.1 · उच्च
सुरक्षा अनुसंधान · FlawOpen

CVE-2025-1094: PostgreSQL psql में SQL इंजेक्शन

जब ऐप escaped text से psql input बनाता था, अमान्य UTF-8 libpq escaping को bypass कर SQL या \! इंजेक्ट कर सकता था। 13 फ़रवरी 2025 को सुधार हुआ।

💡 आसान भाषा में (ELI5)

एक अनुवादक की कल्पना करें जिसका काम आपकी हर बात को उद्धरण-चिह्नों में रखना है, ताकि उसे कभी आदेश न समझा जाए। आपको पता चलता है कि अगर आप उसे किसी अनजान लिपि का शब्द दें, तो वह उलझ जाता है और एक उद्धरण-चिह्न छोड़ देता है। अब आपकी बात उद्धरण-चिह्नों से बाहर निकलकर निर्देश की तरह पढ़ी जाती है, जबकि अनुवादक ने हर उस इनपुट पर ठीक वैसा ही किया जिसके लिए उसे बनाया गया था और जिसे किसी ने परखा था।

इस पेज के मुख्य शब्द

PQescapeLiteral
libpq का एक फ़ंक्शन जो किसी मान को उद्धरण-चिह्नों में रखकर एस्केप करता है, ताकि उसे SQL टेक्स्ट में डाला जा सके। PQescapeIdentifier, PQescapeString और PQescapeStringConn भी प्रभावित थे।
अमान्य UTF-8
ऐसा बाइट क्रम जो घोषित एन्कोडिंग में सही ढंग से बना न हो। एस्केप कोड और psql इस पर सहमत नहीं थे कि ऐसे बाइट अपने बाद के कितने अक्षर निगल लेते हैं।
psql मेटा-कमांड
बैकस्लैश वाला कमांड जिसे सर्वर नहीं, psql क्लाइंट संभालता है। \! पंक्ति का बाक़ी हिस्सा ऑपरेटिंग-सिस्टम शेल कमांड की तरह चलाता है।
CVE-2024-12356
BeyondTrust Privileged Remote Access और Remote Support में कमांड इंजेक्शन की गंभीर ख़ामी। Rapid7 के परीक्षणों में इसके ज़रिए कोड चलाने के लिए CVE-2025-1094 ज़रूरी थी।
बाउंड पैरामीटर
ऐसा मान जो SQL टेक्स्ट से अलग सर्वर को भेजा जाता है, ताकि उस पर उद्धरण या एस्केप का कोई निर्णय कभी लेना ही न पड़े।

फ्रेमवर्क मैपिंग

  • इस गाइड में बताई गई कमजोरी के लिए CWE संदर्भ: CWE-89 CWE-149

घटना का समयक्रम (Timeline)

2024-12-16

कुछ Remote Support SaaS इंस्टेंस में सेंध की जाँच के बाद BeyondTrust ने CVE-2024-12356 पर सलाह BT24-10 प्रकाशित की; अमेरिकी ट्रेज़री ने बाद में बताया कि यह घटना उसके सिस्टम तक पहुँची थी।

2024-12-19

CISA ने CVE-2024-12356 को Known Exploited Vulnerabilities सूची में जोड़ा।

2025-02-13

PostgreSQL ने CVE-2025-1094 ठीक करने वाले 17.3, 16.7, 15.11, 14.16 और 13.19 जारी किए, और Rapid7 ने अपना विश्लेषण प्रकाशित किया।

हमले का चरण-दर-चरण प्रवाह

चरण 1

इनपुट एस्केप फ़ंक्शन तक पहुँचता है

एक एप्लिकेशन हमलावर से प्रभावित टेक्स्ट लेकर SQL कथन बनाने के लिए उसे PQescapeLiteral या libpq के किसी मिलते-जुलते फ़ंक्शन को देता है।

चरण 2

अमान्य UTF-8 एक उद्धरण-चिह्न छिपा लेता है

PostgreSQL की सलाह के अनुसार, एकल उद्धरण-चिह्न से पहले रखा गया गढ़ा हुआ अमान्य मल्टीबाइट क्रम एस्केप रूटीन को उस चिह्न को बिना एस्केप किए छोड़ने पर मजबूर कर देता था।

चरण 3

psql लिटरल को जल्दी बंद कर देता है

जब कथन psql को दिया जाता है, तो बिना एस्केप वाला उद्धरण-चिह्न स्ट्रिंग लिटरल को बंद कर देता है और बाक़ी इनपुट SQL या psql कमांड की तरह पढ़ा जाता है।

चरण 4

मेटा-कमांड शेल चलाता है

Rapid7 ने दिखाया कि इंजेक्ट किए गए टेक्स्ट में \! मेटा-कमांड हो सकता है, जिसे psql उसी मशीन पर ऑपरेटिंग-सिस्टम कमांड की तरह चलाता है जहाँ वह चल रहा है।

सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन

यह psycopg 3 के साथ उदाहरण के लिए Python कोड है, BeyondTrust का कोड नहीं। कमज़ोर संस्करण सलाह में बताए गए जोखिम भरे पैटर्न को दोहराता है: libpq से मान एस्केप करना, उसे SQL टेक्स्ट में जोड़ना और वह टेक्स्ट psql को भेजना। मज़बूत संस्करण दोनों हिस्से हटा देता है: यह किसी भी प्रोसेसिंग से पहले ग़लत बने UTF-8 को अस्वीकार करता है और मान को असली ड्राइवर के ज़रिए बाउंड पैरामीटर की तरह भेजता है, इसलिए न कोई एस्केप चरण बचता है जिसे धोखा दिया जा सके, न रास्ते में psql का मेटा-कमांड पार्सर। जो कोड अब भी एस्केप करता है, उसके लिए libpq अपग्रेड करना ज़रूरी बना रहता है।

कमज़ोर कार्यान्वयन
import subprocess

import psycopg


def lookup_user(conn: psycopg.Connection, name: bytes) -> bytes:
    # libpq का PQescapeLiteral (17.3/16.7/15.11/14.16/13.19 से पहले) नहीं कर पाता था
    # अमान्य UTF-8 बाइट अनुक्रम के पीछे छिपे उद्धरण चिह्न को निष्क्रिय करना।
    literal = conn.pgconn.escape_literal(name)
    script = b"SELECT id FROM users WHERE name = " + literal + b";\n"
    # psql अपने इनपुट को स्क्रिप्ट की तरह चलाता है, जिसमें \! जैसे मेटा-कमांड भी शामिल हैं।
    result = subprocess.run(["psql", "-At", "-d", "app"], input=script,
                            capture_output=True, check=True)
    return result.stdout
सुरक्षित और सुदृढ़ फ़िक्स
import psycopg

MAX_NAME_CHARS = 128


def lookup_user(conn: psycopg.Connection, name: bytes) -> list[int]:
    try:
        text = name.decode("utf-8")  # reject malformed input at the boundary
    except UnicodeDecodeError:
        raise ValueError("name is not valid UTF-8") from None
    if len(text) > MAX_NAME_CHARS:
        raise ValueError("name too long")
    with conn.cursor() as cur:
        # मान SQL टेक्स्ट से अलग, बाइंड पैरामीटर के रूप में भेजा जाता है,
        # और कोई psql प्रक्रिया (इसलिए मेटा-कमांड पार्सर) शामिल नहीं होता।
        cur.execute("SELECT id FROM users WHERE name = %s", (text,))
        return [row[0] for row in cur.fetchall()]

इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट

स्रोत