The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



"Опасные уязвимости в платформе электронной коммерции Magento "
Версия для распечатки Пред. тема | След. тема
Форум Разговоры, обсуждение новостей
Исходное сообщение [ Отслеживать ]
Заметили полезную информацию ? Пожалуйста добавьте в FAQ на WIKI.
. "Опасные уязвимости в платформе электронной коммерции Magento..." +/
Сообщение от Ordu (ok), 29-Мрт-19, 05:04 
>> let result = query_builder()
>>     .select(["uid", "nickname", field_name])
>>     .from(USERS_TABLE)
>>     .where(less(length("nickname"), 5))
>>     .execute(SQL_CONNECTION);
> Ну с селектом-то всё просто. Если уж показывать, то джойны, агрегаты, вложенные
> запросы. =)

Мне сложно навскидку предложить решение для php. Там нужны ссылки на поля из разных таблиц, но как это представить в синтаксисе php, чтобы это было бы не совсем уродливо? В php есть tuple? Можно ли написать, что-то типа:

select([("table1", "id"), ("table2", "name")]), имея ввиду "SELECT table1.id, table2.name"?

Всё равно уродливо выходит?

А, или это не надо? Если наш escape_string, не будет искейпить точки из имени, и оставлять table1.id неизменным -- это будет дырой для злоумышленной веб-макаки, которая намеренно пишет код, который содержит sql-injection, или нет?

Вложенные запросы реализуются элементарно, просто надо научить тип QueryBuilder принимать Query в качестве аргумента. Немного ООП, и QueryBuilder'у даже не надо будет знать, что он получил Query в качестве аргумента from, а не EscapedSqlString.


Да блин, хочешь я тебе сейчас прямо здесь напидаю простейшую реализацию? Я не буду парится на тему того, чтобы писать на пхп -- я его не помню, я псевдокодом.

Смотри.

Во-первых, метод для наших объектов. Если встроенным типам php возможно этот метод добавить, то надо его добавить им, и тогда все встроенные типы должны преобразовываться к String, после чего полностью экранироваться.

method sql_escape(self) -> EscapedString;

EscapedString тоже должна иметь этот метод:

function EscapedString::sql_escape(self) -> EscapedString {
    return self;
}

Затем мы пишем функцию:

function my_sql_escape(obj) -> EscapedString {
    if obj.has_method("sql_escape") {
        return obj.sql_escape();
    } elseif obj.has_method("to_string") /* or maybe object is a string */{
        // я подразумеваю здесь, что метод from реально экранирует всё
        return EscapedString::from(obj.to_string());
    } else {
        // может быть нам надо ещё какие-то типы обработать, скажем int или float, но мне лень
        panic("I'm a stupid programmer, who cannot into program");
    }
}

И дальше пишется
class Query {
    query: String,
}

пачка функций вида:

function Query::select(self, obj) -> Query {
    // только эти функции будут писать в self.query нативные php-строки,
    // это ограниченный объём кода, и его возможно проверить вручную глазами, чтобы тут
    // не писалось бы ничего глупого в запрос
    self.query.append("SELECT ");
    self.query.append(my_sql_escape(obj).to_string());
    self.query.append(" ");
    return self;
}

Чтобы Query можно было бы втыкать подзапросом:
function Query::sql_escape(self) -> EscapedString {
    // тут мы вернём EscapedString, которая будет содержать реально non-escaped string
    return EscapedString::from_string_unchecked(self.query);
}

С функциями типа less, or, and и тп, надо подумать как сделать. Надо ли тут создавать тип NaryFunCall, который будет хранить имя функции ("<", ">=", "or", "and"), аргументы и флаг infix_notation, чтобы все эти less/or/and сделать конструкторами этого типа? Или может надо сделать как-то ещё?

Но, в общем, это ТУПЕЙШАЯ реализация, и она даже получилась лучше, чем я ждал от такой реализации. Строку Query::query придётся перевыделять постоянно в процессе конкатенаций, но это вероятно можно обойти, предвыделив килобайт памяти под строку, и может быть даже хранить такую строку от запроса к запросу, чтобы не выделять её каждый раз снова, а потом не удалять.

Эта ТУПЕЙШАЯ реализация не проверяет SQL синтаксис, и позволяет генерить невалидные запросы, скажем, "WHERE hello FROM world". Более глубокая проверка потребует кучи дополнительных усилий. Но sql-injection здесь либо вырезана уже, либо её возможно вырезать. Опять же утверждать не возьмусь, поскольку язык для этого псевдокода я придумывал по ходу дела.

В ней есть ещё косяк, связанный с тем, что она легко может позволять ситуацию, когда одно и то же значение имеет несколько mutable ссылок. Может я зря беспокоюсь, а может и нет.

Ещё она создаёт лишние и ненужные копии строк. Вероятно это можно победить, как-нибудь, если прокидывать везде строку Query::query, в которую надо дописывать значения, вместо того, чтобы создавать их в куче и возвращать, чтобы они тут же были сконкатенированы с Query::query и выброшены в мусор.

Ответить | Правка | Наверх | Cообщить модератору

Оглавление
Опасные уязвимости в платформе электронной коммерции Magento , opennews, 28-Мрт-19, 23:09  [смотреть все]
Форумы | Темы | Пред. тема | След. тема



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру