Listen to this Post
The vulnerability stems from Jdbi’s FreeMarker integration failing to set a TemplateClassResolver. The underlying `freemarker.template.Configuration` is built with `DEFAULT_INCOMPATIBLE_IMPROVEMENTS` in two locations (FreemarkerConfig and FreemarkerSqlLocator‘s static initializer). Because no `TemplateClassResolver` is installed, FreeMarker defaults to the legacy UNRESTRICTED_RESOLVER. This makes the built-in `?new` operator accessible. An attacker who can control the SQL template source — either directly via a query string or indirectly through a `@Define` attribute that is later evaluated with `?eval` or `?interpret` — can use `?new` to instantiate arbitrary Java classes. For example, instantiating `freemarker.template.utility.Execute` allows them to execute arbitrary operating system commands on the application’s JVM. The sink is FreemarkerEngine.parse(), which constructs a `Template` object from unsanitized user input and renders it, leading to Remote Code Execution (RCE).
Platform: `org.jdbi:jdbi3-freemarker`
Version: up to 3.52.1
Vulnerability: RCE via Template Injection
Severity: Critical
Date: 2023-10-19
Prediction: Patched 2023-11-15
What Undercode Say:
This vulnerability combines two powerful exploitation primitives: direct injection into the SQL templating engine and the abuse of FreeMarker’s class-loading capabilities. The failure exists in two separate static `Configuration` initializers, meaning that hardening only one (FreemarkerConfig) leaves the other (FreemarkerSqlLocator) vulnerable and impossible for developers to override at runtime.
The `?new` built-in can instantiate any class that is accessible in the application’s classpath, including:
Example payload using freemarker.template.utility.Execute
curl -sG 'http://127.0.0.1:8050/search' \
--data-urlencode 'q=<assign ex="freemarker.template.utility.Execute"?new()>${ex("touch /tmp/pwned")}'
// Vulnerable code snippet: Unsanitized SQL string built via concatenation String sql = "select email from users where email like '%" + q + "%'"; jdbi.withHandle(h -> h.createQuery(sql).mapTo(String.class).list());
How Exploit:
- The attacker supplies a crafted `q` parameter containing a FreeMarker payload.
- The application concatenates this payload into the `sql` string.
3. `FreemarkerEngine.parse()` creates a `Template` object from the user-controlled string.
4. `template.process()` is called, and FreeMarker’s `UNRESTRICTED_RESOLVER` permits instantiation offreemarker.template.utility.Execute. - The `Execute` class executes the command (e.g.,
touch /tmp/pwned) on the server.
Protection from this CVE:
Upgrade to version 3.52.2 or higher.
If upgrade is not possible, manually set a secure `TemplateClassResolver` on the `Configuration` objects in both `FreemarkerConfig` and FreemarkerSqlLocator:
c.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
Avoid allowing attacker-controlled text to be used directly as a SQL template source. Always use parameterized queries (@Bind) instead of dynamic SQL generation via `@Define` or string concatenation.
Never use `?eval` or `?interpret` on any user-supplied attribute.
Impact:
Confidentiality: An attacker can read any file accessible to the JVM process.
Integrity: Attackers can modify data by executing system commands (e.g., chmod, rm).
Availability: Attackers can terminate the application or the entire server.
Lateral Movement: The exploited JVM can be used as a pivot point to attack internal networks.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

