في 25 يناير، كشفت مايكروسوفت عن أ خرق أمني من قبل مجموعة إلكترونية روسية تم تحديدها باسم Midnight Blizzard (من بين أسماء أخرى)، والتي استهدفت حسابات البريد الإلكتروني في الفترة من نوفمبر 2023 إلى يناير 2024. تمكن الممثلون في البداية من الوصول عن طريق اختراق حساب مستأجر قديم غير إنتاجي لم يتم تمكين MFA (مصادقة متعددة العوامل)، ثم انتقل بعد ذلك أفقيًا إلى مستأجر الإنتاج الرئيسي لشركة Microsoft. لقد حصلوا على امتيازات عالية داخل مستأجر Exchange Online الخاص بشركة Microsoft، مما أدى إلى وصول غير مقيد إلى صناديق بريد الشركة الخاصة بهم.

في هذه المدونة، سنقدم تحليلًا تفصيليًا لسلسلة الهجوم بأكملها. سنناقش ما نعتقد أنه قد حدث مع التركيز بشكل أساسي على تقنيات هجوم OAuth المستخدمة في هذه الحملة، حيث لا تزال هناك أجزاء مهمة مفقودة من التقرير (مما يحجب الفهم الكامل لجميع التفاصيل). بالإضافة إلى ذلك، سنوفر أيضًا بعض الاستعلامات الخاصة بالاكتشافات/تعقب التهديدات المتعلقة بالمخاطر المحتملة التي تشكلها تطبيقات OAuth ونقدم بعض التوصيات العامة وأفضل الممارسات التي قد تنفذها أي مؤسسة لتقليل مخاطر التعرض للاختراق بواسطة تطبيقات OAuth الضارة وهجمات القوة الغاشمة/رش كلمة المرور.

يشير تقرير Microsoft إلى أنه بعد أن حصل الخصم على وصول مبدئي إلى حساب مستأجر الاختبار القديم من خلال اختراق مستخدم Entra ID من خلال تقنية رش كلمة المرور، فقد قام باختراق تطبيق OAuth للاختبار القديم الذي كان يتمتع بوصول مرتفع إلى بيئة شركة Microsoft.

بناءً على ذلك، يمكننا أن ندعي بثقة أن حساب Entra ID الأولي الذي تم اختراقه كان لديه امتياز إنشاء أسرار/شهادات جديدة لتطبيقات OAuth في مستأجر الاختبار، وبالتالي السماح للخصم بالمصادقة كتطبيق اختبار وتنفيذ الإجراءات نيابة عنه.

يشير عبارة “تطبيق OAuth للاختبار القديم الذي يتمتع بوصول مرتفع إلى بيئة شركة Microsoft” إلى أن تطبيق الاختبار قد تم منحه موافقة مسبقًا من قبل مستخدم Entra ID ذي الامتيازات العالية في مستأجر الشركة – مما يسمح له بامتيازات عالية في بيئة الشركة. لفهم الامتيازات التي تم منحها مسبقًا من قبل مسؤول شرعي، سنلاحظ البيان التالي: “لقد أنشأوا حساب مستخدم جديد لمنح الموافقة في بيئة شركة Microsoft”. بمعنى آخر، إما أن يكون إذن تطبيق MS Graph Directory.ReadWrite.All أو User.ReadWrite.All تم منح الموافقة مسبقًا لمستأجر الشركة، نظرًا لأن هذه هي أذونات MS Graph الوحيدة التي تسمح بإنشاء مستخدمي Entra ID الجدد. لغرض العرض التوضيحي، لنفترض أن Directory.ReadWrite.All تم منح الإذن الموافقة.

يشير التقرير لاحقًا إلى أن الخصم استخدم إذن تطبيق Office 365 Exchange Online full_access_as_app للوصول إلى صناديق بريد الشركات. نظرًا لأنه يتطلب موافقة المسؤول، يمكننا أن نستنتج أن المستخدم الذي تم إنشاؤه حديثًا في بيئة الشركة قد تم تعيينه لامتيازات المسؤول. وبالتالي، يمكننا أن نستنتج أن إذن تطبيق MS Graph RoleManagement.ReadWrite.Directory تم أيضًا منحه سابقًا حق الوصول إلى بيئة الشركة (قبل وقوع الحادث).

من مستأجر شركة Microsoft، سيبدو مدير الخدمة الذي يمثل تطبيق OAuth للاختبار القديم (في مستأجر الاختبار) بهذا الشكل، مما يشير إلى أن أذونات MS Graph الخاصة بـ Directory.ReadWrite.All و RoleManagement.ReadWrite.Directory تم منح الموافقة نيابة عن المستأجر بأكمله:

ثم أساء المهاجم بعد ذلك استخدام أذونات MS Graph المرتفعة الممنوحة مسبقًا في بيئة الشركة، وذلك باستخدام بيانات اعتماد تطبيق اختبار OAuth لإنشاء مستخدم Entra ID جديد يتمتع بامتيازات المسؤول. وقد تم ذلك في ثلاث خطوات.

الخطوة 1: أولاً، يطلب المهاجم رمز وصول يوفر الوصول إلى مستأجر الشركة بالامتيازات الممنوحة مسبقًا:

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=<clientId-of-test-app>&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=<client-secret-of-test-app>&grant_type=client_credentials' 'https://login.microsoftonline.com/<MS-Corporate-TenantID>/oauth2/v2.0/token'

الخطوة 2: باستخدام هذا الرمز، يستخدم المهاجم Directory.ReadWrite.All إذن لإنشاء مستخدم جديد في مستأجر الشركة:

الخطوة 3: ثم يستخدم المهاجم RoleManagement.ReadWrite.Directory إذن لتعيين دور المسؤول العالمي للمستخدم:

علاوة على ذلك، يشير التقرير إلى أن الخصم أنشأ أيضًا تطبيقات OAuth إضافية، على الرغم من أنه لا يشير إلى ما إذا كان تم إنشاؤها بواسطة المستخدم المخترق الأولي أو التطبيق الاختباري (سنفترض أن التطبيق الاختباري هو من أنشأها). كما أنه لا يحدد ما إذا كان قد تم إنشاؤها في مستأجر الاختبار أو مستأجر المنتج. وبالنظر إلى أن مجموعة APT التابعة للدولة معروفة بعملياتها المتطورة وقدرتها على البقاء تحت الرادار والتهرب من الكشف، فإننا نفترض أنهم لن يختاروا إنشاء تطبيقات في مستأجر المنتج، حيث يكاد يكون من المؤكد أن Microsoft تراقب بشكل صارم بيئات الإنتاج الخاصة بهم.

وهذا يعني أن التطبيق الاختباري حصل أيضًا على إذن مرتفع لتطبيق MS Graph Application.ReadWrite.All. يشير التقرير أيضًا إلى أن جهة التهديد استخدمت تطبيق OAuth للاختبار القديم لمنح تطبيقاتها الضارة الجديدة إذنًا مرتفعًا لـ Office 365 Exchange Online full_access_as_app، مما يعني أن التطبيق الاختباري حصل أيضًا على إذن MS Graph ذي الامتيازات العالية لـ AppRoleAssignment.ReadWrite.All.

بشكل عام، قد يكون لتطبيق OAuth الاختباري القديم في مستأجر الاختبار أذونات MS Graph التالية:

  • Directory.ReadWrite.All: إذن MS Graph الذي تم منحه مسبقًا في مستأجر شركة Microsoft – مما يسمح للخصوم بإنشاء مستخدم جديد في مستأجر الشركة.

  • RoleManagement.ReadWrite.Directory: إذن MS Graph الذي تم منحه مسبقًا في مستأجر شركة Microsoft – مما يسمح للخصوم بتعيين أي أدوار دليل للمستخدم الجديد.

  • Application.ReadWrite.All: إذن MS Graph الذي يسمح لتطبيق OAuth بإنشاء تطبيقات OAuth جديدة. سمح هذا الإذن للمهاجم بإنشاء تطبيق OAuth الضار الجديد.

  • AppRoleAssignment.ReadWrite.All: إذن MS Graph الذي يسمح لتطبيق OAuth بتعيين أذونات جديدة للتطبيقات الموجودة. سمح هذا الإذن للمهاجم بتعيين full_access_as_app إذن لتطبيقاتهم الضارة.

الإجراء الخاص بإنشاء تطبيق OAuth جديد قد يكون ضارًا وتعيين إذن Office 365 Exchange Online له full_access_as_app عبر تطبيق OAuth الاختباري القديم، قد يتم المتابعة على النحو التالي:

az ad app create --display-name malicious-mail-access --sign-in-audience AzureADMultipleOrgs --web-redirect-uris https://google.com

az ad app permission add --id fe588533-bb17-4026-bbc3-af8513399c67 --api 00000002-0000-0ff1-ce00-000000000000 --api-permissions dc890d15-9560-4a4c-9b7f-a736ec74ec40=Role

وبعد ذلك الجديد الوصول الخبيث للبريد الإلكتروني يتم إنشاء تطبيق OAuth في مستأجر الاختبار وقد يبدو بالشكل التالي:

سيحتاج الخصوم بعد ذلك إلى إنشاء بيانات اعتماد تطبيق OAuth الضارة الجديدة (ربما باستخدام نفس حساب المستخدم الذي تم اختراقه في البداية عبر هجوم رش كلمة المرور)، ثم بدء هجوم موافقة غير مشروعة حيث يوافقون على إذن Office 365 Exchange Online لـ full_access_as_app باستخدام المستخدم الإداري الجديد الخاص بهم في مستأجر شركة Microsoft، مما يسمح لاحقًا بالوصول غير المقيد إلى أي صندوق بريد مرتبط بالمستخدمين في مستأجر الشركة. يمكن أن يكون هذا الإجراء لهذه العملية كما يلي:

يقوم الخصوم بتسجيل الدخول إلى تطبيقهم الضار متعدد المستأجرين باستخدام المستخدم الإداري الجديد الخاص بهم في مستأجر شركة Microsoft.

بعد ذلك، يستخدمون الامتيازات الإدارية للمستخدم لمنح الموافقة على تطبيقهم الضار، والذي يهدف إلى الحصول على حق الوصول الكامل إلى جميع صناديق بريد الشركة.

أخيرًا، عند الحصول على الموافقة، لن يحتاج المهاجمون إلا إلى طلب رمز وصول باستخدام بيانات الاعتماد الخاصة بهم الوصول الخبيث للبريد الإلكتروني تطبيق OAuth (الاسم الذي اخترناه لغرض هذا العرض التوضيحي) للوصول إلى أي صندوق بريد داخل مستأجر الشركة:

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=<clientId-of-malicious-mail-access-app>&scope=https%3A%2F%2Foutlook.office365.com%2F.default&client_secret=<client-secret-of-malicious-mail-access-app>&grant_type=client_credentials' 'https://login.microsoftonline.com/<MS-Corporate-TenantID>/oauth2/v2.0/token'

فيما يلي بعض استعلامات الكشف/البحث المتعلقة بالنشاط الشاذ المرتبط بتطبيقات Entra ID OAuth، باستخدام سجلات تدقيق Entra ID (AAD) في تحليلات Azure Log.

1. اكتشف تعيينات الأذونات ذات الامتيازات العالية لتطبيقات OAuth:

AuditLogs 
| where OperationName == "Update application" and Result == "success" 
| extend userPrincipalName = tostring(parse_json(InitiatedBy).user.userPrincipalName), userId = tostring(parse_json(InitiatedBy).user.id) 
| extend appName = tostring(parse_json(InitiatedBy).app.displayName), spId = tostring(parse_json(InitiatedBy).app.servicePrincipalId) 
| mv-expand TargetResources 
| extend targetAppId = tostring(parse_json(TargetResources).id), targetAppName = tostring(parse_json(TargetResources).displayName) 
| extend modifiedProps = parse_json(TargetResources).modifiedProperties 
| mv-expand modifiedProps 
| extend newValue = parse_json(tostring(modifiedProps.newValue)) 
| mv-expand newValue 
| extend requiredAppPermissions = parse_json(tostring(newValue.RequiredAppPermissions)) 
| mv-expand requiredAppPermissions 
| extend  EntitlementId = tostring(requiredAppPermissions.EntitlementId) 
| where EntitlementId in 
("1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9", //Application.ReadWrite.All 
 "06b708a9-e830-4db3-a914-8e69da51d44f", //AppRoleAssignment.ReadWrite.All 
 "19dbc75e-c2e2-444c-a770-ec69d8559fc7", //Directory.ReadWrite.All 
 "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8", //RoleManagement.ReadWrite.Directory 
 "dc890d15-9560-4a4c-9b7f-a736ec74ec40"  //full_access_as_app 
 ) 
| extend initiatingPrincipalName = iff(userPrincipalName != "", userPrincipalName, appName) 
| extend initiatingPrincipalId = iff(userId != "", userId, spId) 
| summarize make_set(EntitlementId) by initiatingPrincipalId, initiatingPrincipalName, targetAppId, targetAppName 

سيكشف هذا الاستعلام عن تعيين أذونات التطبيق من النوع المذكور في هذه المدونة. إذا كنت مهتمًا بتغطية أذونات MS Graph الإضافية، فارجع إلى وثائق Microsoft الرسمية.

2. اكتشف تعيينات أدوار الدليل ذات الامتيازات العالية لمستخدمي Entra ID، وتحديدًا الأدوار المضمنة للمسؤول العالمي ومسؤول الدور المميز ومسؤول التطبيق ومسؤول التطبيق السحابي التي يمكنها منح موافقة المسؤول على مستوى المستأجر لتطبيقات OAuth:

AuditLogs 
| where OperationName == "Add member to role" and Result == "success" 
| extend initiatedByUserName = tostring(parse_json(InitiatedBy).user.userPrincipalName), initiatedByUserId = tostring(parse_json(InitiatedBy).user.id) 
| extend initiatedByAppName = tostring(parse_json(InitiatedBy).app.displayName), initiatedByAppId = tostring(parse_json(InitiatedBy).app.servicePrincipalId) 
| mv-expand TargetResources 
| extend targetUserId = tostring(parse_json(TargetResources).id), targetUserName = tostring(parse_json(TargetResources).userPrincipalName) 
| extend modifiedProperties = parse_json(TargetResources).modifiedProperties 
| mv-expand modifiedProperties 
| extend displayName = tostring(parse_json(modifiedProperties).displayName), newValue = tostring(parse_json(modifiedProperties).newValue) 
| where displayName == "Role.DisplayName" 
| extend assignedRole = trim('"',newValue) 
| where assignedRole in ("Global Administrator","Privileged Role Administrator","Application Administrator","Cloud Application Administrator") 
| extend initiatingPrincipalName = iff(initiatedByUserName != "", initiatedByUserName, initiatedByAppName) 
| extend initiatingPrincipalId = iff(initiatedByUserId != "", initiatedByUserId, initiatedByAppId) 
| summarize initiatedByPrincipalsNames = make_set(initiatingPrincipalName),  
  initiatedByPrincipalsIds = make_set(initiatingPrincipalId), 
  assignedRoles = make_set(assignedRole) by targetUserId, targetUserName

3. كشف الأسرار/الشهادات التي تم إنشاؤها لتطبيقات OAuth المتعددة بواسطة مدير معين في فترة زمنية قصيرة:

AuditLogs 
//| where TimeGenerated between ( .. ) or TimeGenerated > ago(3h) 
| where OperationName == "Update application – Certificates and secrets management " and Result == "success" 
| extend userPrincipalName = tostring(parse_json(InitiatedBy).user.userPrincipalName), userId = tostring(parse_json(InitiatedBy).user.id) 
| extend appName = tostring(parse_json(InitiatedBy).app.displayName), spId = tostring(parse_json(InitiatedBy).app.servicePrincipalId) 
| mv-expand TargetResources 
| extend targetAppId = tostring(parse_json(TargetResources).id), targetAppName = tostring(parse_json(TargetResources).displayName) 
| extend initiatingPrincipalName = iff(userPrincipalName != "", userPrincipalName, appName) 
| extend initiatingPrincipalId = iff(userId != "", userId, spId) 
| summarize distinctApps = dcount(targetAppId), make_set(targetAppName) by initiatingPrincipalId, initiatingPrincipalName 
| where distinctApps > 2 //modify TH to your requirements 

تأكد من تحديد الإطار الزمني والعتبة وفقًا لمتطلباتك.

4. اكتشف متى تمت الموافقة على تطبيق جهة خارجية جديد في المستأجر الخاص بك:

let addedSP = AuditLogs 
| where OperationName == "Add service principal" and Result == "success" 
| mv-expand AdditionalDetails 
| extend detailKey = tostring(parse_json(AdditionalDetails).key) 
| extend detailValue = tostring(parse_json(AdditionalDetails).value) 
| where detailKey == "AppId" 
| extend appId = detailValue; 
let consentApp = AuditLogs 
| where OperationName == "Consent to application" and Result == "success" 
| extend UserConsentedRequest = tostring(parse_json(InitiatedBy).user.userPrincipalName), UserId = tostring(parse_json(InitiatedBy).user.id) 
| mv-expand AdditionalDetails 
| extend detailKey = tostring(parse_json(AdditionalDetails).key) 
| extend detailValue = tostring(parse_json(AdditionalDetails).value) 
| mv-expand TargetResources 
| extend appName = tostring(parse_json(TargetResources).displayName) 
| where detailKey == "AppId" 
| extend appId = detailValue; 
addedSP 
| join kind=inner consentApp on appId 
| where TimeGenerated >= TimeGenerated1 //if service principal was added AFTER a consent was granted to it then it's probably owned by an external tenant 
| project TimeGenerated1, UserConsentedRequest, UserId, appId, appName 

تأكد من مراقبة مبادئ الخدمة الجديدة التي تتم إضافتها إلى المستأجر الخاص بك نتيجة للموافقة على تطبيق OAuth لجهة خارجية. إذا وجدت أي مدير خدمة مشبوه جديد، فتحقق من الأذونات المعتمدة وحدد ما إذا كان هذا تطبيقًا شرعيًا يمكنه الوصول إلى بيانات مؤسستك.

قم بفرض MFA على مستأجر معرف Entra الخاص بك

كان من الممكن منع هذا النوع من الهجمات إذا كانت هناك ضوابط أمنية صارمة، مثل وجود MFA على كل مستخدم معرف Entra في المستأجر.

تأكد من تطبيق سياسة تسجيل مصادقة MFA في المستأجر الخاص بك عن طريق المتابعة هذه الخطوات.

تمكين القفل الذكي

يدافع Azure AD Smart Lockout عن هجمات القوة الغاشمة أو رش كلمة المرور عن طريق قفل المهاجمين مع ضمان إمكانية وصول المستخدمين الشرعيين إلى حساباتهم. فهو يفرق بين عمليات تسجيل الدخول المشروعة المحتملة ومحاولات المهاجم، ويحدد حدودًا ومددًا لعمليات إغلاق الحساب لتحقيق التوازن بين الأمان وإمكانية الوصول. لفرض ذلك على المستأجر الخاص بك، اتبع هذه الخطوات.

منع هجمات الموافقة على التطبيقات غير المشروعة

افتراضيًا، يمكن لجميع المستخدمين منح الموافقة للتطبيقات التي لا تتطلب مراجعة إدارية. لتقليل مخاطر التطبيقات الضارة التي تحاول خداع المستخدمين لمنحهم حق الوصول إلى بيانات مؤسستك، نوصي بشدة بتقييد المستخدمين من الموافقة على تطبيقات الجهات الخارجية التي لم يتم التحقق منها. لتكوين إعدادات موافقة المستخدم، اتبع هذه الخطوات وتأكد من تحديد الخيار الثاني (السماح بموافقة المستخدم على التطبيقات من الناشرين الذين تم التحقق منهم):

يقدم Wiz حلاً شاملاً لاكتشاف الهجمات المماثلة ومنعها.

كشف

يمكن لعملاء Wiz استخدام Wiz CDR (اكتشاف السحابة والاستجابة لها) لاكتشاف التهديدات السحابية الناشئة في الوقت الفعلي، مثل السيناريوهات التالية:

  1. اكتشف هجوم القوة الغاشمة الناجح على حساب مستخدم Entra ID محدد.

  2. اكتشف العديد من حسابات مستخدم Entra ID الصالحة التي فشلت في المصادقة من نفس عنوان IP (يرتبط عادةً بهجمات رش كلمة المرور).

  3. اكتشاف إنشاء بيانات اعتماد جديدة لتطبيقات OAuth المتعددة بواسطة مبدأ معرف Entra محدد في فترة زمنية قصيرة.

  4. اكتشف موافقة المشرف غير المشروعة المحتملة على تطبيق جهة خارجية يطلب أذونات ذات امتيازات عالية.

وقاية

يمكن لعملاء Wiz استخدام Wiz لتقييم المخاطر في بيئتهم واكتشاف المجموعات السامة والخطرة ذات الصلة، على غرار تلك التي تم استغلالها في الهجوم الموصوف أعلاه:

  1. اكتشف ما إذا كان لديك أساسيات خدمة الطرف الثالث ذات الامتيازات العالية في المستأجر الخاص بك والتي تم منحها الموافقة مسبقًا.

  2. تتبع جميع مستخدمي Entra ID ذوي الامتيازات العالية الذين لم يتم تمكين MFA لديهم.

تضمن هجوم Midnight Blizzard أسلوبًا متطورًا ومتعدد الطبقات. إنه بمثابة تذكير صارخ بأهمية التدابير الأمنية القوية للمؤسسات التي تمارس الأعمال التجارية في السحابة. يمكن لعملاء Wiz استخدام ويز مجلس الإنماء والإعمار للحصول على معلومات الكشف عن التهديدات ذات الصلة والمدمجة الضوابط لتحديد المخاطر ذات الصلة في بيئاتهم. إذا كانت لديك أية أسئلة أو مساعدة في تصحيح الثغرات الأمنية أو التخفيف منها، فلا تتردد في الاتصال بنا على التهديد.hunters@wiz.io.

نود أن نشكر Matt Graeber وJustin Schoenfeld من Red Canary على التواصل ولفت انتباهنا إلى أن خطوة الهجوم النهائية تتطلب أوفيس 365 أوتلوك مواصفات النطاق لاسترداد الرمز المميز لدور التطبيق ذي الصلة.

شاركها.
اترك تعليقاً