
fork من seal-security-nuget-demo لـ .NET 7: نفس قصة استغلال CVE-2024-21907، مع إعادة الاستهداف للعملاء المقيدين بإصدار .NET SDK 7.
هذا فرع أُعيدت توجيهه من المستودع المرجعي seal-security-nuget-demo (الذي يستهدف net9.0). سيناريو الاستغلال ووحدات التحكم وقائمة الحزم المختومة متطابقة — يختلف TargetFramework فقط.
هذا الفرع موجود لأن معظم عملاء المؤسسات لا يستطيعون الانتقال إلى أحدث .NET SDK عند الطلب. وصل .NET 7 إلى نهاية الدعم في 14 مايو 2024، لكن بيئات الإنتاج الفعلية ما تزال تعمل عليه لأسباب تتعلق بالتوافق أو الشهادات أو التشغيل. وهذه هي بالضبط الحالة التي صُممت Seal Security من أجلها: عندما لا يستطيع العميل (أو لا يريد) القفز إلى إصدار رئيسي جديد، تقوم Seal بتصحيح التبعية الثغرية في مكانها تحت نفس الإصدار، دون أي تغيير في API العام ودون تعديلات على كود تطبيق العميل. يتيح هذا العرض إجراء تلك المحادثة على البنية التقنية الفعلية للعميل بدلاً من مطالبتهم بتثبيت net8/net9 أولاً.
يثبّت الفرع SDK على 7.0.x عبر global.json حتى لا تتسلل ترقيات عرضية أثناء العرض التوضيحي.
هذا التطبيق التوضيحي عبارة عن صفحة ترحيب بسيطة من ASP.NET Core تستخدم Newtonsoft.Json 12.0.2 لتحليل إدخال المستخدم ككائن إعدادات. يحتوي التطبيق على حقل اسم — اكتب اسمك وانقر Go، فيعرض "Welcome, alice!". داخلياً يمرر الإدخال عبر JsonConvert.DeserializeObject<NestedConfig>() الخاص بـ Newtonsoft.Json. هذا كل شيء — استخدام قياسي تماماً لمكتبة JSON شهيرة.
المشكلة أن Newtonsoft.Json 12.0.2 (والإصدارات قبل 13.0.1) يحتوي على CVE-2024-21907 — ثغرة رفض خدمة (Denial of Service) عالية الخطورة بنتيجة CVSS تبلغ 7.5 (عالية). يوضح هذا العرض كيف تقوم Seal Security بتصحيح الثغرة في مكانها دون الحاجة إلى ترقية إصدار رئيسي.
يمكن استغلال طريقة JsonConvert.DeserializeObject<T>() في Newtonsoft.Json عبر صياغة حمولات JSON متداخلة بعمق. عند إلغاء التسلسل إلى كائن مكتوب (POCO)، يقوم JsonSerializerInternalReader في المكتبة باستدعاءات تكرارية حقيقية (CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue → CreateValueInternal) تسبب تجاوز سعة المكدس (stack overflow)، مما يؤدي إلى تعطل التطبيق (رفض الخدمة).
يأخذ التطبيق إدخال المستخدم ويحلله عبر Newtonsoft.Json. إذا كان الإدخال رابطاً، يجلب التطبيق المحتوى أولاً — وهو نمط واقعي تستخدمه أدوات تحميل الإعدادات ومختبرو API ومستقبلات الـ webhook:
public class NestedConfig
{
[JsonProperty("n")]
public NestedConfig? N { get; set; }
}
var config = JsonConvert.DeserializeObject<NestedConfig>(name);
إدخال عادي: اكتب alice ← يعرض "Welcome, alice!"
الاستغلال: الصق هذا الرابط في حقل الاسم وانقر Go:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
يكتشف التطبيق أنه رابط، ويجلب json-payload (JSON متداخل بعمق {"n":{"n":{...}}})، ويلغي تسلسله عبر Newtonsoft.Json إلى فئة NestedConfig التكرارية — مما يؤدي إلى تجاوز سعة المكدس.
يتكرر JsonSerializerInternalReader عبر CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue لكل مستوى تداخل. عند عمق ~5,000 مستوى، يستنفد هذا مكدس الخيط ويتعطل التطبيق مع StackOverflowException — تنتهي العملية فوراً (لا يمكن معالجة الخطأ بشكل أنيق).
بهذه الثغرة، يمكن للمهاجمين:
الإصلاح المتاح علناً يتطلب الترقية إلى الإصدار 13.0.1. ومع ذلك، غالباً ما يقدم الترقية إلى إصدار رئيسي:
هذا يجعل حل "فقط قم بالترقية" مشروعاً قد يستغرق بسهولة أسابيع من وقت المطور — تاركاً الثغرة مفتوحة في هذه الأثناء.
يضيف إصدار Seal المصحح (12.0.2-sp1) حماية من عمق التكرار دون تغيير أي API عام. التصحيح:
MaxDepth افتراضية لمنع التكرار غير المحدودهذه هي نفس استراتيجية التخفيف المطبقة في Newtonsoft.Json 13.0.1، أُعيد نقلها إلى 12.0.2 كبديل متوافق تماماً (drop-in).
يتضمن هذا العرض أيضاً حزم NuGet أخرى بها ثغرات يمكن لـ Seal Security تصحيحها:
ثغرة الكيان الخارجي XML (XXE) في تحليل إعدادات XML الخاص بـ log4net. يمكن للمهاجم الذي يتحكم في ملف إعدادات log4net أن:
ملاحظة حول
System.Net.Http: العرض المرجعي على net9 يشحن أيضاً مرجعاً ثغرياًSystem.Net.Http 4.3.0لـ CVE-2017-0249. لقد حذفناه من هذا الفرع على net7 لأنSystem.Net.Httpعلى .NET 7 جزء من BCL ومرجع الحزمة المستقل هو حزمة meta-package متبقية — لها حالات حافة معروفة معdotnet add package --source <local-nupkg>، وهذا هو بالضبط كيف يطبق Seal CLI الإصدارات المختومة. حذفها يجعل خطوةseal fixموثوقة دون تغيير قصة العرض (HttpClientما زال يعمل بشكل جيد؛ فالنظام (runtime) يوفره).
توقفت ملفات Windows الثنائية من CLI بعد v0.3.238. الإصدار v0.3.238 يعمل بشكل كامل لمعالجة NuGet على Windows.
يوجد دليل تفصيلي لتثبيت وتشغيل Windows Server في README-WINDOWS-SERVER.md. يغطي قسم البدء السريع أدناه الخطوات نفسها بشكل مختصر.
PowerShell:
$env:SEAL_TOKEN = "your-seal-token-here"
$env:SEAL_PROJECT = "nuget-demo-net7"
cd seal-security-nuget-demo-net7
# Restore (pulls from nuget.org and the Seal feed — see nuget.config)
dotnet restore
# Build and run
dotnet build
dotnet run
افتح http://localhost:5000 — التطبيق يعمل بتبعيات بها ثغرات.
اكتب alice في حقل الاسم وانقر Go. يجب أن ترى: "Welcome, alice!"
الصق الرابط التالي في حقل الاسم وانقر Go:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
النتيجة قبل التصحيح: يعرض المتصفح خطأ / إعادة تعيين الاتصال — تعطل التطبيق مع StackOverflowException في JsonSerializerInternalReader.CreateValueInternal. العملية ميتة.
# (Optional — already done above) Restore dependencies first
dotnet restore
# Run Seal CLI to fix vulnerabilities
seal fix . --mode remote -v
# Restore again to pull sealed versions
dotnet restore
# Build and run the patched app
dotnet build
dotnet run
يستخدم التطبيق الآن الإصدارات المصححة (Newtonsoft.Json 12.0.2-sp1, log4net 2.0.5-sp1).
النتيجة بعد التصحيح: الصق رابط الاستغلال نفسه ← تعرض الصفحة "Blocked by Seal patch: MaxDepth of 64 has been exceeded." — حد التكرار المصحح في Newtonsoft.Json رفض الحمولة العميقة. يستمر الخادم في العمل بشكل طبيعي.
dotnet list package
يجب أن ترى حزماً باللاحقة -sp1 للإشارة إلى تصحيحات Seal Security.
يجب إضافة خطوة CLI مباشرة بعد تثبيت التبعيات ولكن قبل البناء النهائي.
# 1. Restore dependencies
dotnet restore
# 2. <--- Run Seal CLI Here
$env:SEAL_TOKEN = "your-seal-token-here"
$env:SEAL_PROJECT = "nuget-demo-net7"
seal fix . --mode remote -v
# 3. Restore again (to get sealed versions)
dotnet restore
# 4. Build
dotnet build
| الوضع | الوصف |
|---|---|
all | تطبيق جميع الإصلاحات المتاحة تلقائياً |
remote | تطبيق الإصلاحات المعتمدة فقط في واجهة Seal |
local | تطبيق الإصلاحات المعرفة فقط في .seal-actions.yml |
يسرد .seal-actions.yml في هذا المستودع بالفعل التجاوزات المختومة الثلاثة لوضع local، لذا يعمل seal fix . --mode local -v دون اتصال (ما زال يحتاج رمزاً لخادم القطع الأثرية).
تم إعداد nuget.config مسبقاً لاستخدام Seal Security مع متغيرات البيئة:
<configuration>
<packageSources>
<add key="Seal" value="https://nuget.sealsecurity.io/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<Seal>
<add key="Username" value="%SEAL_PROJECT%" />
<add key="ClearTextPassword" value="%SEAL_TOKEN%" />
</Seal>
</packageSourceCredentials>
</configuration>
| المتغير | الوصف |
|---|---|
SEAL_TOKEN | رمز الوصول الخاص بك إلى Seal Security |
SEAL_PROJECT | معرّف المشروع (مثل nuget-demo-net7) |
يحتاج Seal CLI إلى HTTPS صادر (TCP 443) إلى:
cli.sealsecurity.io — تكوين الفحص / الإصلاحauthorization.sealsecurity.io — التحقق من الرمزnuget.sealsecurity.io — تنزيل حزم .nupkg المختومةd2zko6i8myndc4.cloudfront.net — شبكة توصيل المحتوى CDN التي تقدم القطع الأثرية المختومة الفعلية (أسماء مضيفي .sealsecurity.io تعيد التوجيه هنا)api.nuget.org / نقاط نهاية nuget.org القياسية — للتبعيات غير المختومةتحقق من PowerShell بعد فتح جدار الحماية:
Test-NetConnection cli.sealsecurity.io -Port 443
Test-NetConnection authorization.sealsecurity.io -Port 443
Test-NetConnection nuget.sealsecurity.io -Port 443
Test-NetConnection d2zko6i8myndc4.cloudfront.net -Port 443
يجب أن يعرض الجميع TcpTestSucceeded: True.
12.0.2-sp1 بديل متوافق ثنائياً (binary-compatible) عن 12.0.2.الحزم المستخدمة في هذا العرض:
| الحزمة | الإصدار الثغري | الإصدار المختوم | CVE | CVSS |
|---|
حزم NuGet مختومة أخرى متاحة من خلاصة Seal (غير مستخدمة في هذا العرض، مدرجة للرجوع إليها):
رخصة MIT - راجع ملف LICENSE للتفاصيل.
| العنصر | لماذا يهم |
|---|
global.json يثبّت SDK على 7.0.x مع rollForward: latestFeature | يمنع الأجهزة التي تحتوي net8/net9 جنباً إلى جنب من تبديل SDK بصمت في منتصف العرض. |
تثبيت System.Configuration.ConfigurationManager على 7.0.0 | يستخدم العرض المرجعي على net9 الإصدار 8.0.0، الذي يستهدف net8 فقط ويفشل في الاستعادة على net7. الإصدار 7.0.0 له نفس سطح API الذي يحتاجه log4net. |
إخماد NU1701 في ملف csproj | يعلن log4net 2.0.5 عن TFM قديم net4x يقبله .NET 7 وقت التشغيل لكنه يحذر منه عند الاستعادة. التحذير تجميلي؛ الإخماد يحافظ على نظافة مخرجات البناء أثناء العرض. |
| Seal CLI v0.3.238 لنظام Windows x64 | آخر إصدار يحتوي على ملف Windows ثنائي؛ يعمل بشكل كامل لمعالجة NuGet. توقفت ملفات Windows الثنائية بعد هذا الإصدار، لذا لا تقترح إصداراً أحدث. |
| Newtonsoft.Json | 12.0.2 | 12.0.2-sp1 | CVE-2024-21907 | 7.5 HIGH |
| log4net | 2.0.5 | 2.0.5-sp1 | CVE-2018-1285 | 9.8 CRITICAL |
| الحزمة | الإصدار الثغري | الإصدار المختوم | CVE | CVSS |
|---|
| log4net | 2.0.0 | 2.0.0-sp1 | CVE-2018-1285 | 9.8 CRITICAL |
| System.Net.Http | 4.3.0 | 4.3.0-sp1 | CVE-2017-0249 | 7.3 HIGH |
| Snappier | 1.1.0 | 1.1.0-sp1 | CVE-2023-28638 | 7.0 HIGH |
| jQuery.Validation | 1.17.0 | 1.17.0-sp1 | CVE-2021-21252 | 7.5 HIGH |