Injection attacks on System() Function
Injection Attacks on System()
استكمالًا للمقالة السابقة
هذه المقالة تُلقي نظرة على بعض ثغرات الـ Injection Attacks في لغة C ، ومتى يتم خَلط مُدخلات المستخدمين مع الكود البرمجي، و ما هو الـ Parser في كل حالة؟
بسم الله نبدأ،
بدايةً، لنفصّل قليلًا في ماهية برامج الـ C
البرنامج المكتوب بلغة C بعدما يتم الإنتهاء من كتابته يتم عمل Compile للـ Source Code ومن ثم يتم تحويله الى Binary Code ، قبل هذه العملية وتحديدًا في مرحلة الـ Compilation Time لا يوجد لدينا أي مُدخلات من المستخدمين ليتم خلطها مع الكود.
للنظُر للصورة الآتية التي تُلخّص المراحل التي يمر بها البرنامج قبل أن يُصبح ملفًا تنفيذيًا (تستطيع الاطلاع على بعض التفاصيل المتعلّقة بهذه العملية وتلخيصها من هنا)
بعدما يتم عمل Compile للكود لنقول بأن الكود سيصبح قطعةً واحدة وسيتم تخزينه في مكانٍ ما في الذّاكرة، وهذا المكان مُنفصل عن المكان الذي ستُخزّن فيه البيانات القادمة من المستخدمين ( إذا أردت الاستزادة حول هذا الموضوع اطلع على هذه المقالة )
تجدر الإشارة أيضًا بأنه في كل مرّة يريد بها المبرمج إضافة "كود" لبرنامجه فيجب عليه تكرار العملية السّابقة حتى يحصل على الملف التنفيذي، أي بعبارة أخرى يجب أن يمر الكود على مرحلة الـ Compilation Time والتي ذكرنا بها سابقًا أنه لن يعبُر من خلالها أي بيانات قادمه من المستخدمين، ذكرنا أيضًا أن كِلا الجزئين (الكود و بيانات المستخدمين) يتم حفظهما في مكانين منفصلين ، فكيف إذًا يحدث الخَلط وكيف تحدث ثغرات الـ Injection Attacks في لغة C !
· Attacks on System()
قبل أن نخوض في التفاصيل، يجب علينا معرفة الوظيفة التي تؤديها هذه الدالة حتى نستطيع فهم أين تحدث المُشكلة ولماذا تحدث أساسًا؟
System() :
o هذه الدّالة تُتيح لنا تنفيذ تعليمات مع تحديد الـ Parameters الخاصّة بهذه التعليمات ( في حالة كانت التعليمة تحتاج إلى تمرير قيم للـ Parameters) .
o ماذا نقصد بالتعليمات هنا؟ نقصد الأوامر الخاصّة بالـ shell مثل ls , mkdir , pwd وغيرها (بالإمكان استخدام نفس الدالة على أنظمة ويندوز، لكن تركيزنا هنا على نظام لينكس).
لو لاحظنا، بعض من هذه الأوامر تحتاج أن تستقبل Parameters حتى يتم تنفيذ الأمر ، والـ Syntax الخاص بالدالة كالآتي :
system(char *command);
نلاحظ أن دالة الـ System تستقبل Parameter واحد، وهذا يعني أنه عندما يقوم المبرمج باستخدام هذه الدالة، فإنه يجب عليه تمرير الأمر المراد تنفيذه + الـ Parameters الخاصة بالأمر وسيتم تمريرهم للدالة كـ Parameter واحد ( بعبارة أخرى سيتم عمل Concatenate للأمر والـ Parameters الخاصة به).
لنأخذ مثال على استخدام الدالة حتى تتّضح وظيفتها أكثر:
int main(int argc, char** argv)
{
char cmd[CMD_MAX] = "/usr/bin/cat "; strcat(cmd, argv[1]);
system(cmd);
}
في المثال أعلاه قام المبرمج بتحديد الأمر الذي سيتم تمريره للدالة وهو نداء البرنامج /usr/bin/cat والذي سيقوم بعملية القراءة للملف، أي ملف؟ هنا عملية تحديد الملف متروكة للمستخدم (أي أن الـ Parameter الخاصة بهذا الأمر يتم تحديدها من قبل المستخدم)
بعدما يتم قراءة الـ Parameter الخاصة بهذا الأمر سيتم عمل Concatenate للأمر والـ Parameter الخاصة به عن طريق تمرير القيم للدالة strcat (هنا يحدث الخَلط)، والقيمة النهائية سيتم إرسالها للدالة System ، الآن لنتحدث قليلًا عن ما تقوم بفعله هذه الدالة تحديدًا ،
هل تقوم هي بنفسها بتنفيذ التعليمة ( نقصد تنفيذ برنامج الـ cat مع قيم الـ Parameter الخاصة به) ؟
الإجابة: لا
الدالة لا تقوم بنفسها بتنفيذ الأمر لكنها تقوم بنداء برنامج آخر يمكنه تنفيذ أوامر النظام، أعتقد أنه أتضح لك الآن لماذا تحدث المُشكلة؟
لنفصّل مرّة أخرى ..
لو عُدنا للمرجع السابق الخاص بالدالة ، سنجد هذه العبارة:
system() executes a command specified in command by calling /bin/sh -c command
والذي يعني بأن الدالة ستقوم بنداء البرنامج /bin/sh والذي بدوره سيقوم بتنفيذ التعليمة التي مُرّرت له عن طريق الدالة System
الآن بما أن الذي سيُنفّذ التعليمة هو /bin/sh فهذا يعني أن الـ Parser الذي سيفسّر هذه التعليمة هو Parser آخر وليس الـ Parser الخاص بلغة C
وفي حالة استخدام هذه الدالة مع أنظمة لينكس فالـ Parser هنا هو الـ Shell Parser
لنُلخّص الآن كُل ما سبق:
دالة System هي دالة تتيح لنا تنفيذ تعليمات خاصة بالنظام، الدالة تستقبل Parameter واحد، أي يتوجب على المبرمج تمرير قيمة واحدة تحمل التعليمة والـ Parameters الخاصة بها ( هنا يحدث الخَلط) ، أيضًا الدالة لا تقوم بنفسها بتنفيذ التعليمات إنما تقوم بنداء shell program والذي سيقوم بتنفيذ التعليمة والذي يعني أيضًا أن الـ Parser هنا هو Shell Parser ، عندما يترك المُبرمج عملية تحديد الـ Parameter الخاصة بالتعليمة للمستخدم تبدأ تحدث المشكلة!
المرجع:
كتاب: Computer Security - A hands-on Approach
فصل: SQL Injection Attack
الموضوع: The Fundamental Cause
صفحة: 194-195