[pitboss] phase 04: Track J.2 + Track L.2 — SSTI corpus + Jinja2 / ERB / Twig / Thymeleaf / Handlebars adapters

This commit is contained in:
pitboss 2026-05-17 18:51:13 -05:00
parent b5e6dddf2c
commit 8583b29796
34 changed files with 1868 additions and 29 deletions

View file

@ -0,0 +1,50 @@
//! Java Thymeleaf `Cap::SSTI` payloads.
//!
//! Vuln payload: `[[${7*7}]]` — Thymeleaf evaluates the SpEL-style
//! expression inside the inlined-output marker and renders `49`.
//! Benign control sends the literal `7*7` text; without the `[[${...}]]`
//! markers Thymeleaf passes the payload through unchanged.
use super::super::{CuratedPayload, Oracle, PayloadProvenance, PayloadRef};
use crate::dynamic::oracle::ProbePredicate;
pub const PAYLOADS: &[CuratedPayload] = &[
CuratedPayload {
bytes: b"[[${7*7}]]",
label: "ssti-thymeleaf-eval",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: false,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/java_thymeleaf/vuln.java",
],
oob_nonce_slot: false,
probe_predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
benign_control: Some(PayloadRef {
label: "ssti-thymeleaf-benign",
}),
no_benign_control_rationale: None,
},
CuratedPayload {
bytes: b"7*7",
label: "ssti-thymeleaf-benign",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: true,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/java_thymeleaf/benign.java",
],
oob_nonce_slot: false,
probe_predicates: &[],
benign_control: None,
no_benign_control_rationale: None,
},
];

View file

@ -0,0 +1,56 @@
//! JavaScript Handlebars `Cap::SSTI` payloads.
//!
//! Handlebars does not evaluate arbitrary arithmetic in `{{ ... }}`
//! expressions out of the box, so the vuln payload reaches the engine
//! through the built-in `lookup` helper combined with a constructor
//! gadget chain: `{{#with (lookup this 'constructor')}}{{lookup
//! this 'constructor'}}{{/with}}` is the canonical pattern, but the
//! evaluation marker we need ("rendered constant only via eval")
//! reduces to a much simpler `{{multiply 7 7}}` against the in-harness
//! `multiply` helper. The harness registers that helper before
//! compiling so the rendered body is `49`; benign control sends `7*7`
//! plain text which Handlebars echoes verbatim.
use super::super::{CuratedPayload, Oracle, PayloadProvenance, PayloadRef};
use crate::dynamic::oracle::ProbePredicate;
pub const PAYLOADS: &[CuratedPayload] = &[
CuratedPayload {
bytes: b"{{multiply 7 7}}",
label: "ssti-handlebars-eval",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: false,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/js_handlebars/vuln.js",
],
oob_nonce_slot: false,
probe_predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
benign_control: Some(PayloadRef {
label: "ssti-handlebars-benign",
}),
no_benign_control_rationale: None,
},
CuratedPayload {
bytes: b"7*7",
label: "ssti-handlebars-benign",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: true,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/js_handlebars/benign.js",
],
oob_nonce_slot: false,
probe_predicates: &[],
benign_control: None,
no_benign_control_rationale: None,
},
];

View file

@ -0,0 +1,19 @@
//! Server-Side Template Injection (`Cap::SSTI`) per-engine payload slices.
//!
//! Phase 04 (Track J.2) carves SSTI across the five most-common template
//! engines: Jinja2 (Python), ERB (Ruby), Twig (PHP), Thymeleaf (Java), and
//! Handlebars (JavaScript). Every vuln payload sends a template
//! expression that resolves to a known constant *only* when the engine
//! actually evaluates the expression (e.g. `{{7*7}}` → `49` in Jinja2,
//! `<%= 7*7 %>` → `49` in ERB). The paired benign control sends the
//! literal arithmetic text without engine markers so the per-engine
//! harness echoes the payload verbatim rather than evaluating it; the
//! oracle's [`crate::dynamic::oracle::ProbePredicate::TemplateEvalEqual`]
//! check fires on the vuln render (`49`) and does not fire on the
//! benign render (`7*7`), satisfying the §4.1 differential rule.
pub mod java_thymeleaf;
pub mod js_handlebars;
pub mod php_twig;
pub mod python_jinja2;
pub mod ruby_erb;

View file

@ -0,0 +1,50 @@
//! PHP Twig `Cap::SSTI` payloads.
//!
//! Vuln payload: `{{7*7}}` — Twig evaluates the expression and the
//! rendered template body is `49`. Benign control sends the literal
//! `7*7` text; Twig has no `{{ ... }}` markers around it and echoes
//! the payload verbatim.
use super::super::{CuratedPayload, Oracle, PayloadProvenance, PayloadRef};
use crate::dynamic::oracle::ProbePredicate;
pub const PAYLOADS: &[CuratedPayload] = &[
CuratedPayload {
bytes: b"{{7*7}}",
label: "ssti-twig-eval",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: false,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/php_twig/vuln.php",
],
oob_nonce_slot: false,
probe_predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
benign_control: Some(PayloadRef {
label: "ssti-twig-benign",
}),
no_benign_control_rationale: None,
},
CuratedPayload {
bytes: b"7*7",
label: "ssti-twig-benign",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: true,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/php_twig/benign.php",
],
oob_nonce_slot: false,
probe_predicates: &[],
benign_control: None,
no_benign_control_rationale: None,
},
];

View file

@ -0,0 +1,57 @@
//! Python Jinja2 `Cap::SSTI` payloads.
//!
//! Vuln payload: `{{7*7}}` — Jinja2 evaluates the expression and the
//! rendered template body is `49`. The harness's
//! [`crate::dynamic::oracle::ProbePredicate::TemplateEvalEqual`] check
//! compares the captured `{"render": "49"}` JSON body against
//! `expected = 49` and the oracle fires.
//!
//! Benign control: literal `7*7` — Jinja2 has no `{{ ... }}` markers to
//! evaluate so the engine echoes the payload verbatim. The rendered
//! body is `7*7`, the oracle's integer parse fails, and the oracle
//! does not fire. Together with the vuln payload this satisfies the
//! §4.1 differential confirmation rule.
use super::super::{CuratedPayload, Oracle, PayloadProvenance, PayloadRef};
use crate::dynamic::oracle::ProbePredicate;
pub const PAYLOADS: &[CuratedPayload] = &[
CuratedPayload {
bytes: b"{{7*7}}",
label: "ssti-jinja2-eval",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: false,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/python_jinja2/vuln.py",
],
oob_nonce_slot: false,
probe_predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
benign_control: Some(PayloadRef {
label: "ssti-jinja2-benign",
}),
no_benign_control_rationale: None,
},
CuratedPayload {
bytes: b"7*7",
label: "ssti-jinja2-benign",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: true,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/python_jinja2/benign.py",
],
oob_nonce_slot: false,
probe_predicates: &[],
benign_control: None,
no_benign_control_rationale: None,
},
];

View file

@ -0,0 +1,50 @@
//! Ruby ERB `Cap::SSTI` payloads.
//!
//! Vuln payload: `<%= 7*7 %>` — ERB evaluates the embedded Ruby
//! expression and the rendered template body is `49`. Benign control
//! ships the literal `7*7` text which ERB has no `<%= ... %>` marker
//! around and so passes through verbatim.
use super::super::{CuratedPayload, Oracle, PayloadProvenance, PayloadRef};
use crate::dynamic::oracle::ProbePredicate;
pub const PAYLOADS: &[CuratedPayload] = &[
CuratedPayload {
bytes: b"<%= 7*7 %>",
label: "ssti-erb-eval",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: false,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/ruby_erb/vuln.rb",
],
oob_nonce_slot: false,
probe_predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
benign_control: Some(PayloadRef {
label: "ssti-erb-benign",
}),
no_benign_control_rationale: None,
},
CuratedPayload {
bytes: b"7*7",
label: "ssti-erb-benign",
oracle: Oracle::SinkProbe {
predicates: &[ProbePredicate::TemplateEvalEqual { expected: 49 }],
},
is_benign: true,
provenance: PayloadProvenance::Curated,
since_corpus_version: 8,
deprecated_at_corpus_version: None,
fixture_paths: &[
"tests/dynamic_fixtures/ssti/ruby_erb/benign.rb",
],
oob_nonce_slot: false,
probe_predicates: &[],
benign_control: None,
no_benign_control_rationale: None,
},
];