FlawOpen

flawopen.com/Vulnerabilities/Server-Side Template Injection (SSTI)

Server-Side Template Injection (SSTI): Penyebab dan Perbaikan

Impact depends on reachable template behavior CWE-1336 Template Engine Security
πŸ’‘ Penjelasan sederhana β€” data atau instruksi printer

Bayangkan perusahaan yang mencetak surat dengan templat β€œHalo, {{ name }}”. Cara yang aman memberikan templat tetap dan nama pelanggan sebagai data secara terpisah. Cara yang tidak aman menyisipkan teks pelanggan ke dalam instruksi templat sebelum dicetak. Jika mesin templat menafsirkan teks itu sebagai sintaks templat, terjadilah Server-Side Template Injection. Dampaknya bergantung pada mesin, konfigurasi, objek yang tersedia, dan hak proses; evaluasi ekspresi tidak otomatis berarti perintah sistem operasi dijalankan.

Target: penyusunan source templat dan rendering sisi server pada mesin seperti Jinja, Twig, FreeMarker, dan ERB.
Batas rentan: input tidak tepercaya dikompilasi atau diurai sebagai source templat, bukan diberikan sebagai nilai kepada templat tepercaya.
Dampak: evaluasi ekspresi templat; dampak lanjutan bergantung pada kemampuan mesin, objek yang terekspos, sandbox, dan hak proses.
Perbaikan: pertahankan source templat yang tepercaya dan statis; berikan input tidak tepercaya hanya sebagai data konteks. Isolasi rendering templat buatan pengguna bila fitur itu diperlukan.

Konsep inti dan istilah subsistem

Mesin templat
Komponen sisi server seperti Jinja atau Twig yang mengurai sintaks templat dan menghasilkan output dari templat serta data konteks.
Injeksi source templat
Cacat ketika teks eksternal dimasukkan ke source sebelum parsing sehingga ditafsirkan sebagai sintaks templat, bukan data biasa.
Data konteks
Nilai yang diberikan secara terpisah kepada templat tetap yang tepercaya. Pemisahan yang benar mencegah nilai seperti {{ 7 * 7 }} diurai ulang sebagai source.
CWE-1336
Netralisasi elemen khusus yang digunakan dalam mesin templat secara tidak tepat. Kategori ini mencakup pemrosesan input eksternal sebagai sintaks templat yang tidak aman.

Alur serangan langkah demi langkah

Step 1

Input yang dikendalikan penyerang mencapai jalur templat

Field formulir, nilai profil tersimpan, atau string lain yang dipengaruhi pihak luar mencapai kode yang membuat atau mengompilasi templat. Batas rentannya adalah penyusunan source, bukan sekadar rendering nilai.

Step 2

Aplikasi mencampur data dengan instruksi templat

Aplikasi menyisipkan string tidak tepercaya ke source templat (misalnya f-string yang diteruskan ke render_template_string) alih-alih memakai templat statis dan nilai konteks terpisah.

Step 3

Mesin mengurai source gabungan

Mesin menafsirkan ekspresi sesuai bahasa dan konfigurasinya. Ekspresi aritmetika yang tidak berbahaya dapat menunjukkan evaluasi; hal itu sendiri tidak membuktikan akses ke file, rahasia, atau perintah sistem.

Step 4

Dampak bergantung pada mesin dan deployment

Dampak lanjutan bergantung pada objek/fungsi yang tersedia, perilaku sandbox, pembatasan mesin, dan hak proses web. RCE mungkin terjadi pada konfigurasi tertentu, tetapi bukan akibat otomatis setiap SSTI.

Mekanisme dan akar masalah

SSTI terjadi ketika aplikasi menjadikan teks yang dipengaruhi pihak luar sebagai bagian program templat sebelum parsing. Pada Flask/Jinja, pola rentannya membuat string source baru dari data request lalu mengirimkannya ke render_template_string(); HTML escaping melindungi konteks output dan tidak mengubah source templat yang tidak tepercaya menjadi data. Perbaikannya adalah memuat templat tetap lalu memberikan nilai secara terpisah sebagai konteks. Jika pengguna perlu menulis templat, berikan model data minimal dan lakukan rendering di worker terisolasi dengan batas sumber daya. Sandbox adalah pertahanan berlapis, bukan alasan untuk mengekspos rahasia atau objek aplikasi yang berkuasa.

flask_app.py (Pola rentan)Rentan
# VULNERABLE: request data becomes template source before parsing.
from flask import Flask, request, render_template_string
app = Flask(__name__)

@app.route("/greet")
def greet():
    name = request.args.get("name", "Guest")
    # A value such as {{ 7 * 7 }} is interpreted by the template engine.
    source = f"<h1>Welcome, {name}!</h1>"
    return render_template_string(source)
flask_app.py (Pola aman)Diperkuat
# HARDENED: fixed template source; request data stays a context value.
from flask import Flask, request, render_template
app = Flask(__name__)

@app.route("/greet")
def greet():
    name = request.args.get("name", "Guest")
    return render_template("greet.html", name=name)

# templates/greet.html is trusted, static source:
# <h1>Welcome, {{ name }}!</h1>

Urutan serangan dan contoh konseptual

Aturan pencegahan dan perlindungan engineering

Sumber utama dan topik keamanan terkait:Direktori Keamanan Lengkap β†’
CWE-1336: Injeksi Mesin Templat β†’ OWASP WSTG: Server-Side Template Injection β†’ Jinja: Sandbox dan Pertimbangan Keamanan β†’ Jinja API: Templat dan loader β†’ Flask: Rendering Templat β†’