
Уязвимость межсайтовой подделки запроса (CSRF) в Teedy версиях <= v1.11 позволяет удалённым злоумышленникам принудить конечного пользователя изменить свои пользовательские данные (имя пользователя, пароль и т. д.) в веб-приложении, в котором он в настоящее время аутентифицирован.
Конечная точка изменения информации пользователя: /api/user/:username.
Эта конечная точка проверяет только auth_token в cookie для авторизации.
Значение auth_token может быть использовано с веб-сайтов других источников.
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
Таким образом, принуждение конечного пользователя посетить веб-сайт, который отправляет запросы к /api/user/:username, приводит к изменению информации конечного пользователя на информацию удалённого злоумышленника.
Информация пользователя включает пароль.
Это может привести к захвату учётной записи.
Эта атака возможна, когда удалённый злоумышленник знает имя пользователя конечного пользователя.
Эта атака применима как к администраторам, так и к гостевым пользователям.
В этой ситуации злоумышленник может захватить учётную запись жертвы, установив пароль жертвы на пароль злоумышленника и войдя в учётную запись жертвы с паролем злоумышленника.
Чтобы исправить эту уязвимость, прикрепите CSRF-токен при запросе к /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=<randomly generated token>
Это защищает от CSRF-атаки, поскольку злоумышленник не знает значения CSRF-токена.
Для безопасного использования CSRF-токена выполните следующие шаги
Сначала создайте эти файлы в каталоге 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();
}
}
После этого измените эти файлы следующим образом.

sismics - Teedy(https://github.com/sismics/docs)
portswigger - Межсайтовая подделка запроса(CSRF)(https://portswigger.net/web-security/csrf)
Mozilla - Примеры сценариев контроля доступа(https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#examples_of_access_control_scenarios)
Спасибо, Ayato за то, что научили меня сообщать об уязвимости.