Template Injection
Template Injection
Description
Template Injection is a vulnerability that allows an attacker to inject malicious code into a template-rendered text, which can then be executed by the server. This can lead to a range of attacks, including data theft, privilege escalation, and remote code execution. Template Injection attacks are particularly dangerous because they can be difficult to detect and can offer dangerous capabilities to an attacker.
Here, the code is vulnerable because we're creating the template string using direct concatenation from the user input (userName), allowing the user to control the structure of the template. This can lead to template injection if the user provides a string that contains Mustache template tags.
import 'dart:io';
import 'package:mustache_template/mustache_template.dart';
Future main() async {
var server = await HttpServer.bind(
InternetAddress.loopbackIPv4,
8080,
);
print('Listening on localhost:${server.port}');
await for (HttpRequest request in server) {
final userName = request.uri.queryParameters['name'] ?? 'guest';
// Vulnerable to template injection due to template string concatenation
final template = 'Hello, ${userName}';
final output = Template(template, lenient: true, htmlEscapeValues: false)
.renderString({});
request.response
..write(output)
..close();
}
}
import com.github.mustachejava.DefaultMustacheFactory
import com.github.mustachejava.Mustache
import io.ktor.application.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.http.Parameters
fun main() {
embeddedServer(Netty, port = 8080) {
routing {
get("/") {
val parameters: Parameters = call.request.queryParameters
val userName = parameters["name"] ?: "guest"
// Vulnerable to template injection due to template string concatenation
val mf = DefaultMustacheFactory()
val mustache: Mustache = mf.compile("template", "Hello, $userName")
val writer = StringWriter()
mustache.execute(writer, emptyMap<String, Any>())
writer.flush()
call.respondText(writer.toString())
}
}
}.start(wait = true)
}
Recommendation
To mitigate this vulnerability, it is important to ensure that all user input is properly sanitized and validated before being passed to the server-side template engine.
Template engine will typically have a render
method that takes a context that will be safely embedded in the text.
import 'dart:io';
import 'package:mustache_template/mustache_template.dart';
Future main() async {
var server = await HttpServer.bind(
InternetAddress.loopbackIPv4,
8080,
);
print('Listening on localhost:${server.port}');
await for (HttpRequest request in server) {
final userName = request.uri.queryParameters['name'] ?? 'guest';
// Vulnerable to template injection due to template string concatenation
final template = 'Hello, {{ username }}';
final output = Template(template, lenient: true, htmlEscapeValues: false)
.renderString({'username': username});
request.response
..write(output)
..close();
}
}
import com.github.mustachejava.DefaultMustacheFactory
import com.github.mustachejava.Mustache
import io.ktor.application.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.http.Parameters
import java.io.StringWriter
fun main() {
embeddedServer(Netty, port = 8080) {
routing {
get("/") {
val parameters: Parameters = call.request.queryParameters
val userName = parameters["name"] ?: "guest"
// Use a predefined template and pass untrusted data as values
val mf = DefaultMustacheFactory()
val mustache: Mustache = mf.compile("template", "Hello, {{name}}")
val writer = StringWriter()
mustache.execute(writer, mapOf("name" to userName))
writer.flush()
call.respondText(writer.toString())
}
}
}.start(wait = true)
}
Links
Standards
- OWASP_MASVS_L1:
- MSTG_PLATFORM_2
- OWASP_MASVS_L2:
- MSTG_PLATFORM_2
- PCI_STANDARDS:
- REQ_2_2
- REQ_6_2
- REQ_6_3
- REQ_11_3
- OWASP_MASVS_v2_1:
- MASVS_CODE_4
- SOC2_CONTROLS:
- CC_2_1
- CC_3_4
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5