
VTiger Open Source CRM v7.5 में प्रमाणित SQL इंजेक्शन भेद्यता
द्वारा खोजा गया: जैकब इलियट
07/13/23
VTiger CRM v7.5.0 के रिपोर्ट मॉड्यूल में, रिपोर्ट के लिए चयनित फ़ील्ड्स की जाँच अपर्याप्त है, जो संग्रहीत की जाती हैं और बाद में रिपोर्ट चलाए जाने पर दूसरे-क्रम SQL इंजेक्शन के रूप में पुन: प्रस्तुत की जाती हैं। यह हमलावर को डेटाबेस से मनमाने फ़ील्ड लीक करने की अनुमति देता है, जिसमें उपयोगकर्ता पासवर्ड हैश, वेबसर्विस API एक्सेस कुंजियाँ और अन्य संवेदनशील डेटा शामिल हैं।
CRM में प्रमाणीकरण के बाद, उपयोगकर्ता रिपोर्ट मॉड्यूल पर जा सकता है और एक नई रिपोर्ट बना सकता है।

जिस तरह से तालिकाएँ जुड़ी हुई हैं, उसके कारण प्राथमिक मॉड्यूल के रूप में एक ऐसा मॉड्यूल चुनना सबसे अच्छा काम करता है जिसमें रिकॉर्ड हों। मैंने Contacts चुना, जिसमें एक रिकॉर्ड था।

इसके बाद, उपयोगकर्ता प्राथमिक मॉड्यूल से कोई भी वैध फ़ील्ड चुन सकता है और रिपोर्ट निर्माण प्रक्रिया जारी रख सकता है।

अंत में, उपयोगकर्ता BurpSuite जैसे प्रॉक्सी टूल के साथ कनेक्शन को इंटरसेप्ट करते हुए अंतिम रिपोर्ट को सहेजने के लिए बटन पर क्लिक कर सकता है। selected_fields पैरामीटर में, पहले से चयनित फ़ील्ड निम्नलिखित प्रारूप में सेव फ़ंक्शन को भेजे जाते हैं:
sql_table:sql_column:label:field_name
इस बिंदु पर, उपयोगकर्ता sql_table और sql_column को डेटाबेस से लीक करने के लिए किसी भी मनमाने मान में संशोधित कर सकता है। इस POC के लिए, मैंने उपयोग किया:
vtiger_users:user_name:Contacts_Salutation:salutationtype
और
vtiger_users:user_password:Contacts_First_Name:firstname
संशोधित अनुरोध को अग्रेषित करने के बाद, हमें अंतिम रिपोर्ट प्रस्तुत की जाती है जिसमें डेटाबेस से वांछित कॉलम होते हैं, जो व्यवस्थापक उपयोगकर्ता का उपयोगकर्ता नाम और पासवर्ड हैश प्रकट करता है।

उचित जाँच की कमी modules/Reports/ReportRun.php (पंक्तियाँ 394-398) में शुरू की गई है। प्रदान किए गए प्रत्येक कॉलम नाम को ":" पर विभाजित किया जाता है।
$selectedfields = explode(":", $fieldcolname);
और फिर यदि उपयोगकर्ता व्यवस्थापक नहीं है, तो स्क्रिप्ट यह जाँचता है कि फ़ील्ड अनुमत फ़ील्ड्स की सरणी में है या नहीं, जो रिपोर्ट के लिए चयनित प्राथमिक मॉड्यूल से उत्पन्न होता है:
!in_array($selectedfields[3], $permitted_fields[$module])
हालाँकि, दिए गए इनपुट को याद करें:
vtiger_users:user_name:Contacts_Salutation:salutationtype
क्योंकि "अनुमत फ़ील्ड्स" की जाँच सरणी में इंडेक्स 3 पर तत्व के विरुद्ध की जा रही है, जाँचा जा रहा फ़ील्ड Contacts मॉड्यूल में salutationtype है, जिसे संवेदनशील नहीं माना जाता है और इसलिए इसे निर्यात के लिए अनुमति है। हालाँकि, सरणी के पहले दो तत्वों में प्रदान की गई तालिका और कॉलम की कोई सत्यापन प्रक्रिया नहीं होती, जिससे डेटा का खुलासा होता है।
यह समस्या इस कमिट में चयनित फ़ील्ड्स पर सत्यापन को बदलकर ठीक की गई थी ताकि उन्हें प्रत्येक मॉड्यूल में हार्ड-कोडेड अनुमत फ़ील्ड्स के विरुद्ध जाँचा जाए।
public function checkPermission(Vtiger_Request $request) {
parent::checkPermission($request);
$record = $request->get('record');
if ($record) {
$reportModel = Reports_Record_Model::getCleanInstance($record);
if (!$reportModel->isEditable()) {
throw new AppException(vtranslate('LBL_PERMISSION_DENIED'));
}
}
$selectedFields = $request->get('selected_fields');
$groupbyfields = $request->get('groupbyfield');
$fieldsData = array($selectedFields, $groupbyfields);
foreach ($fieldsData as $selectedField){
foreach ($selectedField as $field) {
list($tablename, $colname, $module_field, $fieldname, $single) = split(":", $field);
list($module, $fieldName) = split("_", $module_field, 2);
$moduleModel = Vtiger_Module_Model::getInstance($module);
$fieldModel = Vtiger_Field_Model::getInstance($fieldname, $moduleModel);
if (($fieldModel->table !== $tablename) || ($fieldModel->column !== $colname)) {
throw new AppException(vtranslate('LBL_PERMISSION_DENIED'));
}
}
}
return true;
}