SQL-injection MODX Revolution < 2.5.1
Пример уязвимого сценария
Код:
<?php
define('MODX_API_MODE', true);
require dirname(__FILE__) . '/index.php';
$modx->getService('error', 'error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget('FILE');
try{
if(empty($_REQUEST['id'])) throw new Exception('Invalid request', 500);
$doc = $modx->getObject(modResource::class, $_REQUEST['id']);
if($doc) echo $doc->pagetitle;
else throw new Exception("Document not found", 404);
}catch(Exception $e){
$modx->sendError($e->getMessage(), [
'error_type' => $e->getCode()
]);
}
Если $_REQUEST['id'] будет массивом, то мы можем конструировать свои параметры выборки в соответствии с
документацией
Но ОРМ будет фильтровать некоторые запросы. Поэтому можно попробовать засунуть скулю в ключ параметра.
Код:
$_REQUEST['id']['1 = (SELECT COUNT(*) FROM modx_site_content)']
Можно попробовать сделать выборку UNION. Но такие запросы проходят через
фильтрацию
Код:
protected function isValidClause($clause) {
$output = rtrim($clause, ' ;');
$output = preg_replace("/\\\\'.*?\\\\'/", '{mask}', $output);
$output = preg_replace('/\\".*?\\"/', '{mask}', $output);
$output = preg_replace("/'.*?'/", '{mask}', $output);
$output = preg_replace('/".*?"/', '{mask}', $output);
return strpos($output, ';') === false && strpos(strtolower($output), 'union ') === false;
}
Соответственно для обхода используем запрос вида
Уязвимость древняя еще со времен
MODX Revolution 2.2.12 (only). Просто до этого точка входа была в коннекторах ядра, а сейчас сместилась в коннекторы компонентов.