flawopen.com/SSTI/FreeMarker dan Velocity
Apakah template FreeMarker dan Velocity aman terhadap input pengguna?
Nilai dari pengguna tetap menjadi data saat dimasukkan ke template tepercaya. Sumber template yang dikendalikan pengguna berbeda: pengguna dapat menulis ekspresi dalam bahasa template. Jangkauan kemampuannya bergantung pada versi, wrapper atau introspector, objek model, dan izin aplikasi. Jangan menganggap setiap injeksi template menjalankan perintah sistem operasi; perlakukan sumber template tak tepercaya sebagai logika yang dapat dieksekusi dan render di luar proses aplikasi.
// Risiko: mengurai data permintaan sebagai sumber template String src = "Hello " + userSuppliedName; Template t = new Template("t", src, cfg); t.process(model, writer); // Risiko: mengevaluasi string VTL yang dikendalikan pengguna Velocity.evaluate(context, writer, "log", userTemplate);
// Template classpath tepercaya; model hanya berisi nilai skalar Configuration cfg = new Configuration( Configuration.VERSION_2_3_34); cfg.setTemplateLoader(new ClassTemplateLoader( App.class, "/templates")); cfg.setNewBuiltinClassResolver( TemplateClassResolver.ALLOWS_NOTHING_RESOLVER); cfg.setObjectWrapper(new SimpleObjectWrapper( Configuration.VERSION_2_3_34)); Template t = cfg.getTemplate("hello.ftl"); Map<String,Object> model = Map.of( "name", userSuppliedName); t.process(model, writer); // Velocity: template tepercaya dan introspeksi terbatas (pertahanan berlapis) Properties p = new Properties(); p.setProperty("resource.loaders", "class"); p.setProperty("resource.loader.class.class", ClasspathResourceLoader.class.getName()); p.setProperty("runtime.introspector.uberspect", SecureUberspector.class.getName()); VelocityEngine engine = new VelocityEngine(); engine.init(p); Template vt = engine.getTemplate("hello.vm", "UTF-8"); VelocityContext vc = new VelocityContext(); vc.put("name", userSuppliedName); vt.merge(vc, writer);
Mengapa mesin Java dapat mengekspos kemampuan berbahaya
Template mengevaluasi ekspresi terhadap model data, tetapi permukaan Java yang tersedia bergantung pada konfigurasi. Wrapper default FreeMarker dapat mengekspos properti dan metode JavaBean dari POJO sembarang; anggota yang tersedia bergantung pada wrapper dan kebijakan akses. Uberspect default Velocity memetakan properti VTL ke metode Java publik. Ini tidak berarti semua model memberi reflection tanpa batas: risikonya meningkat jika model berisi objek layanan, class loader, objek permintaan, atau kemampuan kuat lainnya. Utamakan map string dan nilai sederhana; berikan hanya field yang diperlukan template tepercaya.
Built-in ?new FreeMarker dapat membuat instance class yang menerapkan TemplateModel. Apache menyarankan pembatasan resolusi class untuk template yang diunggah; SAFER_RESOLVER masih mengizinkan sejumlah class, sedangkan ALLOWS_NOTHING_RESOLVER menolak semua resolusi. Kontrol ini tidak menggantikan wrapper terbatas dan model data minimal.
Cara mengurangi risiko dan memahami batasnya
- ✓FreeMarker: untuk template tak tepercaya, setel
new_builtin_class_resolverkeALLOWS_NOTHING_RESOLVERdan gunakan wrapper sepertiSimpleObjectWrapperyang menolak POJO sembarang. Berikan hanya nilai sederhana sesuai kebutuhan. - ✓Velocity: gunakan
SecureUberspectoruntuk template tak tepercaya dan masukkan hanya nilai sederhana yang dibutuhkan ke context. Ini memblokir jalur reflection dan pembuatan objek yang terdokumentasi, tetapi bukan sandbox sistem operasi. - ✓Keduanya: muat template aplikasi dari sumber tepercaya yang terlindungi dari perubahan. Jangan ubah parameter permintaan atau baris database yang dapat diedit pengguna menjadi sumber template.
- ✓Jika template buatan pengguna memang diperlukan: render dalam proses terpisah dengan hak minimum, tanpa jaringan, rahasia, atau file aplikasi yang dapat ditulis; batasi CPU, memori, dan durasi dari luar mesin template.
Anggap pembatasan mesin sebagai pertahanan berlapis, bukan isolasi proses. Gunakan versi yang didukung, tinjau konfigurasi terhadap panduan resmi terkini, dan jauhkan rahasia serta objek berhak istimewa dari renderer.
Pertanyaan umum
Ini risiko terkait tetapi berbeda. Nama view yang dikendalikan pengguna tidak otomatis menjadi kelemahan injeksi ekspresi. Tinjau aliran data spesifik menuju evaluasi Thymeleaf atau Spring Expression Language dan jangan membuat fragmen ekspresi dari input tak tepercaya. Perbarui integrasi dan pilih view melalui logika aplikasi tepercaya.
Penulis template dapat menggunakan kemampuan yang diekspos mesin dan model data; ini tidak selalu berarti eksekusi perintah sistem operasi. Perlakukan izin mengedit template sebagai hak sensitif untuk menulis kode, batasi kepada pemelihara tepercaya, dan audit perubahannya.
Mesin tanpa logika seperti Mustache dapat mengurangi permukaan ekspresi dan pemanggilan metode, tetapi encoding output, kendali sumber template, dan kemampuan helper tetap penting. Pilih mesin yang sesuai model kepercayaan dan isolasi proses render; jangan mengandalkan mesin JVM umum sebagai sandbox.
Sumber resmi dan referensi
- Apache FreeMarker — FAQ keamanan template yang diunggah
- Apache FreeMarker — API SimpleObjectWrapper
- Apache FreeMarker — API TemplateClassResolver
- Apache Velocity — panduan pengembang
- Apache Velocity 2.3 — API ClasspathResourceLoader
- PortSwigger — Server-Side Template Injection
- CWE-1336 — Server-Side Template Injection