قائمة تحقّق للحدّ الأدنى من الأمان في تطوير تطبيقات Windows
تنزيل قائمة التحقّق بصيغة Excel
عندما يقال «أمان تطبيقات Windows»، يقفز الحديث في الغالب مباشرةً إلى المواضيع الكبرى.
Zero trust وEDR وSBOM وعمليّات الشهادات وإدارة الثغرات. كلّ ذلك مهمّ، لكن في التسليم اليوميّ توجد أوّلاً مشكلة أبسط: أساسيّات لا ينبغي تركها مرخيّة.
ذلك صحيح بصورة خاصّة في تطبيقات مثل هذه:
- تطبيقات سطح المكتب من نوع WPF أو WinForms أو WinUI
- تطبيقات Win32 المكتوبة بـ C++ أو C#
- أدوات داخليّة تتّصل بأجهزة أو ملفّات أو قواعد بيانات
- تطبيقات الأعمال ذات السلوك التحديثيّ التلقائيّ
- الحلول التي تتضمّن Windows Services أو ملفّات تنفيذيّة مساعدة
في مثل هذه البرمجيّات، فإنّ إصلاح الأساسيّات الواضحة يُحدث في الغالب فرقاً أكبر من الانكباب المبكر على دفاعات متقدّمة.
يُنظّم هذا المقال خطّ الأساس الأمنيّ الأدنى في صورة قائمة تحقّق يسهل مراجعتها عبر التصميم والتنفيذ والتوزيع والتشغيل.
1. الخلاصة المختصرة
- أوّل ما يستحقّ الحماية ليس سوى عدم طلب صلاحيّات مسؤول غير ضروريّة، وتوقيع ما تشحنه، وعدم إبقاء الأسرار بنصّ صريح، وعدم تعطيل التحقّق من الشهادات في الإنتاج.
- في برمجيّات Windows، فإنّ القابل للتوزيع نفسه جزء من سطح الهجوم. ذلك يشمل ملفّات EXE والـ DLL وحزم MSI أو MSIX ومكوّنات المحدِّث.
- أنماط من قبيل
ServerCertificateValidationCallback => true، وسلاسل الاتّصال بنصّ صريح، والاستخدام المتراخي لـLoadLibrary("foo.dll")، وSQL المبنيّ بتسلسل السلاسل، ينبغي أن تُعدّ سلفاً تحت خطّ الحدّ الأدنى. - إن كان جزء فقط من النظام يحتاج إلى رفع الصلاحيّات، فقسّم ذلك الجزء إلى عمليّة أو خدمة منفصلة بدلاً من رفع صلاحيّات التطبيق بأكمله.
- في توزيع Windows، يجب أن يُعامَل التوقيع مع timestamping على أنّه الإعداد الافتراضيّ، لا لمسة جماليّة. فهو يُحسّن الثقة، وكشف العبث، والوضوح التشغيليّ.
- بالنسبة للأسرار المخزَّنة، اختَر شيئاً مثل DPAPI / ProtectedData أو Credential Locker بناءً على نموذج التطبيق. على الأقل، تجاوَز مرحلة «اتركه في
appsettings.jsonبنصّ صريح». - الـ logging ليس جيّداً تلقائياً لمجرّد أنّ هناك مزيداً منه. إن احتفظت السجلّات بـ tokens أو كلمات مرور أو سلاسل اتّصال أو بيانات شخصيّة أو أجسام طلبات كاملة، فقد تصبح السجلّات نفسها هي الحادثة.
خطّ الحدّ الأدنى ليس مرتبطاً بإضافة ميزات أمان خاصّة بقدر ما هو مرتبط بـ عدم شحن إعدادات افتراضيّة خطرة أو خيارات تنفيذيّة متراخية.
2. ماذا يعني هذا المقال بـ «الحدّ الأدنى»
2.1. ما يدخل في النطاق
يستهدف هذا المقال تطبيقات Windows مثل:
- تطبيقات سطح المكتب من WPF أو WinForms أو WinUI
- تطبيقات Win32 المكتوبة بـ C++ أو C#
- أدوات التوزيع الداخليّ، وأدوات المراقبة، وأدوات تكامل الأجهزة
- المنتجات التي تتضمّن EXE مساعدة وWindows Services ومحدِّثات
- برامج الأعمال الموزَّعة بصيغة EXE أو MSI أو MSIX
هنا، «الحدّ الأدنى» لا يعني «ما يكفي لإرضاء كلّ تدقيق».
بل يعني خطّ الأساس الذي يؤدّي تركه برخاوة عادةً إلى حوادث اعتياديّة جدّاً، يمكن تجنّبها جدّاً.
2.2. ما يخرج عن النطاق
ليس هذا المقال أساساً عن:
- تصميم zero trust على مستوى المنظّمة بأكملها
- تشغيل EDR وSIEM وDLP وMDM بشكل كامل
- التحصين العميق لـ kernel drivers
- بناء أنظمة تشفير من الصفر
- إجراءات صيد التهديدات أو تحقيقات الـ forensics المتقدّمة
التركيز أضيق: الخطّ الأساسيّ الذي ينبغي ألّا يفوته مطوّرو تطبيقات Windows قبل الإصدار.
3. أوّل قائمة تحقّق ينبغي النظر إليها
قبل الدخول في التفاصيل، يساعد النظر أوّلاً إلى الشكل الكلّي.
3.1. النظرة العامّة
| المجال المطلوب فحصه | الإجراء الأدنى | النمط السيّئ المعتاد |
|---|---|---|
| صلاحيّات التنفيذ | اجعل asInvoker افتراضاً، واعزل العمليّات المرفوعة الصلاحيّات |
ضبط التطبيق بأكمله على requireAdministrator |
| الثقة في التوزيع | وقِّع ملفّات EXE والـ DLL وحزم MSI وMSIX، وأرفق timestamps | شحن binaries غير موقَّعة |
| التحديث | ثبِّت مصدر التحديث، وتحقّق من السلامة عبر HTTPS مع توقيع أو فحص hash | التنزيل عبر HTTP والكتابة فوق الملفّات مباشرةً |
| الأسرار | أبقِ الأسرار خارج الكود المصدريّ والإعدادات بنصّ صريح، واستخدم DPAPI أو Credential Locker عند الحاجة | تخزين مفاتيح API أو سلاسل اتّصال في الإعدادات بنصّ صريح |
| أمان النقل | استخدم HTTPS وأبقِ التحقّق من الشهادات مفعَّلاً | تخطّي فحوص الشهادات بـ return true دائماً |
| المدخلات الخارجيّة | تحقّق من مدخلات SQL والملفّات والـ IPC والـ URI والـ CSV والـ JSON ومصادر مماثلة | الوثوق بالمدخلات لأنّها «أداة داخليّة فقط» |
| تحميل الـ DLL | استخدم مسارات صريحة وترتيب بحث آمناً مثل SetDefaultDllDirectories |
الاعتماد على حلّ DLL من المجلّد الحاليّ |
| الـ logging | أخفِ الـ tokens وكلمات المرور وPII، وافصل أخطاء الواجهة عن التفاصيل الداخليّة | حفظ تفاصيل الاستثناءات والأسرار كما هي |
| نظافة التبعيّات | حدّث SDKs وحزم NuGet ومكوّنات VC++ runtime وتبعيّات OSS باستمرار | تجميد التبعيّات سنوات وتجاهل التحذيرات |
3.2. اجعل asInvoker هو الإعداد الافتراضيّ
غالباً ما يكون هذا أوّل موضع يستحقّ المراجعة.
إن كان التطبيق بأكمله يعمل بصلاحيّات مرفوعة، فإنّ الأخطاء البرمجيّة، وحلّ الـ DLL السيّئ، وأخطاء الإعدادات، والمدخلات غير الموثوقة، تعمل أيضاً بصلاحيّات أقوى.
النمط الأساسيّ مباشر:
- أبقِ تطبيقات الواجهة العاديّة على
asInvoker - اعزل فقط العمليّات التي تحتاج فعلاً إلى صلاحيّات إداريّة
- ارفع الصلاحيّات فقط عندما تكون تلك العمليّة المحدّدة مطلوبة
- تحقّق أيضاً من المدخلات التي تذهب إلى EXE المساعدة أو الخدمات
إن كان التطبيق يقرأ ويعدّل البيانات في معظم الأحيان، لكنّ التثبيت أو تغييرات جدار الحماية فقط هي التي تحتاج إلى رفع الصلاحيّات، فمن الأكثر أماناً عادةً إبقاء عمليّة الواجهة بدون امتيازات ونقل العمليّة المتمتّعة بالامتيازات وحدها إلى عمليّة broker أو خدمة.
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
«التشغيل كمسؤول أسهل» يبدو ملائماً في البداية فقط.
بمرور الوقت، يعطي تصميم الحدّ الأدنى من الامتيازات نطاق انفجار أصغر دائماً تقريباً.
3.3. وقِّع الـ binaries والـ installer
في برمجيّات Windows، فإنّ الثقة في التوزيع تهمّ كثيراً.
يتفاعل المستخدمون مع EXEs وDLLs وحزم MSI وحزم MSIX وحدات المحدِّث، لا مع مستودع المصدر لديك. إن كانت تلك المنتجات غير موقَّعة، فإنّ كلّاً من كشف العبث والثقة التشغيليّة يصبحان أضعف.
قائمة التحقّق الأساسيّة هي:
- وقِّع EXEs وDLLs وحزم MSI وحزم MSIX
- وقّع الـ binaries المساعدة المستخدمة في التحديث، لا الـ installer الرئيسيّ فقط
- أضف timestamps
- ضمِّن إجراء تجديد الشهادات في سير عمل الإصدار
التوقيع بدون timestamp يصبح مزعجاً ما إن تنتهي صلاحيّة الشهادة.
من الأكثر استقراراً معاملة التوقيع مع timestamping كجزء من عمليّة الإصدار.
إن كنت تشحن MSIX، فتوقيع الحزم متوقَّع سلفاً.
وحتّى مع توزيع MSI أو EXE، فإنّ توقيع الـ installer والـ executables الجوهريّة على الأقلّ هو حدّ أدنى معقول.
3.4. اضبط مسار التحديث وتحقّق من الأصالة
في تطبيقات Windows الحديثة، غالباً ما يعيش مسار التحديث أطول من مسار التثبيت الأوّل.
إن كانت معالجة التحديث ضعيفة، فقد يصبح المحدِّث أضعف جزء في المنتج حتّى لو بُني التطبيق الرئيسيّ بعناية.
خطّ الحدّ الأدنى هو:
- جلب أحمال التحديث عبر HTTPS
- التحقّق من المحتوى المنزَّل عبر فحص توقيع أو hash
- تجنّب جعل URL مصدر التحديث قابلاً للاستبدال بشكل اعتباطيّ
- توقيع المحدِّث نفسه
- تعريف سلوك الاسترجاع أو الاسترداد عند الإخفاقات
إن كان MSIX مع App Installer يلائم نموذج توزيعك، فإنّه يستطيع تحويل مزيد من آليّة التحديث نحو نظام التشغيل.
إن كنت تحتفظ بمحدِّث مخصّص، فعليك الاهتمام بكلّ من أمان النقل وأصالة المنتج. الـ HTTPS يحمي القناة، لكنّه لا يحمي بنفسه دعوى أنّ الملف جاء حقّاً منك.
3.5. لا تبقِ الأسرار في الكود المصدريّ أو الإعدادات بنصّ صريح
هذه إحدى أكثر نقاط الإخفاق شيوعاً في الواقع العمليّ.
لأنّ الأداة داخليّة، أو لأنّها «مجرّد EXE»، تترك الفرق غالباً سلاسل اتّصال ومفاتيح API واعتمادات مجلّدات مشتركة وtokens ثابتة مباشرةً في الكود أو الإعدادات.
الأمور التي تستحقّ الإزالة أوّلاً هي:
- مفاتيح API مكتوبة مباشرةً في المصدر
- كلمات مرور بنصّ صريح في
appsettings.jsonأوapp.config - سلاسل اتّصال مودَعة في المستودع
- تصاميم تخزّن النصّ المشفَّر ومفتاح فكّ التشفير معاً
- اعتماد مشترك واحد يستخدمه كلّ مستخدم
بالنسبة لتطبيقات Windows، تبدو الخيارات العمليّة عادةً هكذا:
- تحتاج إلى تخزين اعتمادات على جانب Windows
للتطبيقات المُحزَّمة لسطح المكتب أو WinUI، فكِّر في Credential Locker. - تحتاج إلى تخزين محلّي مشفَّر
لبرمجيّات Win32 أو .NET، يكون DPAPI /ProtectedDataغالباً هو الافتراض العمليّ. - النظام المستهدف يدعم مصادقة Windows المتكاملة
يفضَّل عدم تخزين كلمات المرور في العميل أصلاً. - يمكن إدارة الأسرار على جانب الخادم
تجنّب تضمين أسرار طويلة الأمد في العميل.
في C#، حتّى المنهج البسيط القائم على DPAPI أفضل بكثير سلفاً من النصّ الصريح:
using System.Security.Cryptography;
using System.Text;
byte[] plaintext = Encoding.UTF8.GetBytes(secretText);
byte[] ciphertext = ProtectedData.Protect(
plaintext,
optionalEntropy: null,
scope: DataProtectionScope.CurrentUser);
السؤال التصميميّ المهمّ ليس فقط «هل هو مشفَّر؟» بل مَن يستطيع فكّ تشفيره؟
CurrentUser وLocalMachine يعنيان حدوداً مختلفة جدّاً.
بالنسبة لاتّصالات SQL Server في بيئات on-premises، يمكن أن تكون مصادقة Windows غالباً الخيار الأوّل المطروح للنظر.
إن كان لا بدّ أن تظهر الاعتمادات في سلسلة اتّصال، فعلى الأقل تجنّب تركها في الإعدادات بنصّ صريح، وأبقِ في ذهنك إعدادات مثل Persist Security Info=False.
3.6. استخدم HTTPS ولا تقتل التحقّق من الشهادات
أحد أقدم الأنماط في تسليم التطبيقات أنّ اختصاراً تطويريّاً مؤقّتاً ينجو بهدوء حتّى الإنتاج.
كود أمان النقل مليء بهذا.
تشمل الأنماط الخطرة الشائعة:
ServicePointManager.ServerCertificateValidationCallback += ... => trueHttpClientHandler.DangerousAcceptAnyServerCertificateValidator- الشحن مع تعطيل فحوص الإلغاء
- ترك افتراضات شهادات موقَّعة ذاتيّاً للتطوير في كود الإنتاج
القاعدة الأساسيّة بسيطة:
- حركة الإنتاج تستخدم HTTPS
- لا يُتخطّى التحقّق من الشهادات على المستوى الكلّي
- إن كان التخفيف الاستثنائيّ مطلوباً، فحدّد نطاقه بإحكام للمضيف والشهادة المتوقَّعَين تحديداً
- يجب استبعاد كود تجاوز التطوير بشكل موثوق عبر البناء أو الإعدادات
- في .NET، فكِّر أيضاً في فحوص الإلغاء
المثال السيّئ الكلاسيكيّ يبدو هكذا:
ServicePointManager.ServerCertificateValidationCallback +=
(_, _, _, _) => true;
يبدو ذلك ملائماً، لكنّه قريب من القول: «اقبل اتّصال HTTPS هذا أيّاً يكن من يردّ».
بمجرّد إزالة التحقّق من الشهادات، تضعف قيمة HTTPS بشدّة.
3.7. عامل كلّ مدخل خارجيّ كمدخل غير موثوق
تطبيقات Windows ليست تطبيقات ويب، لذا فإنّ التحقّق من المدخلات يُعامَل أحياناً بمزيد من التراخي.
لكن في الواقع، تمتلك برمجيّات Windows أسطح مدخلات كثيرة:
- مسارات الملفّات
- CSV وExcel وJSON وXML
- وسائط سطر الأوامر
- named pipes والـ sockets والـ COM والـ RPC والـ gRPC
- السلاسل المرسَلة إلى قاعدة البيانات
- قيم الـ registry
- محتوى الـ clipboard
- URLs وdeep links
- البيانات المُعادة من الأجهزة أو SDKs الطرف الثالث
ثلاث قواعد أساسيّة تهمّ كثيراً وبصورة خاصّة:
- اضبط بارامترات SQL دائماً
لا تبنِ SQL بتسلسل السلاسل. - طبِّع المسارات قبل استخدامها
لا تحذف ولا تكتب فوق ولا تستخرج مباشرةً من مسارات يقدّمها المستخدم خاماً. - طبّق حدود الحجم وفحوص التنسيق على الملفّات الخارجيّة
«فُتح بنجاح» ليس مساوياً لـ «هو آمن».
هذا هو نوع SQL الذي تريد تجنّبه:
var sql = "SELECT * FROM Users WHERE Name = '" + userName + "'";
حتّى الصيغة الأكثر أماناً بحدّها الأدنى ينبغي أن تبدو أكثر هكذا:
using System.Data;
using Microsoft.Data.SqlClient;
using var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM Users WHERE Name = @name";
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 256).Value = userName;
«إنّها مجرّد أداة داخليّة، ولذا فالمدخل موثوق» يبقى افتراضاً محفوفاً بالمخاطر.
ملفّات CSV التالفة، وأسماء ملفّات غير متوقَّعة، وصفوف قواعد بيانات قديمة، وأخطاء المشغّلين، وJSON مكتوب جزئيّاً من أداة أخرى، كلّها أمور طبيعيّة جدّاً في الميدان.
3.8. اجعل تحميل الـ DLL صريحاً
هذه عثرة بشكل Windows جدّاً.
إن استدعيت LoadLibrary("foo.dll") بمجرّد اسم الملفّ، فقد يدفع ترتيب البحث العمليّةَ إلى التقاط DLL من مكان لم تقصده.
خطّ الأساس الأكثر أماناً هو:
- استخدم مساراً مطلقاً للـ DLL عند الإمكان
- استدعِ
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)مبكراً - أضِف فقط مجلّدات بحث صريحة عبر
AddDllDirectory - تجنّب التصاميم التي تغذّي نتائج
SearchPathمباشرةً إلىLoadLibrary - لا تعتمد كلّياً على افتراضات وضع البحث الآمن للـ DLL
في الكود الـ native، يكون نمط كهذا في وقت مبكّر من تهيئة العمليّة غالباً نقطة بداية قويّة:
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
ثم أضِف فقط المجلّدات التي تحتاج إليها فعلاً عبر AddDllDirectory.
يُهمَل هذا المجال بسهولة لأنّه «يعمل عادةً»، لكنّه قد ينهار بهدوء عندما يتغيّر المجلّد العامل أو يُسقِط منتج آخر DLLs في PATH.
يحسّن ذلك ليس الأمان فحسب، بل الموثوقيّة أيضاً.
3.9. أبقِ الأسرار خارج السجلّات وعروض الاستثناءات
يساعد المزيد من الـ logging في تتبّع المشاكل، لكنّ السجلّات يمكن أن تصبح أيضاً المكان الذي تتراكم فيه البيانات الحسّاسة.
نقاط المراجعة الدنيا هي:
- لا تسجّل كلمات المرور أو bearer tokens أو مفاتيح API
- لا تُفرغ سلاسل الاتّصال كاملة
- أخفِ أجسام البيانات الشخصيّة أو التجاريّة
- افصل التشخيصات الداخليّة عن رسائل الخطأ المعروضة للمستخدم
- لا تترك تسجيل PII الخاصّ بالـ debug مفعَّلاً في الإنتاج
- راجع حقوق الوصول إلى تخزين الـ dumps والـ traces والـ logs
تجعل أدوات .NET الحديثة الإخفاء البنيويّ أسهل أيضاً، لكن حتّى بدون ذلك، فإنّ التغيير الأدنى هو التوقّف عن تحويل كلّ كائن إلى سلسلة وتسجيلها كما هي.
تشمل الأنماط السيّئة الشائعة:
- تخزين أجسام طلبات HTTP أو الردود كاملة
- إفراغ الترويسات أو الـ tokens كاملة عند فشل المصادقة
- إظهار رسائل استثناءات خام في
MessageBox - حشر كلّ سجلّ حسّاس في ZIP صيانة
التقسيم الأفضل يبدو هكذا:
- المعروض للمستخدم: «فشل الاتّصال بالخادم. تحقّق من إعدادات الشبكة والـ URL.»
- السجلّ الداخليّ: المضيف الهدف، فئة خطأ TLS، correlation ID، stack trace، عدد المحاولات.
ذلك التقسيم وحده يُحسّن السرّيّة وقابليّة التشخيص.
3.10. لا تهمل التبعيّات والأدوات
ليس هذا براقاً، لكنّه يهمّ.
حتّى لو كان كود التطبيق دقيقاً، فإنّ runtime عتيقاً أو تبعيّة ذات ثغرات معروفة قد تظلّ هي نقطة الضعف.
خطّ الحدّ الأدنى هو:
- أبقِ إصدارات .NET SDK والـ runtime ضمن النطاقات المدعومة
- افحص تبعيّات NuGet وOSS بانتظام
- بالنسبة لـ C++، أدِر الإعادات القابلة للتوزيع للـ runtime وإصدارات الـ DLL الخارجيّة بشكل صريح
- أدخل مراجعة الثغرات في قائمة تحقّق الإصدار
- احتفظ بـ smoke test كي لا يصبح تحديث التبعيّات مستحيل الشحن
أخطر نمط هنا هو «سنحدّث كلّ شيء لاحقاً».
بعد نصف عام أو عام، قد تصبح فجوة التبعيّات كبيرة بما يكفي لتتحوّل حتّى الصيانة الأمنيّة الأساسيّة إلى عمل ضخم.
4. قائمة تحقّق إصدار يمكنك استخدامها فعلاً
في الأسفل قائمة تحقّق ما قبل الإصدار البسيطة، تعمل كصحيفة مراجعة بنعم أو لا.
4.1. الصلاحيّات ونموذج التنفيذ
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
البدء العاديّ يعمل بـ asInvoker |
□ | |
| العمليّات التي تتطلّب صلاحيّات مسؤول معزولة في EXE أو خدمة أو مكوّن مماثل منفصل | □ | |
| إن استُخدمت خدمة، فهي لا تعمل بحساب أقوى ممّا هو ضروريّ | □ | |
المسؤوليّات مقسومة بوضوح بين %ProgramFiles% ومواقع بيانات المستخدم |
□ |
4.2. التوزيع والتوقيع
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
| EXEs والـ DLLs وحزم MSI / MSIX وbinaries المحدِّث موقَّعة | □ | |
| timestamps مرفقة بالتوقيعات | □ | |
| انتهاء صلاحيّة الشهادات وخطوات التجديد مدرجة في مسار الإصدار | □ | |
| توجد طريقة محدَّدة للتحقّق من السلامة أو كشف العبث للمنتجات الموزَّعة | □ |
4.3. التحديث
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
| استرجاع التحديث يستخدم HTTPS | □ | |
| التحديثات المنزَّلة يُتحقّق منها بتوقيع أو hash | □ | |
| URL مصدر التحديث ليس قابلاً للاستبدال بشكل سطحيّ | □ | |
| توجد سياسة استرجاع أو إعادة محاولة لإخفاقات التحديث | □ |
4.4. الأسرار
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
| كلمات المرور ومفاتيح API وسلاسل الاتّصال غير مكتوبة مباشرةً في المصدر | □ | |
| لا تُخزَّن الأسرار في ملفّات إعدادات بنصّ صريح | □ | |
| الأسرار التي يجب تخزينها محلّيّاً محميّة بـ DPAPI أو Credential Locker أو آليّة Windows مكافئة | □ | |
| حيث أمكن، يميل التصميم إلى مصادقة Windows أو الاعتمادات التي يقدّمها المستخدم | □ |
4.5. أمان النقل
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
| حركة الإنتاج تستخدم HTTPS | □ | |
DangerousAcceptAnyServerCertificateValidator أو تجاوزات الشهادات => true غير موجودة في منتجات الإصدار |
□ | |
| التحقّق من اسم المضيف وفحوص الإلغاء مأخوذان بعين الاعتبار | □ | |
| افتراضات شهادات التطوير فقط لا تتسرّب إلى كود الإنتاج أو الإعدادات | □ |
4.6. المدخلات والوصول إلى البيانات
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
| SQL يستخدم بارامترات | □ | |
| لمدخلات سطر الأوامر والملفّات والـ IPC والـ URI حدود وتحقّق من التنسيق | □ | |
| التعامل مع المسارات يطبّع المدخل ويمنع الإفلات من الجذر | □ | |
| رسائل الاستثناءات الخام لا تُعرض مباشرةً للمستخدمين النهائيّين | □ |
4.7. الـ DLLs وبيئة التشغيل
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
| مصادر تحميل الـ DLL صريحة | □ | |
ترتيب البحث متحكَّم به عبر SetDefaultDllDirectories وAddDllDirectory أو تدابير مكافئة |
□ | |
حلّ الـ DLL لا يعتمد على المجلّد الحاليّ أو PATH |
□ | |
| الملفّات اللازمة للتحميل الديناميكيّ في بيئة الوجهة معروفة | □ |
4.8. الـ logging والتشغيل
| بند الفحص | الحالة | ملاحظات |
|---|---|---|
| الـ tokens وكلمات المرور وPII لا تُكتب في السجلّات | □ | |
| التشخيصات الداخليّة والرسائل المعروضة للمستخدم مفصولة | □ | |
| صلاحيّات تخزين الـ dumps والـ traces والسجلّات راجعت | □ | |
| حالة تحديث SDK والتبعيّات تُفحص ضمن تحضيرات الإصدار | □ |
5. مواساة زائفة شائعة
5.1. «إنّها مجرّد أداة داخليّة»
ما زالت الأدوات الداخليّة تواجه ملفّات تالفة وأخطاء مشغّلين ومجلّدات مشتركة ونقاط نهاية غير مُدارة وDLLs قديمة وصلاحيّات مرخيّة.
عدم التعرّض للإنترنت لا يمحو سطح الهجوم.
5.2. «إنّه يستخدم HTTPS، فهو آمن»
HTTPS مهمّ، لكنّ تعطيل التحقّق من الشهادات يزيل قدراً كبيراً من جدواه.
لتوزيع التحديثات، HTTPS وحده ليس كافياً أيضاً. لا تزال أصالة المنتج بحاجة إلى التحقّق.
5.3. «إنّه مشفَّر، فهو آمن»
التشفير وحده ليس الإجابة الكاملة إن لم يُفكَّر في موضع المفتاح وحقوق فكّ التشفير وحدود المستخدم وحدود الجهاز.
القيم المحميّة بـ LocalMachine، مثلاً، لا ينبغي أن تُعامَل باستخفاف كأنّها أسرار لكلّ مستخدم.
5.4. «إن سجّلنا أكثر، فيمكننا التحقيق لاحقاً دائماً»
إن كانت السجلّات نفسها ترشّ tokens أو بيانات شخصيّة، فإنّ استراتيجيّة الـ logging تصبح جزءاً من الحادثة.
ما يُحفظ وما يُخفى يجب أن يُحدَّد قبل زيادة الحجم.
5.5. «التشغيل كمسؤول يحلّ الأمر»
قد يبدو الأمر أسهل في البداية، لكنّه عادةً يجعل سلوك UAC والتوزيع والدعم وحدود الصلاحيّات وتحميل الـ DLL وموضع الملفّات أصعب لاحقاً.
الحدّ الأدنى من الامتيازات أكثر استقراراً بمرور الوقت.
6. ترتيب أولويّات عمليّ
إن لم يكن إصلاح كلّ شيء دفعة واحدة ممكناً، فإنّ الترتيب المعقول هو:
- راجع رفع الصلاحيّات أوّلاً
توقّف عن استخدامrequireAdministratorكإعداد افتراضيّ. - أضف التوقيع وtimestamping
أرسِ الثقة في ما تشحنه. - انقل الأسرار خارج المصدر والإعدادات بنصّ صريح
قلّل أسهل مسار للتسرّب. - أصلِح اختصارات HTTPS والتحقّق من الشهادات
أزل تجاوزات نمط=> trueمن بناءات الإصدار. - راجع معالجة مدخلات SQL والملفّات والـ IPC
قلّل التسلسل والمدخلات غير المفحوصة. - اجعل تحميل الـ DLL حتميّاً
توقّف عن التحميل بالاسم العاري أو عبر افتراضاتPATH. - أخفِ السجلّات
امنع الاستجابة للحوادث من التحوّل إلى حادثة ثانية. - اجعل مراجعة التبعيّات روتيناً
حوّلها إلى عادة إصدار بدلاً من مشروع مستقبليّ.
يميل ذلك الترتيب إلى العمل جيّداً عندما يكون الهدف ببساطة هو إغلاق أوضح الثغرات أوّلاً.
7. الخلاصة
قبل إضافة أنظمة أمان كبيرة، يتحسّن أمان تطبيقات Windows كثيراً بمجرّد إحكام الأساسيّات حول
الصلاحيّات، والتوقيع، والأسرار، والنقل، والمدخلات، وتحميل الـ DLL، والـ logging.
الخطّ الأدنى الذي يجب الإبقاء عليه ضمن الرؤية:
- لا تشغّل التطبيق بأكمله كمسؤول
- وقّع الـ binaries الموزَّعة والمحدَّثة وأرفق timestamps
- أبقِ الأسرار خارج الكود المصدريّ والإعدادات بنصّ صريح
- لا تعطّل التحقّق من الشهادات حتّى لو استخدمت HTTPS
- لا تثق بمدخلات خارجيّة من SQL أو الملفّات أو الـ IPC أو ما شابه
- اجعل مسارات تحميل الـ DLL صريحة
- أبقِ البيانات الحسّاسة خارج السجلّات
- لا تترك التبعيّات بلا إدارة
الأمان واسع، ولا حاجة لإنهاء كلّ موضوع دفعة واحدة.
لكن ثمّة قيمة كبيرة في التأكّد من أنّ الإعدادات الافتراضيّة الخطرة بشكل واضح ليست هي ما تشحنه.
8. مراجع
- Administrator Broker Model - Win32 apps
- How User Account Control works
- Authenticode Digital Signatures
- Time Stamping Authenticode Signatures
- Sign a Windows app package
- Credential Locker for Windows apps
- CryptProtectData function (dpapi.h)
- CA5359: Do not disable certificate validation
- CA5399: Enable HttpClient certificate revocation list check
- Configuring parameters - ADO.NET Provider for SQL Server
- Connection String Syntax - ADO.NET
- Dynamic-Link Library Security - Win32 apps
- SetDefaultDllDirectories function (libloaderapi.h)
- Data redaction in .NET
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
كيف تعزل العمل الذي يحتاج إلى المسؤول فقط داخل تطبيقات Windows
دليل عمليّ لإبقاء واجهة تطبيق Windows عند asInvoker مع إسناد العمل المرفَّع إلى helper EXE عبر runas و named pipes، مع التحقّق من الطلبات...
أفضل الممارسات في DPAPI لإبعاد الأسرار عن إعدادات النصّ الصريح في تطبيقات Windows
دليل تطبيقيّ لاستخدام DPAPI و ProtectedData في .NET لتخزين أسرار تطبيقات Windows محلّيّاً بدل النصّ الصريح، مع اختيار CurrentUser و Local...
أين يجب التقاط الاستثناءات وتسجيلها ومعالجة الأخطاء - دليل عمليّ للحدود والمسؤوليّات في تسلسل الاستدعاء
دليل عمليّ يساعدك على تحديد مستوى تسلسل الاستدعاء الذي يجب فيه التقاط الاستثناء وكتابة السجلّ وتحويل الإخفاق إلى قرار، مع أمثلة C# وقائمة...
أساسيّات أمان ميزة التحديث التلقائيّ - الأنماط السيّئة وأفضل الممارسات
نلخّص أساسيّات أمان ميزة التحديث التلقائيّ: لماذا لا يكفي HTTPS، وأهمّيّة signed metadata والتحقّق من جهة الـ client وفصل المفاتيح ومواجه...
كيفيّة استخدام FileSystemWatcher بأمان - الأحداث المفقودة والإشعارات المكرّرة وفخاخ كشف الاكتمال
دليل عمليّ يشرح لماذا ينبغي اعتبار FileSystemWatcher مجرّد محفّز للمسح وليس إشارة اكتمال، ويقدّم أنماط المطالبة الذرّيّة و idempotency.
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
تطوير تطبيقات ويندوز
ندعم تطوير برامج ويندوز للأعمال، وتكامل الأجهزة، وأدوات التواصل.