Pysa: كيفية تجنب مشكلات الأمان في كود Python



في 7 أغسطس ، قدم Facebook Pysa ، وهو محلل ثابت مفتوح المصدر يركز على الأمان ويساعدك على العمل مع ملايين سلاسل Instagram. يتم الكشف عن القيود ، ويتم التطرق إلى قرارات التصميم ، وبالطبع ، الوسائل للمساعدة في تجنب الإيجابيات الخاطئة. يظهر الموقف عندما يكون Pysa مفيدًا للغاية ، ويكون الرمز الذي لا ينطبق فيه المحلل. التفاصيل من مدونة Facebook Engineering تحت الخفض.



في العام الماضي ، كتبنا عن كيفية إنشاء Zoncolan ، وهي أداة تحليل ثابتة تحلل أكثر من 100 مليون سطر من كود Hack وتساعد المهندسين على منع الآلاف من مشكلات الأمان المحتملة. ألهم النجاح Pysa - Python Static Analyzer. تم إنشاء المحلل اللغوي أعلى Pyre ، أداة التحقق من نوع Python على Facebook. يعمل Pysa مع تدفق البيانات في التعليمات البرمجية. يعد تحليل تدفق البيانات مفيدًا لأنه غالبًا ما يتم تصميم مشكلات الأمان والخصوصية على أنها بيانات تذهب إلى حيث لا ينبغي أن تكون.



يساعد Pysa في تحديد العديد من أنواع المشاكل. يتحقق المحلل مما إذا كانت الشفرة تستخدم هياكل داخلية معينة بشكل صحيح لمنع الوصول إلى بيانات المستخدم أو الكشف عنها بناءً على سياسات الخصوصية التقنية. بالإضافة إلى ذلك ، يكتشف المحلل مشكلات أمان تطبيقات الويب الشائعة مثل XSS و SQL injection. مثل Zoncolan ، ساعدت الأداة الجديدة في زيادة جهود أمان تطبيقات Python. هذا ينطبق بشكل خاص على Instagram.



Pysa على Instagram



أكبر مستودع Python على Facebook هو ملايين الأسطر على خوادم Instagram. عندما يتم تشغيل Pysa على تغيير كود مقترح للمطور ، فإنه يوفر نتائج في غضون ساعة تقريبًا ، بدلاً من الأسابيع أو الأشهر التي قد يستغرقها التحقق يدويًا. يساعدك هذا في العثور على مشكلة ومنعها بسرعة كافية بحيث لا تصل إلى قاعدة التعليمات البرمجية الخاصة بك. يتم إرسال نتائج الفحوصات مباشرة إلى المطور أو مهندسي السلامة ، اعتمادًا على نوع المشكلة ونسبة الإشارة إلى الضوضاء في الموقف المحدد.



Pysa والمصدر المفتوح



Pysa شفرة المصدر و العديد من التعريفات المشكلة هي مفتوحة للمطورين آخرين لتحليل رمز لمشاريعهم. نحن نعمل مع أطر عمل من جانب الخادم مفتوحة المصدر مثل Django و Tornado ، لذا فمنذ الإطلاق الأول داخل Facebook ، وجد Pysa مشكلات أمنية في المشاريع التي تستخدم هذه الأطر. عادةً ما يكون استخدام Pysa لأطر العمل التي لا تحتوي على تغطية بنفس سهولة إضافة بضعة أسطر من التكوين. تحتاج فقط إلى إخبار المحلل بمصدر البيانات إلى الخادم.



تم استخدام Pysa لاكتشاف مشكلات مثل CVE-2019-19775 في مشاريع Python مفتوحة المصدر. لقد عملنا أيضًا مع مشروع Zulip وأدرجت Pysa في قاعدة بياناتها البرمجية.



كيف تعمل؟



تم تصميم Pysa مع الدروس المستفادة من Zoncolan. يستخدم نفس الخوارزميات لإجراء تحليل ثابت وحتى يشارك الكود مع Zoncolan. مثل Zoncolan ، يراقب Pysa تدفق البيانات في البرنامج. يحدد المستخدم مصادر البيانات المهمة والوجهات التي تأتي منها البيانات. في تطبيقات الأمان ، أكثر أنواع المصادر شيوعًا هي النقاط التي تدخل فيها البيانات التي يتحكم فيها المستخدم إلى التطبيق ، مثل قاموس HttpRequest.GET في Django. تكون أجهزة الاستقبال بشكل عام أكثر تنوعًا ويمكن أن تتضمن تنفيذ واجهات برمجة التطبيقات. على سبيل المثال ، evalأوos.open... يقوم Pysa بشكل متكرر بإجراء جولات من التحليل لبناء الملخصات لتحديد الوظائف التي تقوم بإرجاع البيانات من المصدر وأيها تصل المعلمات إلى الوجهة. عندما يكتشف المحلل أن المصدر يتصل في النهاية بجهاز الاستقبال ، فإنه يبلغ عن المشكلة. تصور هذه العملية عبارة عن شجرة بها مشكلة في الأعلى ومصادر وتدفق في الأوراق:







لإجراء تحليل إجرائي مشترك - لمتابعة تدفق البيانات بين استدعاءات الوظائف - يجب أن تكون قادرًا على تعيين استدعاءات الوظائف لتطبيقاتها. للقيام بذلك ، تحتاج إلى استخدام جميع المعلومات المتاحة في الكود ، بما في ذلك الأنواع الثابتة الاختيارية ، إن وجدت. لقد عملنا مع Pyre لمعرفة هذه المعلومات. بينما تعتمد Pysa بشكل كبير على Pyre وتتشارك كلتا الأداتين في نفس المستودع ، فمن المهم ملاحظة أن هذه المنتجات منفصلة بتطبيقات منفصلة. 



ايجابيات مزيفة



مهندسو الأمن هم المستخدمون الرئيسيون لـ Pysa على Facebook. مثل أي مهندس يعمل بأدوات الكشف عن الأخطاء تلقائيًا ، كان علينا معرفة كيفية التعامل مع الإيجابيات الزائفة (لا توجد مشكلة ، لا توجد إشارة) والسلبيات (لا توجد مشكلة ، لا توجد إشارة).



يهدف تصميم Pysa إلى تجنب إهمال المشكلات واكتشاف أكبر عدد ممكن من المشكلات الحقيقية. ومع ذلك ، فإن تقليل عدد الإنذارات الكاذبة يمكن أن يتطلب مقايضات تزيد من عدد الإشارات غير الضرورية. يؤدي الكثير من الإيجابيات الخاطئة إلى إجهاد القلق وخطر التغاضي عن مشاكل حقيقية في الضوضاء. لدى Pysa أداتان لإزالة الإشارات غير المرغوب فيها: المطهرات والعلامات.



مطهرهي أداة بسيطة. يخبر المحلل اللغوي بعدم متابعة دفق البيانات بعد مرور الدفق عبر الوظيفة أو السمة. تسمح لك المطهرات بتشفير معرفة تحويل المجال التي تقدم البيانات دائمًا بطريقة آمنة وسرية.



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



لفهم المواقف الأكثر فائدة من Pysa ، تخيل أن الكود التالي يعمل لتحميل ملف تعريف مستخدم:



# views/user.py
async def get_profile(request: HttpRequest) -> HttpResponse:
   profile = load_profile(request.GET['user_id'])
   ...
 
# controller/user.py
async def load_profile(user_id: str):
   user = load_user(user_id) # Loads a user safely; no SQL injection
   pictures = load_pictures(user.id)
   ...
 
# model/media.py
async def load_pictures(user_id: str):
   query = f"""
      SELECT *
      FROM pictures
      WHERE user_id = {user_id}
   """
   result = run_query(query)
   ...
 
# model/shared.py
async def run_query(query: str):
   connection = create_sql_connection()
   result = await connection.execute(query)
   ...


هذا هو المكان الذي لا يمكن فيه استغلال حقن SQL المحتمل في load_pictures: هذه الوظيفة تصبح صالحة دائمًا user_idمن الوظيفة load_userفي load_profile. عند التهيئة بشكل صحيح ، ربما لن تبلغ Pysa عن مشكلة. تخيل الآن أن مهندسًا مغامرًا يكتب رمزًا على مستوى وحدة التحكم يدرك أن جلب بيانات المستخدم وصورة في نفس الوقت يؤدي إلى نتائج أسرع:



# controller/user.py
async def load_profile(user_id: str):
   user, pictures = await asyncio.gather(
       load_user(user_id),
       load_pictures(user_id) # no longer 'user.id'!
   )
   ...


قد يبدو التغيير غير ضار ، لكنه في الواقع ينتهي بدمج السلسلة التي يتحكم فيها المستخدم user_idمع مشكلة حقن SQL في load_pictures. في تطبيق به العديد من الطبقات بين نقطة الإدخال واستعلامات قاعدة البيانات ، قد لا يدرك المهندس أن المستخدم يتحكم في البيانات بالكامل ، أو أن مشكلة الحقن مخفية في الوظيفة التي تم استدعاؤها. هذا هو بالضبط الموقف الذي تمت كتابة المحلل من أجله. عندما يقترح مهندس تغييرًا مشابهًا على Instagram ، يكتشف Pysa أن البيانات تنتقل من إدخال يحركه المستخدم إلى استعلام SQL ويبلغ عن المشكلة.



قيود المحلل



من المستحيل كتابة محلل ثابت مثالي . Pysa لها قيود في النطاق وتدفق البيانات وقرارات التصميم ، مما يضر بالأداء من أجل الدقة والدقة. تتميز بايثون كلغة ديناميكية بخصائص فريدة تكمن وراء بعض قرارات التصميم هذه.



مساحة المشكلة



تم تصميم Pysa لاكتشاف مشكلات الأمان المتعلقة بتدفقات البيانات فقط. لم يتم تصميم جميع مخاوف الأمان أو الخصوصية على أنها تدفقات بيانات. تحقق من مثال:



def admin_operation(request: HttpRequest):
  if not user_is_admin():
      return Http404
 
  delete_user(request.GET["user_to_delete"])


لا تعد Pysa الأداة الصحيحة لضمان user_is_adminتشغيل فحص التفويض قبل إجراء عملية ذات امتياز delete_user. يمكن للمحلل اكتشاف البيانات من request.GETالتوجيه إلى delete_user، لكن هذه البيانات لا تخضع للتحقق مطلقًا user_is_admin. يمكن إعادة كتابة الكود لجعل المشكلة على غرار Pysa ، أو يمكنك إنشاء التحقق من الأذونات في عملية إدارية delete_user. لكن هذا الرمز يوضح أولاً وقبل كل شيء المشكلات التي لا يحلها Pysa.



حدود الموارد



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



قيد آخر هو وقت التطوير. لقد فرضت تسوية بشأن ميزات Python المدعومة. لا يتضمن Pysa حتى الآن أدوات الديكور في الرسم البياني للمكالمات عند استدعاء الوظائف وبالتالي يتخطى المشاكل داخل الديكور. 



بايثون كلغة ديناميكية



تجعل مرونة Python التحليل الثابت صعبًا. من الصعب تتبع تدفقات البيانات من خلال استدعاءات الأسلوب بدون معلومات النوع. في الكود أدناه ، من المستحيل تحديد أي من التطبيقات flyيسمى:



class Bird:
  def fly(self): ...
 
class Airplane:
  def fly(self): ...
 
def take_off(x):
  x.fly()  # Which function does this call?


يعمل المحلل في مشاريع غير نمطية تمامًا. لكن لا يتطلب الأمر سوى القليل من الجهد لتغطية الأنواع المهمة.



تفرض الطبيعة الديناميكية لبايثون قيودًا أخرى. انظر أدناه:



def secret_eval(request: HttpRequest):
  os = importlib.import_module("os")
 
  # Pysa won't know what 'os' is, and thus won't
  # catch this remote code execution issue
  os.system(request.GET["command"])


تظهر ثغرة التنفيذ بوضوح هنا ، لكن المحلل سيتخطى ذلك. يتم osاستيراد الوحدة بشكل ديناميكي. لا يفهم Pysa أن المتغير المحلي os يمثل الوحدة النمطية بالضبط os. تتيح لك Python استيراد أي رمز تقريبًا بشكل ديناميكي في أي وقت. بالإضافة إلى ذلك ، يمكن للغة تغيير سلوك استدعاء الوظيفة لأي كائن تقريبًا. يمكن لـ Pysa تعلم تحليل نظام التشغيل واكتشاف المشكلة. لكن ديناميكية بايثون تعني أن هناك أمثلة لا حصر لها من تدفقات البيانات المرضية التي لن يراها المحلل.



النتائج



في النصف الأول من عام 2020 ، استحوذت Pysa على 44 بالمائة من جميع المشكلات التي تم اكتشافها على Instagram. من بين جميع أنواع الثغرات الأمنية ، تم العثور على 330 مشكلة فريدة في التغييرات البرمجية المقترحة. 49 (15٪) مشكلة اتضح أنها كبيرة ، 131 من المشاكل (40٪) كانت حقيقية ، لكن كانت لها ظروف مخففة. تم تسجيل السلبيات الكاذبة في 150 (45٪) حالة.



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



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



وثائق محلل Pysa والبرامج التعليمية .

صورة


تعرف على تفاصيل كيفية الحصول على مهنة رفيعة المستوى من البداية أو من المستوى الأعلى في المهارات والراتب من خلال حضور دورات SkillFactory عبر الإنترنت:





E







All Articles