
استغلال إثبات المفهوم لـ CVE-2025-22963، وهي ثغرة CSRF في Teedy v1.11 تسمح بالاستيلاء على الحساب عبر نقطة تغيير معلومات المستخدم.
ثغرة تزوير الطلب عبر المواقع (CSRF) في إصدارات Teedy <= v1.11 تسمح للمهاجمين عن بُعد بإجبار المستخدم النهائي على تغيير معلومات المستخدم الخاصة به (اسم المستخدم، كلمة المرور، إلخ) في تطبيق الويب الذي قام بتسجيل الدخول إليه حاليًا.
نقطة تغيير معلومات المستخدم هي /api/user/:username.
تتحقق نقطة النهاية هذه فقط من auth_token في ملفات تعريف الارتباط (cookies) للتحقق من الصلاحية.
يمكن استخدام قيمة 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=<رمز تم إنشاؤه عشوائيًا>
يحمي هذا من هجوم 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 - Cross-site request forgery(CSRF)(https://portswigger.net/web-security/csrf)
Mozilla - Examples of access control scenarios(https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#examples_of_access_control_scenarios)
شكرًا لك، Ayato لتعليمي كيفية الإبلاغ عن ثغرة.