كيفية حماية تطبيقات Python من إدخال البرامج الضارة





تستخدم تطبيقات Python الكثير من البرامج النصية. هذا ما يستخدمه مجرمو الإنترنت لوضع "خنزير" علينا - حيث لا نتوقع رؤيته على الأقل.



تتمثل إحدى مزايا Python في سهولة استخدامها: لتشغيل برنامج نصي ، ما عليك سوى حفظه في .pyملف وتنفيذ الأمر python (, python my_file.py). بل هو أيضا من السهل كسر ملفنا، مثل وحدات my_app.pyو my_lib.pyالاستمرار في ربط وحدات لتصميم استخدام import...from: import my_lib from my_app.py.



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



ضع كود بايثون في مكان آمن



يعتمد نموذج أمان Python على ثلاثة مبادئ:



  1. , sys.path , .
  2. , (main), sys.path.
  3. python , -c -m.


لنفترض أنك تريد تشغيل تطبيق Python الذي تم تثبيته "بشكل صحيح" على جهازك. في هذه الحالة ، الموقع الوحيد (إلى جانب المجلد الذي تم تثبيت Python عليه) الذي سيتم إضافته تلقائيًا إلى sys.path افتراضيًا هو المجلد الذي يحتوي على البرنامج النصي الرئيسي أو الملف القابل للتنفيذ.



على سبيل المثال ، إذا كان pipفي /usr/bin، وقمت بتشغيل /usr/bin/pip، sys.pathفسيتم إضافة فقط /usr/bin. يمكن فقط للجذر كتابة الملفات إلى / usr / bin ، لذلك يعتبر هذا الموقع آمنًا.



ومع ذلك، فإن الاتفاق يتطلب منا أن نفعل ذلك: /path/to/python -m pip. هذا يتجنب المشاكل ويتعارض $PATHمع وثائق Windows.



بشكل عام ، سيكون كل شيء على ما يرام على أي حال ، إذا كان لديك وحدك سلطة إضافة وتعديل الملفات في الدلائل التي تأخذ منها Python الوحدات النمطية للاستيراد.



مجلد التنزيلات - موقع ضعيف



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



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



ومع ذلك ، سيكون من الصعب جدًا حل هذه المشكلة تمامًا: على سبيل المثال ، لا يزال هناك خيار متاح Content-Disposition HTTP header’s filename*يتيح للمواقع اختيار دليل لوضع الملفات التي تم تنزيلها.



كيف يعمل الهجوم



تشغيل التثبيت: python -m pip. أنت تقوم بتنزيل حزمة Python من موقع ويب موثوق به تمامًا ، والذي ، لسبب ما ، يقدم تنزيلات مباشرة بدلاً من PyPI. ربما يكون نوعًا من الإصدار الداخلي ، وربما إصدارًا أوليًا - لا فرق. لذلك يذهب إليك totally-legit-package.whl:



~$ cd Downloads
~/Downloads$ python -m pip install ./totally-legit-package.whl


يبدو أنه لا بأس به ، ولكن اتضح أنه قبل أسبوعين على موقع مختلف تمامًا قمت بزيارته ، قام بعض XSS JavaScript بتنزيل pip.py ببرامج ضارة في مجلد التنزيلات دون علمك.



فقاعة!



يصطدم!



~$ mkdir attacker_dir
~$ cd attacker_dir
~/attacker_dir$ echo 'print("lol ur pwnt")' > pip.py
~/attacker_dir$ python -m pip install requests
lol ur pwnt


سلوك غريب PYTHONPATH



بضع فقرات أعلاه ، كتبت:



الموقع الوحيد (بخلاف مجلد Python المثبت) الذي سيتم إضافته تلقائيًا إلى sys.path افتراضيًا هو البرنامج النصي الرئيسي أو المجلد القابل للتنفيذ.


إذن ماذا يفعل "الافتراضي" هنا؟ ما المواقع الأخرى التي يمكنني إضافتها؟



في الأساس ، $PYTHONPATHيمكنك كتابة أي شيء لمتغير البيئة . لكنك لن تكتب موقعك الحالي $PYTHONPATH، أليس كذلك؟



لسوء الحظ ، هناك موقف قد تقوم فيه بذلك عن طريق الخطأ.

لنرسم تطبيق Python "الضعيف" للتوضيح:



# tool.py
try:
    import optional_extra
except ImportError:
    print("extra not found, that's fine")


دعونا ننشئ دليلين: install_dirو attacker_dir. دعنا نفشل install_dir، ثم ننفذ cd attacker_dirونضع الكود الضار هناك بالاسم tool.py:



# optional_extra.py
print("lol ur pwnt")


كل ما تبقى هو تشغيله:



~/attacker_dir$ python ../install_dir/tool.py
extra not found, that's fine


حتى الآن ، كل شيء يسير على ما يرام.



لكن الآن سنرى خطأ شائعًا. العديد نوصي بإضافة واحد $PYTHONPATHأكثر شيء :



export PYTHONPATH="/new/useful/stuff:$PYTHONPATH";


للوهلة الأولى ، يبدو هذا منطقيًا: إذا أضفت المشروع X إلى $PYTHONPATH، ربما ، وفقًا للمشروع Y ، تمت إضافة شيء ما هناك أيضًا ، أو ربما لا ؛ في أي حال ، لن ترغب في الكتابة فوق التغييرات المرتبطة بالمشاريع الأخرى. هذا مهم بشكل خاص عند كتابة الوثائق التي سيستخدمها العديد من الأشخاص.



والآن نحن نواجه سلوك "غريب" $PYTHONPATH. إذا $PYTHONPATHكان فارغًا أو لم يتم تثبيته قبل الإطلاق الأول ، فسيظهر سطر فارغ فيه ، والذي سيتم التعرف عليه على أنه الدليل الحالي. دعنا نتحقق من هذا:



~/attacker_dir$ export PYTHONPATH="/a/perfectly/safe/place:$PYTHONPATH";
~/attacker_dir$ python ../install_dir/tool.py
lol ur pwnt


لمزيد من الأمان ، دعنا نجعله $PYTHONPATHفارغًا وحاول مرة أخرى:



~/attacker_dir$ export PYTHONPATH="";
~/attacker_dir$ python ../install_dir/tool.py
lol ur pwnt


بالضبط ، هذا ليس آمنًا على الإطلاق! وشيء آخر



: اتضح أن المواقف التي يكون فيها المتغير $PYTHONPATHفارغًا وعندما $PYTHONPATHلا يتم تعيين متغير ، هناك قصتان مختلفتان:



os.environ.get("PYTHONPATH") == ""</code>  <code>os.environ.get("PYTHONPATH") == None.


إذا كنت تريد التأكد من التنظيف $PYTHONPATH، فاستخدم الأمر unset:



~/attacker_dir$ python ../install_dir/tool.py
extra not found, that's fine


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



إذا لم تتمكن من القيام بذلك لسبب ما ، فاستخدم اختراق الحياة :



export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}new_entry_1"
export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}new_entry_2"


في bash و zsh ، سيعطي هذا الناتج:



$ echo "${PYTHONPATH}"
new_entry_1:new_entry_2


حسنًا ، الآن لا توجد نقطتان إضافيتان وإدخالات فارغة.



وأخيرًا: إذا كنت لا تزال تعمل $PYTHONPATHباستخدام المسارات المطلقة. دائما!



المشكلة أكثر خطورة



هناك عدة خيارات للتطور الخطير للأحداث المرتبطة بإطلاق ملفات Python من مجلد التنزيلات:



  • تشغيل بيثون ~/Downloads/anything.py(حتى لو كان anything.pyآمنًا بحد ذاته ). ستتم إضافة مجلد التنزيلات إلى sys.path.
  • بمجرد بدء التشغيل ، jupyter notebook ~/Downloads/anything.ipynbستتم إضافة مجلد التنزيلات أيضًا إلى sys.path.


لذلك ، من الأفضل إزالة ملفات .py و .ipynb من هذا المجلد قبل التشغيل.



لا يؤدي التنفيذ cd Downloadsوالتشغيل اللاحق python -cمع الإرشادات importالداخلية أو التشغيل التفاعلي pythonمع الاستيراد اللاحق إلى حل المشكلة تمامًا إذا كانت الملفات المستوردة موجودة في مجلد التنزيلات.



لسوء الحظ ، ~/Downloads/ليس هذا هو الموقع الوحيد الذي يمكن أن يحتوي على ملفات ضارة. على سبيل المثال ، إذا كنت تدير خادمًا يمكن للمستخدمين تحميل الملفات إليه ، فتأكد من أنه لا يمكن لأي شخص أو أي شيء البدء cd public_uploadsقبل تشغيل الأمر python.



في هذه الحالة ، قد يكون من المفيد الأخذ في الاعتبار أن الكود الذي يعالج تحميل الملفات مُلحق بأسمائهم .uploaded. سيساعد هذا في تجنب تنفيذ البرنامج النصي غير المخطط له .py.



يحذر



إذا كانت لديك تطبيقات مكتوبة بلغة Python وتريد استخدامها أثناء وجودك في مجلد التنزيلات ، اجعلها قاعدة لإدخال المسار إلى البرنامج النصي ( / path / to / venv / bin / pip) ، وليس الوحدة النمطية ( / path / to / venv / bin / python -m pip).



بشكل عام ، تجنب استخدام التنزيلات كدليل العمل الحالي الخاص بك وانقل أي نصوص برمجية تريد استخدامها إلى موقع أكثر ملاءمة قبل البدء.



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



بحكم الضرورة



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



على مر السنين ، لاحظت بتردد يحسد عليه كيف لم يفهم المستخدمون من أين يتم تنزيل Python للرمز. على سبيل المثال ، وضع الأشخاص برنامجهم الأول باستخدام Twisted في ملف يسمى twisted.py. لكن في هذه الحالة ، فإن استيراد المكتبة أمر مستحيل!



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



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



خطأ أو ميزة ...



لا شيء مما وصفته أعلاه هو في الواقع "خطأ" أو "ثغرة أمنية". لا أعتقد أن مطوري Python أو Jupyter فعلوا أي شيء عن طريق الخطأ. يعمل النظام بالطريقة التي تم تصميمه بها ويمكن تفسير ذلك على الأرجح. أنا شخصياً ليس لدي أي فكرة عن كيفية تغيير شيء ما فيها دون تقليص قوة بايثون التي نقدرها كثيرًا.



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



لذلك ، من خلال تفصيل تعقيدات برمجة Python النصية ، آمل أيضًا أن أفكر ببعض مهندسي الأمن. هل يمكن جعل SawStop لتنفيذ تعليمات برمجية عشوائية للمترجمين التفاعليين؟ ما الحل الذي يمكن أن يمنع بعض المشاكل المذكورة أعلاه؟



ابقوا أصدقاء آمنين.






إعلان



تقدم VDSina خوادم آمنة على Linux أو Windows - اختر أحد أنظمة التشغيل المثبتة مسبقًا ، أو قم بالتثبيت من صورتك.






All Articles