FlawOpen

flawopen.com/SSTI/Jinja2

क्या Jinja2 का render_template_string() सुरक्षित है?

CWE-1336: सर्वर-साइड टेम्पलेट इंजेक्शनसंदर्भ पृष्ठ
संक्षिप्त उत्तर

render_template_string() का उपयोग तभी करें जब टेम्पलेट स्ट्रिंग एप्लिकेशन कोड में तय हो। यदि Jinja के पार्स करने से पहले अविश्वसनीय इनपुट उस स्ट्रिंग में जोड़ा जाता है, तो सर्वर-साइड टेम्पलेट इंजेक्शन (SSTI) होता है। Flask के डिफ़ॉल्ट, बिना sandbox वाले Jinja वातावरण में प्रभाव में कोड चलना शामिल हो सकता है; यह उपलब्ध ऑब्जेक्ट, कॉन्फ़िगरेशन और एप्लिकेशन पर निर्भर है और हर deployment में अपने-आप नहीं होता।

असुरक्षित
# All four are the same bug
render_template_string(f"Hi {name}")
render_template_string("Hi " + name)
render_template_string("Hi %s" % name)
render_template_string("Hi {}".format(name))

# A very common real-world shape:
@app.errorhandler(404)
def not_found(e):
    return render_template_string(
        f"<h1>No such page: "
        f"{request.path}</h1>"
    ), 404
# The URL path is attacker-controlled.
ठीक किया गया
# Template is a literal; the user value
# arrives as a named context variable
render_template_string(
    "Hi {{ name }}", name=name
)

# Better still, a real template file
render_template("greeting.html",
                name=name)

# For the 404 case, no template
# evaluation is needed at all:
return render_template("404.html",
                       path=request.path), 404

हमलावर के नियंत्रण वाला टेम्पलेट सोर्स क्यों जोखिमपूर्ण है

Flask डिफ़ॉल्ट रूप से टेम्पलेट को config, request और session जैसे एप्लिकेशन ग्लोबल उपलब्ध कराता है। यदि हमलावर टेम्पलेट सोर्स नियंत्रित करता है, तो Jinja उस वातावरण में उपलब्ध ऑब्जेक्ट के साथ अभिव्यक्तियों का मूल्यांकन करता है। असर इस बात पर निर्भर करता है कि एप्लिकेशन कौन-से ऑब्जेक्ट और क्षमताएँ उजागर करता है। एक निरापद गणितीय अभिव्यक्ति मूल्यांकन की पुष्टि कर सकती है, लेकिन अकेले इससे कोड निष्पादन या डेटा पहुँच सिद्ध नहीं होती।

यदि एप्लिकेशन ने संवेदनशील मान कॉन्टेक्स्ट में रखे हैं, तो टेम्पलेट उन्हें उजागर कर सकता है। उदाहरण के लिए Flask के config में SECRET_KEY या डेटाबेस सेटिंग हो सकती हैं, लेकिन deployments अलग-अलग होते हैं। टेम्पलेट को दिखने वाले डेटा में secrets न रखें और output escaping को टेम्पलेट मूल्यांकन रोकने वाली सीमा न मानें।

CVE-2024-56201 एक अलग मामला है

यह Jinja compiler की अलग कमजोरी है और सामान्य SSTI के लिए आवश्यक नहीं: CVE-2024-56201 Jinja 3.0.0 से 3.1.4 तक को प्रभावित करती है, जब हमलावर टेम्पलेट की सामग्री और उसका नाम दोनों नियंत्रित कर सके। इस स्थिति में sandbox के बावजूद मनमाना Python कोड चल सकता था। Jinja 3.1.5 में सुधार हुआ। यदि आपका ऐप हमलावर द्वारा दिए गए टेम्पलेट या नाम स्वीकार करता है, तो advisory देखें और upgrade करें।

यह समस्या कहाँ दिखती है

यह पैटर्न ऐसे error page में मिल सकता है जो अनुरोधित path दिखाता है, ईमेल टेम्पलेट के admin फीचर में, tenant-विशिष्ट branding में, और उन preview या debug endpoints में जिन्हें सार्वजनिक नहीं होना चाहिए।

अक्सर पूछे जाने वाले प्रश्न

क्या autoescape इससे बचाता है?

नहीं। Autoescape rendered values को escape करके output में XSS का जोखिम घटाता है। यह उपयोगकर्ता की स्ट्रिंग को template source के रूप में compile होने से नहीं रोकता। दोनों नियंत्रण अलग-अलग चरणों पर काम करते हैं।

अगर मुझे उपयोगकर्ता टेम्पलेट स्वीकार करने हों, जैसे ईमेल अनुकूलन के लिए?

Jinja उपयोगकर्ता-लिखित टेम्पलेट के लिए SandboxedEnvironment देता है, लेकिन उसके दस्तावेज़ कहते हैं कि यह पूर्ण सुरक्षा नहीं है। केवल आवश्यक डेटा दें, side effect वाले ऑब्जेक्ट से बचें और template engine के बाहर CPU, memory और process सीमित करें। Sandbox, parsing से पहले अविश्वसनीय इनपुट जोड़ने को सुरक्षित नहीं बनाता।

मौजूदा codebase में इसे कैसे खोजें?

render_template_string खोजें और देखें कि पहला argument ऐप द्वारा तय स्थिर string है। उपयोगकर्ता मान named context variables के रूप में दें या template file उपयोग करें। गतिशील रूप से template compile करने वाले API और उनके नाम नियंत्रित करने के रास्ते भी जाँचें।

संदर्भ

यह भी देखें SSTI: कारण, प्रभाव और template injection का बचाव Server-side template injection क्या है? FreeMarker और Velocity SSTI: टेम्पलेट सुरक्षा