T3MP3ST public launch build

This commit is contained in:
t3mp3st contributors committed 2026-07-03 10:57:20 -04:00
1 parent 972247b881
commit 184c7d4e59
1589 files changed
+57150 -506

No files matched your search

@@ -0,0 +1,30 @@
cve: CVE-2022-22965
alias: Spring4Shell — DataBinder classLoader traversal
cwe_primary: CWE-915
cwe_acceptable: [CWE-915, CWE-94, CWE-470, CWE-913, CWE-20, CWE-913, CWE-1336]
target_file: source.java
vuln_lines: [27, 28, 29, 30, 35, 36, 37, 38, 39, 40, 41]
severity: critical
vuln_class: improper_property_binding
exploit_pattern_regex: 'class\.module\.classLoader|classLoader\.resources|AccessLogValve|\.classLoader\.'
must_mention_any:
- classloader
- class loader
- introspect
- nested property
- getClass
- allowlist
- filter
- tomcat
- accesslogvalve
- jsp
points: 30
notes: |
Vulnerability: setNestedProperty traverses ANY dotted path through bean
introspection without filtering forbidden navigations like "class.module.
classLoader" — letting attacker reach Tomcat AccessLogValve and write
a JSP webshell to the server filesystem.
Hunter MUST identify:
1. Untrusted parameter name flows into bean traversal.
2. No allowlist/denylist on traversal targets (class/classLoader/module).
3. The result is arbitrary property write → RCE primitive.
@@ -0,0 +1,62 @@
// Spring DataBinder + JDK9+ property navigation — pre-CVE-2022-22965 (Spring4Shell).
// PropertyAccessor follows arbitrary nested setter chains from HTTP form params.
// "class.module.classLoader.resources.context.parent.pipeline.first.pattern"
// reaches Tomcat AccessLogValve.pattern → attacker-controlled JSP path → RCE.
package org.springframework.beans;
import javax.servlet.http.HttpServletRequest;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Map;
public final class DataBinderUnsafe {
public void bind(Object target, HttpServletRequest req) throws Exception {
Map<String, String[]> params = req.getParameterMap();
for (Map.Entry<String, String[]> e : params.entrySet()) {
String path = e.getKey(); /* attacker-controlled */
String value = e.getValue()[0]; /* attacker-controlled */
setNestedProperty(target, path, value);
}
}
/**
* BUG: traverses dotted paths through ANY introspectable getter chain
* without filtering "class"/"classLoader"/sensitive bean traversals.
* Under JDK9+ where Class.module is exposed, an attacker can navigate
* from any bean → getClass() → module → classLoader → ... → AccessLogValve
* → set pattern to an attacker-chosen log path that writes JSP.
*/
private void setNestedProperty(Object root, String dottedPath, String value) throws Exception {
String[] parts = dottedPath.split("\\.");
Object cur = root;
for (int i = 0; i < parts.length - 1; ++i) {
cur = invokeGetter(cur, parts[i]);
if (cur == null) return;
}
invokeSetter(cur, parts[parts.length - 1], value);
}
private Object invokeGetter(Object obj, String prop) throws Exception {
PropertyDescriptor[] descs = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
for (PropertyDescriptor d : descs) {
if (d.getName().equals(prop)) {
Method m = d.getReadMethod();
if (m != null) return m.invoke(obj);
}
}
return null;
}
private void invokeSetter(Object obj, String prop, String value) throws Exception {
PropertyDescriptor[] descs = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
for (PropertyDescriptor d : descs) {
if (d.getName().equals(prop)) {
Method m = d.getWriteMethod();
if (m != null) { m.invoke(obj, value); return; }
}
}
}
}