
Proof-of-concept exploit per CVE-2025-22963, una vulnerabilità CSRF in Teedy v1.11 che consente il dirottamento dell'account tramite l'endpoint di modifica delle informazioni utente.
La vulnerabilità di cross-site request forgery (CSRF) in Teedy versioni <= v1.11 consente a un attaccante remoto di costringere un utente finale a modificare le proprie informazioni utente (nome utente, password, ecc.) nell'applicazione web in cui è attualmente autenticato.
L'endpoint per la modifica delle informazioni utente è /api/user/:username.
Questo endpoint controlla solo auth_token nei cookie per l'autorizzazione.
Il valore di auth_token può essere utilizzato da siti web di altre origini.
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
Pertanto, far visitare a un utente finale il sito web che invia richieste a /api/user/:username porta a modificare le informazioni dell'utente finale con quelle dell'attaccante remoto.
Le informazioni utente includono la password.
Ciò potrebbe portare all'acquisizione dell'account.
Questo attacco è realizzabile quando un attaccante remoto conosce il nome utente di un utente finale.
Questo attacco è sfruttabile sia contro utenti amministratori che ospiti.
In questa situazione, un attaccante può prendere il controllo dell'utente vittima impostando la password dell'utente vittima con la propria password e accedendo all'utente vittima con la propria password.
Per correggere questa vulnerabilità, allega un token CSRF quando si effettua una richiesta a /api/user/:username
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=<token generato casualmente>
Questo protegge dall'attacco CSRF perché un attaccante non conosce il valore del token CSRF.
Per utilizzare il token CSRF in modo sicuro, segui questi passaggi
Per prima cosa, crea questi file nella directory 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();
}
}
Successivamente, modifica questi file come segue.

sismics - Teedy(https://github.com/sismics/docs)
portswigger - Cross-site request forgery (CSRF)(https://portswigger.net/web-security/csrf)
Mozilla - Esempi di scenari di controllo degli accessi(https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#examples_of_access_control_scenarios)
Grazie, Ayato, per avermi insegnato come segnalare una vulnerabilità.