The OpenNET Project / Index page

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



Индекс форумов
Составление сообщения

Исходное сообщение
"Опасные уязвимости в платформе электронной коммерции Magento..."
Отправлено Ordu, 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 и выброшены в мусор.

 

Ваше сообщение
Имя*:
EMail:
Для отправки ответов на email укажите знак ! перед адресом, например, !user@host.ru (!! - не показывать email).
Более тонкая настройка отправки ответов производится в профиле зарегистрированного участника форума.
Заголовок*:
Сообщение*:
  Введите код, изображенный на картинке: КОД
 
При общении не допускается: неуважительное отношение к собеседнику, хамство, унизительное обращение, ненормативная лексика, переход на личности, агрессивное поведение, обесценивание собеседника, провоцирование флейма голословными и заведомо ложными заявлениями. Не отвечайте на сообщения, явно нарушающие правила - удаляются не только сами нарушения, но и все ответы на них. Лог модерирования.



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

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