произвольный JOIN в обход xpdo
Сегодня делал рандомную выборку данных, т.к. при большом кол-во данных вроде как в старый mysql сортировка по rand() проходила очень долго. В сети существует множество вариантов как сделать так чтобы выборка была еще быстрее, но по большей части в них используются процедуры, вложенные sql и самый простой вариант мудренный JOIN. Мне не хотелось для моей задачи писать сниппет и я использовал msProducts, который использует методы pdoTools для построения запросов. Поэтому начну с него. Для того чтобы передать состряпать JOIN мы можем использовать запись JSON, но если нам нужен вот такой
Конечно нельзя сказать что это настоящая уязвимость, но она вполне имеет место, если вы используете в своих сниппетах или запросах непроверенное содержимое запросов браузера или позволяете менеджерам выполнять код modx (и то и другое уже открытые ворота конечно же). Хотя по мне, так это прекрасная возможность использовать хитрые JOIN-ы.
JOIN ( SELECT CEIL(RAND() * (SELECT MAX(id) FROM random)) AS id ) AS r2 USING (id);
??? то формат вида: "Randomid": {
"alias":"...",
"class":"...",
"on":"..."
},
Нам не подходит, да и вообще нет параметров в сниппете которыми можно воспользоваться чтобы добавить такой запрос (если я чего не пропустил конечно). НО есть маленькая лазейка. В pdofetch join строиться как $this->query->$join($class, $alias, $v['on']);
query это xPDOQuery. Так вот, если мы передадим в него, в моем случае воспользовавшись сниппетом, такую конструкцию при которой JOIN будет парсироваться правильно:"Randomid": {
"alias":"modResource",
"class":"modResource",
"on":"1=1 JOIN ( SELECT CEIL(RAND() * (SELECT MAX(id) FROM `modx_site_content`)) AS rid ) AS r2"
},
То мы получим вполне работоспособный JOIN. Сразу возникает вопрос, а что если после 1=1 послать ; SELECT 1,2,3
Отвечу: не прокатит, получим ошибку SQL injection attempt detected: 1=1; SELECT 1,2,3
Не проверял но думаю это либо xpdo либо уже pdo проверяет наличие точки с запятой и UNION. Но это конечно не значит что прикрыты все дырки, например, если в сниппет послать такой подарок:...&leftJoin=`{
"Randomid": {
"class":"modResource",
"on":"1=1 AND ExtractValue(1,concat(0x5C,(select password from modx_users where id=1 limit 1)))"
}...
}`
То некоторые версии SQL воспримут как нужно и вернут нам нечто вроде:Т.е. в тексте ошибки вернется нам результат запроса.Конечно нельзя сказать что это настоящая уязвимость, но она вполне имеет место, если вы используете в своих сниппетах или запросах непроверенное содержимое запросов браузера или позволяете менеджерам выполнять код modx (и то и другое уже открытые ворота конечно же). Хотя по мне, так это прекрасная возможность использовать хитрые JOIN-ы.
Поблагодарить автора
Отправить деньги