PDA

Просмотр полной версии : [Function] GenerateSalt - генератор случайно соли для хэширования



TheMallard
17.10.2018, 00:43
Описание:

Генерирует случайную соль для паролей из символов ASCII с 33 по 126 код.

Параметры:

buf[] - строка, в которую будет записана соль
len - длина строки (по умолчанию равно длине строки buf[])


Возвращаемое значение: длина строки

Код:


GenerateSalt(buf[], len = sizeof buf)
{
for(new i = 0; i < (len - 1); i++)
{
buf[i] = random(94) + 33;
if(buf[i] == '%')
buf[i] = '#';
}
buf[len - 1] = 0;
return len;
}



Пример использования:


new hash[64 + 1];
new salt[64 + 1];
GenerateSalt(salt);
SHA256_PassHash(inputtext, salt, hash, sizeof hash);



Автор: themallard

Daniel_Cortez
17.10.2018, 12:43
Во-первых, "Salt" - слишком простое название, которое не раскрывает сути работы функции. ИМХО, самым очевидным было бы "GenerateSalt".

Во-вторых, функция не записывает завершающий '\0', из-за чего строка не будет закончена правильно, если в массиве salt уже была строка, которая длиннее сгенерированной соли.
Пример:

Salt(salt[], len = sizeof salt)
{
for(new i = 0; i < len; i++)
{
salt[i] = random(94) + 33;
if(salt[i] == '%')
salt[i] = '#';
}
return;
}

main()
{
new str[] = "abcdefghijklmnopqrstuvwxyz";
Salt(str, 8);
print(str);
}

2sDM55zUijklmnopqrstuvwxyz

В-третьих, в чём смысл заменять "%" на "#"?

В-четвёртых, зачем в конце функции нужен return, если функция всё равно ничего не возвращает?

В-пятых, не лишним было бы сделать возврат длины получившейся строки, как в функциях SA-MP (к примеру, GetPlayerName (http://wiki.pro-pawn.ru/wiki/GetPlayerName) возвращает не только сам ник (косвенно, через массив), но и его длину).

TheMallard
19.10.2018, 00:01
Спасибо, я исправил ошибки.

По третьему замечанию: символ % может создать проблемы, если такая строка попадет в функцию format — то есть всегда, ведь мы обычно форматируем запрос в базу данных.

Daniel_Cortez
19.10.2018, 10:02
Спасибо, я исправил ошибки.
Не исправили, завершающий '\0' записывается по неправильному индексу (последний валидный индекс - это не "len", а "len - 1").

Да и функция всё так же названа "Salt" - должно быть очень сложно было переименовать её в предложенный выше вариант.
(Ни в коем случае не пытаюсь выглядеть слишком придирчивым, просто хочу понять вашу логику. Если предложенное мной название не понравилось и вы знаете вариант лучше, вместо игнорирования могли бы обосновать свой выбор - разве это сложно?)


По третьему замечанию: символ % может создать проблемы, если такая строка попадет в функцию format — то есть всегда, ведь мы обычно форматируем запрос в базу данных.
Даже если и так, "%" можно просто продублировать - format распознаёт спецификатор "%%", выводя одиночный знак "%".
http://wiki.pro-pawn.ru/wiki/%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D1%81%D1%82%D1%80%D0%BE%D0%BA

TheMallard
20.10.2018, 16:04
Исправил. Прошу исправить название темы.

// VVWVV: Готово

DeimoS
21.10.2018, 11:20
Только большого профита от функции нет. Скорее, только лишние траты ресурсов (как для генерации соли, так и для получения/хранения).

Проще и лучше в качестве соли использовать ник игрока, который известен ещё до отправки каких-либо запросов в базу. На выходе получится точно такая же уникальная соль, которая не даст использовать радужные таблицы, усложнив жизнь хацкерам, но, при этом, сведя все телодвижения при обработке пароля сервером к минимуму.

ziggi
21.10.2018, 15:39
Только большого профита от функции нет. Скорее, только лишние траты ресурсов (как для генерации соли, так и для получения/хранения).

Проще и лучше в качестве соли использовать ник игрока, который известен ещё до отправки каких-либо запросов в базу. На выходе получится точно такая же уникальная соль, которая не даст использовать радужные таблицы, усложнив жизнь хацкерам, но, при этом, сведя все телодвижения при обработке пароля сервером к минимуму.

Вот только станет невозможно изменить ник игроку без изменения пароля.

Kucklovod00
21.10.2018, 18:31
Вот только станет невозможно изменить ник игроку без изменения пароля.
Почему нет? Соль хранить можно отдельно, а там уже делай что угодно с ником.

ziggi
21.10.2018, 19:43
Почему нет? Соль хранить можно отдельно, а там уже делай что угодно с ником.

Соль и нужно хранить в отдельном поле. А мои слова относятся к цитируемому сообщению, которое, по всей видимости, ты не удосужился прочитать.

DeimoS
21.10.2018, 21:19
Вот только станет невозможно изменить ник игроку без изменения пароля.

Достаточно попросить игрока ввести повторно пароль под предлогом защиты, например (что, к слову, вполне разумно). Хотя далеко не на всех серверах есть возможность смены ника.

Да основной посыл в том, что можно использовать уже существующую постоянную и уникальную информацию в качестве соли (тот же ID аккаунта, например), а не плодить дополнительные поля.

DeimoS
21.10.2018, 21:52
Хотя, на самом деле, проблема кражи БД для SA-MP не особо актуальна. Каких-то архитектурных лазеек, которые позволили бы выкачать базу, нет, а в тех ситуациях, когда подбирают пароль к аккаунту на хостинге, никто обычно не париться с подбором хэшей даже без соли (по крайней мере я не припомню таких случаев).
Рандомная (или хотя бы статическая) соль, конечно, не будет лишней, но если вы действительно заботитесь о защите аккаунтов игроков, то лучше снабдите сервер рабочей системой привязки аккаунта к почте и добавьте Google Authenticator. Уже эти два простых шага принесут гораздо больше пользы, ибо шанс на кражу аккаунта гораздо более существенный со стороны самого игрока, нежели в случае доступа к базе.
Ну и заодно не давайте доступ к базе кому попало/устанавливайте нормальные пароли на хостинг, а не уповайте на хэширование и тому подобное (я не говорю, что хэширование не нужно. Но есть гораздо более оптимальные способы того, чтоб реализовать хэширование так, чтоб хацкеру трудно было понять даже то, используется ли соль или нет, при этом не тратя лишние ресурсы)

ziggi
21.10.2018, 22:09
Достаточно попросить игрока ввести повторно пароль под предлогом защиты, например (что, к слову, вполне разумно). Хотя далеко не на всех серверах есть возможность смены ника.

А если игрок оффлайн? Придётся ему установить другой пароль вручную.


Да основной посыл в том, что можно использовать уже существующую постоянную и уникальную информацию в качестве соли (тот же ID аккаунта, например), а не плодить дополнительные поля.

ID аккаунта слишком прост, как правило это обычное число, в качестве соли не годится. В дополнительном поле нет ничего плохого.


Хотя, на самом деле, проблема кражи БД для SA-MP не особо актуальна. Каких-то архитектурных лазеек, которые позволили бы выкачать базу, нет, а в тех ситуациях, когда подбирают пароль к аккаунту на хостинге, никто обычно не париться с подбором хэшей даже без соли (по крайней мере я не припомню таких случаев).

Уязвимость может быть, например, в сайте, который выводит статистику с БД.


Рандомная (или хотя бы статическая) соль, конечно, не будет лишней, но если вы действительно заботитесь о защите аккаунтов игроков, то лучше снабдите сервер рабочей системой привязки аккаунта к почте и добавьте Google Authenticator. Уже эти два простых шага принесут гораздо больше пользы, ибо шанс на кражу аккаунта гораздо более существенный со стороны самого игрока, нежели в случае доступа к базе.
Ну и заодно не давайте доступ к базе кому попало/устанавливайте нормальные пароли на хостинг, а не уповайте на хэширование и тому подобное (я не говорю, что хэширование не нужно. Но есть гораздо более оптимальные способы того, чтоб реализовать хэширование так, чтоб хацкеру трудно было понять даже то, используется ли соль или нет, при этом не тратя лишние ресурсы)

Нельзя просто установить хороший пароль на БД и думать, что ты теперь в безопасности. Уязвимость может быть на любом уровне информационной системы, вплоть до аппаратного. Поэтому и о возможном взломе нужно тоже позаботиться, и TOTP прикрутить, и отправку оповещений о входе через мессенджер, и логировать IP и дату каждого входа в аккаунт в отдельную таблицу с выключенными привилегиями на DELETE и UPDATE. Нужно применять все доступные на данный момент меры.

P.S. Утёкшая БД с открытыми паролями не так страшна для игроков самого сервера, как страшна для этих игроков на других серверах, ведь многие используют одни и те же пароли и ники на разных серверах и сайтах.

DeimoS
22.10.2018, 08:00
А если игрок оффлайн? Придётся ему установить другой пароль вручную.

Менять данные игрока без его ведома - такая себе затея. Как минимум, это не очень этично. Ну и крайне интересно то, как же ты потом игроку сообщишь его новый ник :)
И да, если уж на сервере так часто меняют ники, то, пока игрок онлайн, никто не запрещает сохранять "чистый" пароль в массив как раз на случай нужды перегенерации нового хэша.


ID аккаунта слишком прост, как правило это обычное число, в качестве соли не годится

Так а зачем сложность? Цель соли ведь не в том, чтоб сделать подбор пароля невозможным. Цель в том, чтоб заставить хацкера брутфорсить каждого конкретного пользователя, если вдруг ему в руки попадётся база данных. И ID в качестве соли с этим прекрасно справится, создавая уникальные хэши даже для игроков с одинаковыми паролями.
Ну а если ты про шанс того, что в словаре уже будет похожая комбинация, то и с рандомной солью шанс так же присутствует. К слову, под использованием ID я подразумевал хоть какой-то мало-мальский алгоритм, по типу: "ID+4V21+ID+пароль+ID". Хотя я всё же предпочитаю использовать ник для таких случаев, всячески его комбинируя с паролем и статичной солью.


Уязвимость может быть, например, в сайте, который выводит статистику с БД.

Речь шла именно про мультиплеер. Естественно, что при работе с сайтами нужно учитывать и их специфику.


Нельзя просто установить хороший пароль на БД и думать, что ты теперь в безопасности. ...

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


Утёкшая БД с открытыми паролями не так страшна для игроков самого сервера, как страшна для этих игроков на других серверах, ведь многие используют одни и те же пароли и ники на разных серверах и сайтах.

Опять же, где я хоть слово сказал о том, что пароли нужно хранить открыто?


Повторяю ещё раз: я не пытаюсь убедить кого-то, что хэширование или соль не нужны. Я говорю о том, что данная функция, в результате, не даст ничего такого, чего дало бы использование ника/ID/даты регистрации и т.п. в качестве соли. При этом, непонятно зачем в функцию запихали проверку на "%", когда можно было просто сместить диапазон доступных символов, исключив из него "%", и на выходе получить тот же результат, только без доп.проверки (будто бы те 3 символа, которые идут до "%", позволят лучше защитить аккаунты, в случае чего).


Как уже писал ранее, основная проблема SA-MP - кража данных со стороны самих игроков (стиллеры и т.п.). И игроки гораздо сильнее будут благодарны, если вы предоставите им возможность защитить аккаунт от несанкционированного входа путём дополнительных ступеней аутентификации, а не тем, что у вас генерируется 3 соли, которые потом особым образом перемешиваются с паролем, делая его максимально устойчивым к брутфорсу. В реалиях SA-MP слив базы - довольно редкое явление, в отличии от взлома игроков и слива всей валюты/имущества и т.п.

ziggi
22.10.2018, 10:40
Менять данные игрока без его ведома - такая себе затея. Как минимум, это не очень этично. Ну и крайне интересно то, как же ты потом игроку сообщишь его новый ник :)
И да, если уж на сервере так часто меняют ники, то, пока игрок онлайн, никто не запрещает сохранять "чистый" пароль в массив как раз на случай нужды перегенерации нового хэша.

Смена никнейма может быть доступна как функция UCP панели сервера, где игрок сам может воспользоваться функцией изменения ника за донат, например. Да и одинаковые никнеймы на некоторых серверах могут быть разрешены (через спец. плагины).


Речь шла именно про мультиплеер. Естественно, что при работе с сайтами нужно учитывать и их специфику.

Иметь UCP у сервера - это обычное дело, и в таких UCP могут быть уязвимости, обычное дело.


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

Окей, мне показалось иначе. И я дополнил список методов защиты.


Опять же, где я хоть слово сказал о том, что пароли нужно хранить открыто?

Это было адресовано самой теме, не тебе.


Так а зачем сложность? Цель соли ведь не в том, чтоб сделать подбор пароля невозможным. Цель в том, чтоб заставить хацкера брутфорсить каждого конкретного пользователя, если вдруг ему в руки попадётся база данных. И ID в качестве соли с этим прекрасно справится, создавая уникальные хэши даже для игроков с одинаковыми паролями.
Ну а если ты про шанс того, что в словаре уже будет похожая комбинация, то и с рандомной солью шанс так же присутствует. К слову, под использованием ID я подразумевал хоть какой-то мало-мальский алгоритм, по типу: "ID+4V21+ID+пароль+ID". Хотя я всё же предпочитаю использовать ник для таких случаев, всячески его комбинируя с паролем и статичной солью.

Просто для тебя сложностью является генерация рандомной строки с созданием поля, а для меня сложность - это оборачивание пароля в нечто вроде "ID+4V21+ID+пароль+ID", у каждого способа есть плюсы и минусы.


Повторяю ещё раз: я не пытаюсь убедить кого-то, что хэширование или соль не нужны. Я говорю о том, что данная функция, в результате, не даст ничего такого, чего дало бы использование ника/ID/даты регистрации и т.п. в качестве соли. При этом, непонятно зачем в функцию запихали проверку на "%", когда можно было просто сместить диапазон доступных символов, исключив из него "%", и на выходе получить тот же результат, только без доп.проверки (будто бы те 3 символа, которые идут до "%", позволят лучше защитить аккаунты, в случае чего).

Изначально совет был об использовании ника в качестве соли, а это может привести к проблемам при его изменении, о чём я и сообщил. ID - уже лучше, но тогда пароль нужно более серьёзно оборачивать, нежели стандартное "пароль+соль", которое даёт функция SHA256_PassHash. Просто я не понимаю, почему создание дополнительного поля в таблице для соли - это проблема для тебя.

DeimoS
24.10.2018, 15:53
Смена никнейма может быть доступна как функция UCP панели сервера, где игрок сам может воспользоваться функцией изменения ника за донат, например.

Если вход в UCP подразумевает ввод пароля от аккаунта, то можно либо заранее сохранить пароль в открытом виде, либо просто попросить игрока ввести пароль при смене ника (не понимаю почему ты видишь в этом большую проблему. Ники меняются не настолько часто, чтоб дополнительный ввод пароля создавал какие-либо неудобства для игроков. Да и безопасности для аккаунта это прибавит, ибо если игрок решит, например, дать поиграть другу/брату/свату, который пришёл к нему в гости, то этот друг/брат/сват не сможет сменить ник без ведома игрока)

А если пароль от UCP не связан с данными аккаунта, то тут тем более нужно требовать пароль перед какими-либо изменениями данных.


Да и одинаковые никнеймы на некоторых серверах могут быть разрешены (через спец. плагины).

Ну давай теперь в качестве доказательств приводить единичные случаи, ага -_-
Логично, что если ты решил использовать одинаковые никнеймы, то использовать ник в качестве соли не получится. Как не получится и многое другое, по типу работы с базой через ник и тому подобное. Соответственно, в этой ситуации ты будешь искать другие данные, по которым можно было бы идентифицировать конкретного игрока как на этапе авторизации, так и на этапе сохранения. И ничто не мешает использовать эти данные так же и для соли.


Иметь UCP у сервера - это обычное дело, и в таких UCP могут быть уязвимости, обычное дело.

Предоставил бы тогда хотя бы пару примеров того, как у каких-либо серверов вытаскивали БД через UCP. А то получается доказательство по типу: "Вот я сказал, а значит верь мне". Гипотетически можно и в хостинге найти уязвимость, получив доступ к другим серверам. Но такими темпами можно оправдать абсолютно всё. По факту же, гораздо проще загнать в какое-нибудь клео стиллер, позаливать это клео на кучу сайтов и получить кучу паролей без всех этих танцев с брутфорсом. А то, о чём ты говоришь - крайне дорогой процесс, который вряд ли себя окупит.


Просто для тебя сложностью является генерация рандомной строки с созданием поля, а для меня сложность - это оборачивание пароля в нечто вроде "ID+4V21+ID+пароль+ID", у каждого способа есть плюсы и минусы.

Ну вот только я не пытаюсь убедить тебя в том, что твой способ априори хуже моего, а вот ты постоянно пытаешься найти какие-то недостатки в предложенном мной способе, прибегая даже к преувеличениям и надумываниям, судя по тем же примерам с одинаковыми никнеймами и UCP.


Изначально совет был об использовании ника в качестве соли, а это может привести к проблемам при его изменении, о чём я и сообщил.

Проблемам, которые без проблем решаются кучей способов? С тем же успехом можно сказать, что генерация, хранение и получение соли при авторизации - тоже проблема метода, который предоставлен в данной теме, о чём я и говорил. И тут уже нужно сравнивать то, насколько часто ты будешь вынужден встречаться с той или иной "проблемой" (хотя это просто особенности работы разных реализаций).



Просто я не понимаю, почему создание дополнительного поля в таблице для соли - это проблема для тебя.

Проблемы тут пока видишь только ты :) А я лишь указываю на то, что создание поля для таблицы - это бессмысленно, с учётом других возможных реализаций, но не страшно. Хотя тут речь не просто о создании дополнительного поля, а о том, что с этим полем нужно так же работать, затрачивая и на это ресурсы. Ну и про то, что для поля нужно сначала данные сгенерировать. И это при том, что рядом есть уже "сгенерированное" уникальное поле, хранящее ник, содержимое которого нам известно ещё до обращения в базу данных.



Дабы опять не говорить про одно и то же по 10-му кругу, давай просто попробуем подвести итоги этого всего (я попробую начать, а ты можешь дополнить), а там каждый уже пусть сам для себя решает.

На одной чаше весов у нас есть вариант генерации рандомной* соли.
"Плюсы":

Пароль зависим от статичных данных, которые не изменятся по желанию игрока (как, например, ник)

"Минусы":

Нужно тратить дополнительные ресурсы на генерацию, хранение и получение соли.
Нет никакой уверенности в том, что у двух игроков с одинаковыми паролями не сгенерируется одинаковая соль (псевдорандом, всё же). Соль придётся делать довольно длинной, чтоб уменьшить риск повторов (хотя и это не будет панацеей).



На другой чаше весов у нас есть вариант с использованием ника (и/или его части) в качестве соли:
"Плюсы":

Не требуется генерировать, хранить или получать соль из базы (ник известен при входе игрока)
Человеку, получившему доступ к базе, придётся не просто брать соль из отдельного столбца, подбирать алгоритм генерации пароля и подбирать сам пароль, а тратить время ещё и на определения алгоритма генерации самой соли, что сыграет на улучшение устойчивости пароля к подбору (по факту, у нас просто получатся очень длинные и уникальные пароли, которые подобрать будет сложнее, чем перебор по алгоритму "известная соль+варианты разных паролей")
Мы можем быть уверены в том, что соль будет уникальной

"Минусы":

В случае смены никнейма, пароль потребуется генерировать заново (для этого можно либо попросить игрока ввести пароль перед сменой ника, либо просто хранить оригинальный пароль в памяти сервера всю сессию игрока. Оригинальный пароль, к слову, упростит и этап смены пароля, и другие действия, завязанные на аутентификации, так как не нужно будет хэшировать то, что ввёл игрок в качестве пароля, а можно сравнивать напрямую. Всё то же самое относится и к сайту/UCP)


Лично мне кажется, что вариант с ником гораздо более эффективный, ибо мы и данные лишние не храним, используя и без того уникальную строку, и лишний раз не требуется обращаться к базе, дабы получить соль, в случае чего, и дополнительно повышаем как защиту самого пароля к подбору, так и защиту аккаунта (ну если просим ввести игрока пароль при смене ника).


* Стоит понимать, что факт "рандомности" соли, по сути, ни на что не влияет. Соль, в первую очередь, используется для того, чтоб у двух игроков с паролем "123123" на выходе получались разные хэши, за счёт чего злоумышленник, подобравший пароль к одному аккаунту, не получал бы сразу доступ к другому, а подбирал пароль и для него. Какой бы сложной вы не сделали соль, пароль всё равно можно подобрать, если злоумышленнику известен алгоритм генерации пароля (а когда сравнивают алгоритмы хэширования, всегда отталкиваются от самой неудачной ситуации, которая как раз и гласит о том, что злоумышленнику алгоритм известен), так что "сложность" соли если и усложняет подбор пароля, то крайне слабо. Гораздо эффективнее использовать более медленные алгоритмы хэширования, по типу bcrypt, за счёт чего подбор одного пароля действительно будет и дольше, и труднее. Поэтому не думайте, что если у вас соль будет рандомная, то это гораздо лучше, чем, например, никнейм. Для соли главное - быть уникальной, с чем никнейм справится гораздо лучше, так как результатом работы данной функции всё же будет псевдорандомная (https://ru.wikipedia.org/wiki/%D0%93%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80_%D0%BF%D1%81%D0%B5%D0%B2%D0%B4%D0%BE%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D1%8B%D1%85_%D1%87%D0%B8%D1%81%D0%B5%D0%BB) строка, шанс уникальности которой стремительно уменьшается с уменьшением размера этой строки


UPD: В завершении хочу напомнить, что я никому не запрещаю использовать генерацию соли и не отговариваю никого от этого. Я лишь озвучил факт того, что есть и другие методы получения всё той же уникальной соли, только без вытекающих из метода, описанного в теме, последствий (хоть и не без своих особенностей). Но вы вольны использовать всё, что вашей душе угодно.

DeimoS
26.05.2019, 13:03
Функция не учитывает спецсимволы, которые могут поломать запросы.

Я предложил бы такой вариант функции:
GenerateSalt(buf[], len = sizeof(buf))
{
len -= 1;
for(new i = 0, c; i < len; i++)
{
switch((c = random(94)+33))
{
case '%', '\'', '\\':
{
buf[i] = c+1;
}
default:
{
buf[i] = c;
}
}
}
buf[len] = 0;
return len;
}

Daniel_Cortez
26.05.2019, 18:27
Функция не учитывает спецсимволы, которые могут поломать запросы.
Разве использование mysql_format() не исключает возможность для подобных атак априори? Или то расчёт на быд тех, кто не пользуется той функцией (по причине лени или просто из принципа - неважно)?

DeimoS
26.05.2019, 18:43
Разве использование mysql_format() не исключает возможность для подобных атак априори? Или то расчёт на быд тех, кто не пользуется той функцией (по причине лени или просто из принципа - неважно)?

mysql_format - нет.
mysql_format + "%e" - да (хотя format + "%q" будет шустрее и результат, при этом, будет тем же)

Но гораздо лучше просто исключить возможность использования нескольких спец-символов (по сути, это только апостроф и обратный слеш). Иначе, если строку нужно сравнивать с какими-то данными в будущем, то придётся и эти данные каждый раз обрабатывать (то бишь, в случае с паролем, на экранирование придётся тратить время каждую проверку). Уж лучше потерять 2 символа, как мне кажется.

Хотя тут ещё зависит от того, как реализована система аккаунтов. Если сверка пароля происходит уже на стороне сервера, а не в запросе к таблице, то "проблем" с экранированием не будет.

execution
27.05.2019, 11:17
mysql_format - нет.
mysql_format + "%e" - да (хотя format + "%q" будет шустрее и результат, при этом, будет тем же)

Но гораздо лучше просто исключить возможность использования нескольких спец-символов (по сути, это только апостроф и обратный слеш). Иначе, если строку нужно сравнивать с какими-то данными в будущем, то придётся и эти данные каждый раз обрабатывать (то бишь, в случае с паролем, на экранирование придётся тратить время каждую проверку). Уж лучше потерять 2 символа, как мне кажется.

Хотя тут ещё зависит от того, как реализована система аккаунтов. Если сверка пароля происходит уже на стороне сервера, а не в запросе к таблице, то "проблем" с экранированием не будет.

Значит выгоднее использовать вместо mysq_format + %e -> format + %q? Это в определенных случаях или всегда можно?

DeimoS
27.05.2019, 13:09
Значит выгоднее использовать вместо mysq_format + %e -> format + %q? Это в определенных случаях или всегда можно?

В определённых. Спецификатор "%q" не экранирует обратный слеш. Из-за этого SQL-инъекции не случится, но либо данные могут подпортиться, либо запрос целиком не сработает (зависит от того, где будет стоять слеш и что за запрос).

Daniel_Cortez
27.05.2019, 16:34
mysql_format - нет.
mysql_format + "%e" - да (хотя format + "%q" будет шустрее и результат, при этом, будет тем же)
Ну всё-таки подход с format() больше применим при использовании SQLite, а не MySQL. Если пользоваться инструментами которые как бы выполняют как бы ту же работу как бы похожим образом, такой подход рано или поздно становится источником багов. На сайтах с новостями по IT-шной тематике то и дело пишут, как в таком-то проекте исправлена такой-то баг или уязвимость, возникшая из-за использования ненадлежащей функции из не имеющего отношения к решаемой задаче фреймворка.

Да и в реализации функции у тебя тоже небольшой изъян: если случайно выпадает один из "опасных" символов, вместо него выбирается один из следующих ('\"', '(', ']'), из-за чего вероятность возникновения этих трёх символов в строке становится в 2 раза больше, т.е. символы распределяются неравномерно.
Равномерную выборку можно сделать примерно так:

GenerateSalt(buf[], len = sizeof(buf))
{
--len;
for (new i = 0, c; i < len; i++)
{
c = 33 + random(94 - 3);
c += _:(c >= '%') + _:(c >= '\'') + _:(c >= '\\');
}
buf[len] = '\0';
return len;
}

DeimoS
28.05.2019, 05:43
Ну всё-таки подход с format() больше применим при использовании SQLite, а не MySQL. Если пользоваться инструментами которые как бы выполняют как бы ту же работу как бы похожим образом, такой подход рано или поздно становится источником багов. На сайтах с новостями по IT-шной тематике то и дело пишут, как в таком-то проекте исправлена такой-то баг или уязвимость, возникшая из-за использования ненадлежащей функции из не имеющего отношения к решаемой задаче фреймворка.

Я понимаю о чём ты говоришь, но в данном случае обе функции выполняют практически идентичную работу (если не считать того изъяна со слешем, о котором писал выше), но format, при этом, будет работать шустрее. Это как вместо кастомной функции PlayerToPoint пользоваться IsPlayerInRangeOfPoint, ибо суть одна, но нативка работает быстрее.
Хотя я не призываю переходить на format. Как я выше сказал, у format есть своя не очень приятная особенность, которую нужно учитывать при написании кода. Просто изменить mysql_format на format не получится.

Ну и как ранее писал, я предпочитаю просто запрещать использование апострофа/слеша там, где это возможно. Это позволяет не заморачиваться с контролем данных в дальнейшем. Но и тут, опять же, всё нужно делать с умом.



Да и в реализации функции у тебя тоже небольшой изъян: если случайно выпадает один из "опасных" символов, вместо него выбирается один из следующих ('\"', '(', ']'), из-за чего вероятность возникновения этих трёх символов в строке становится в 2 раза больше, т.е. символы распределяются неравномерно.
Равномерную выборку можно сделать примерно так:

GenerateSalt(buf[], len = sizeof(buf))
{
--len;
for (new i = 0, c; i < len; i++)
{
c = 33 + random(94 - 3);
c += _:(c >= '%') + _:(c >= '\'') + _:(c >= '\\');
}
buf[len] = '\0';
return len;
}


Только проблем от повышения вероятности выпадения символов никаких не будет :) Шанс генерации двух одинаковых строк повысится несущественно (конечно, зависит от количества символов) и соль, в любом случае, будет выполнять свою функцию.
Хотя хуже не станет от такой реализации, соглашусь.