PDA

Просмотр полной версии : [Вопрос] Своеобразная система безопасности



Elrmrnt-Kritik
27.03.2018, 22:35
Нашел в исходниках MySQL такую вещь:


forward OnPlayerDataLoaded(playerid, race_check);
public OnPlayerDataLoaded(playerid, race_check)
{
/* race condition check:
player A connects -> SELECT query is fired -> this query takes very long
while the query is still processing, player A with playerid 2 disconnects
player B joins now with playerid 2 -> our laggy SELECT query is finally finished, but for the wrong player
what do we do against it?
we create a connection count for each playerid and increase it everytime the playerid connects or disconnects
we also pass the current value of the connection count to our OnPlayerDataLoaded callback
then we check if current connection count is the same as connection count we passed to the callback
if yes, everything is okay, if not, we just kick the player
*/
if (race_check != g_MysqlRaceCheck[playerid]) return Kick(playerid);


Действительно ли стоит создавать такие проверки? Если да, когда?

DeimoS
28.03.2018, 09:22
Эмм, ну так написано же там, что при подключении. И так же описана ситуация, из-за которой такая проверка будет актуальной.

Elrmrnt-Kritik
28.03.2018, 10:49
Просто эту проверку мало где можно встретить. Я и интересуюсь, нужна ли.

DeimoS
28.03.2018, 11:26
Это просто перестраховка от гипотетической ситуации. На деле, если таблица и запросы реализованы нормально, задержек между ними не должно хватить для того, чтоб один игрок успел отключиться, а второй подключиться на его слот. Но и лишней такая проверка не будет, дабы просто закрыть возможную уязвимость

$continue$
28.03.2018, 12:14
Это не совсем уязвимость, а ошибка проектирования ПО. Гонка потоков (https://ru.m.wikipedia.org/wiki/%D0%A1%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%B3%D0%BE%D0%BD%D0%BA%D0%B8). Т.к плагин использует потоки, есть вероятность, что 2 поток, выполнится быстрей первого. Обычно в C++ это решают, через srd::mutex_lock

DeimoS
28.03.2018, 12:26
Это не совсем уязвимость, а ошибка проектирование ПО Гонка потоков (https://ru.m.wikipedia.org/wiki/%D0%A1%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%B3%D0%BE%D0%BD%D0BA%D0%B8). Т.к плагин использует потоки, есть вероятность, что 2 поток, выполнится бысстрей первого.

Ошибка проектирования так же становится уязвимостью :) И ты сказал то же самое, что и я написал выше
+ссылка битая

$continue$
28.03.2018, 12:32
Изначально это ошибка проектирование, которая в последствии может превратиться в ошибку безопасности ПО. А может и не превратиться :)

DeimoS
28.03.2018, 12:40
Изначально это ошибка проектирование, которая в последствии может превратиться в ошибку безопасности ПО. А может и не превратиться :)

Эмм, ты сам понимаешь о чём говоришь? По твоей логике, если имеется возможность провести SQL инъекцию, но ей никто не пользуется, то это вовсе не уязвимость.

*тут я начал тебе объяснять, что же является уязвимостью, но потом понял, что проще так же дать ссылку на статью из википедии*

Собственно, вот статья (https://ru.wikipedia.org/wiki/%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D1%8C_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C))

Цитата:

В компьютерной безопасности термин «уязвимость» используется для обозначения недостатка в системе, используя который можно намеренно нарушить её целостность и вызвать неправильную работу. Уязвимость может быть результатом ошибок программирования, недостатков, допущенных при проектировании системы, ненадежных паролей, вирусов и других вредоносных программ, скриптовых и SQL-инъекций.

Daniel_Cortez
28.03.2018, 12:40
Изначально это ошибка проектирование
Во-первых, научись уже склонять, "ошибка проектирования".
Во-вторых, в чём именно ошибка? В том, что плагин позволяет делать запросы в отдельном потоке, не подвешивая основной?

DeimoS
28.03.2018, 12:46
Во-первых, научись уже склонять, "ошибка проектирования".
Во-вторых, в чём именно ошибка? В том, что плагин позволяет делать запросы в отдельном потоке, не подвешивая основной?

Если я правильно понимаю его мысль, то под ошибкой проектирования он подразумевает именно отсутствие той проверки, из-за которой запрос одного игрока может сработать на другом, если тот успеет зайти под тем же ID.
А иначе никак подобный баг не спровоцировать, ибо кэш запросов привязан к ID (ну либо к любым другим параметрам паблика, который указывается для обработки результата запроса) и 2 запроса от разных игроков никак не смогут перебить друг друга.

$continue$
28.03.2018, 13:04
Я с телефона. На андройде есть "болезнь", автозамена слов. Как раз оно и сработало.

На счёт второго: Ну есть поток 1, есть поток 2, нельзя предугадать какой выполнится первым

DeimoS
28.03.2018, 13:59
На счёт второго: Ну есть поток 1, есть поток 2, нельзя предугадать какой выполнится первый.

Это не работает на запросах, связанных с аккаунтами игроков. Как я уже сказал, каждый результат запроса "привязан" к ID игрока (именно для того ты и передаёшь "playerid" в mysql_tuery). Точнее, передавая ID, мы понимаем для какого игрока какой результат обрабатывать.


Единственная уязвимость в этом случае - если один игрок отправит запрос на загрузку данных и выйдет с сервера, а другой игрок в этот момент зайдёт на слот первого игрока и результат запроса придёт только к этому моменту. Собственно, получится, что данные одного игрока сработали на другом и то условие, что показал автор, как раз защищает от этого.
Защита происходит за счёт того, что мы контролируем количество срабатываний OnPlayerConnect для каждого ID игрока, прибавляя каждый раз единицу к переменной и передавая это значение в наш паблик для обработки запроса, указывая его вместе с playerid в mysql_tquery. Далее, когда запрос сработал, мы проверяем, равны ли текущее значение переменной и то значение, что мы передали. Если нет, значит под тот ID игрока, который отправил запрос, во время обработки запроса успел зайти другой игрок.
То бишь:

Игрок зашёл на сервер, сработал OnPlayerConnect и к переменной прибавилась единица (сейчас значение равно "1")
Запрос отправился, а в паблик, созданный для обработки запроса, был передан ID игрока и значение переменной (1)
Далее игрок выходит с сервера, не додидаясь результата запроса
Заходит другой игрок под тот же ID и значение переменной уже становится равным "2"
Запрос, который отправил первый игрок, наконец, обрабатывается и переданное значение сравнивается с текущим значением переменной (в данном случае у тас будет "1" и "2")
...
PROFIT!!!

Вот так мы и поймём, что запрос отправлял не тот игрок

Но такое возможно только в случае, если запрос будет обрабатываться достаточно долго, о чём даже в комментарии написано:

player A connects -> SELECT query is fired -> this query takes very long
while the query is still processing, player A with playerid 2 disconnects
player B joins now with playerid 2 -> our laggy SELECT query is finally finished, but for the wrong player
what do we do against it?
we create a connection count for each playerid and increase it everytime the playerid connects or disconnects
we also pass the current value of the connection count to our OnPlayerDataLoaded callback
then we check if current connection count is the same as connection count we passed to the callback
if yes, everything is okay, if not, we just kick the player
Собственно, в этом комментарии как раз и описан принцип работы сей уязвимости

UPD: Вангую в ответ что-то типа: "Я и так всё это знал. Зачем ты мне это расписывал". Я описывал это не только для тебя, а для автора и всех остальных, кому интересно как это работает.

$continue$
28.03.2018, 14:47
Так, гонка потоков не только в плагине. Я объяснил, что есть такая ситуация и зачем BlueG сделал переменную.

Я же не говорил, обязательно использую доп.переменную. К слову, я сам не использую в запросах :)

DeimoS
28.03.2018, 15:06
Так, гонка потоков не только в плагине. Я объяснил, что есть такая ситуация и зачем BlueG сделал переменную.

Эмм, а кто сказал, что гонка потоков есть только в плагине?
Речь о том, что принцип появления ошибки нельзя описать как:

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

Elrmrnt-Kritik
28.03.2018, 16:45
Спасибо большое за очередную отзывчивость и помощь. В этом вопросе в принципе разобрался. Лишней не будет эта штука, добавлю. Хотя и вправду, навряд ли так быстро игроки могут успеть зайти.
Правда не понял из-за чего у вас сыр-бор, в драку влезать не буду :mosking:

$continue$
28.03.2018, 16:45
И почему же? Я не люблю расписывать на 200500 страниц как ты. У меня есть личные дела, которые я ещё решаю + я был с телефона)

Речь о том, что принцип появления ошибки нельзя описать как:

DeimoS
28.03.2018, 17:54
И почему же?

Я же написал причину выше, ну -_-

Окей. Обратимся к википедии:

Состояние гонки (англ. race condition), также конкуренция — ошибка проектирования многопоточной системы или приложения, при которой работа системы или приложения зависит от того, в каком порядке выполняются части кода.

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



Я не люблю расписывать на 200500 страниц как ты. У меня есть личные дела, которые я ещё решаю + я был с телефона)

Эмм, а это к чему?
Я, например, не люблю писать с ошибками и если делаю какие-то ошибки, которые впоследствии замечаю сам или подмечают другие, стараюсь от них избавляться. Все мы не без греха :pardon:

$continue$
28.03.2018, 23:05
Лол. Так это и есть. Нельзя предугадать в каком порядке выполнятся поток (какой первый придет). Что я не так сказал? Я, что-то не пойму.


зависит от того, в каком порядке выполняются части кода.

DeimoS
29.03.2018, 09:16
И правда, лол.
Пойми же ты, гонку потоков определяет не только следствие, но и причина. Обычно под гонкой потоков принято называть случаи, когда несколько работают одновременно с одной и той же информацией, при этом, хотя бы один из потоков должен эту информацию обновлять, из-за чего все остальные потоки, в лучшем случае, будут получать уже устаревшие данные. И чем больше потоков делает перезапись, тем больше коллизий данных происходит. То, что в нашем случае в определении ситуации присутствует слово "потоки", не делает всю ситуацию равноценной гонкам потоков.

Давай попробуем пойти от обратного и, опять же, обратится к сторонним источникам.
Википедия: (https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%B3%D0%BE%D0%BD%D0%BA%D0%B8)

Состояние гонки (англ. race condition), также конкуренция — ошибка проектирования многопоточной системы или приложения, при которой работа системы или приложения зависит от того, в каком порядке выполняются части кода.

studexpo.ru (https://studexpo.ru/5947/informatsionnye_tehnologii/kollizii_voznikayuschie_ispolzovanii_potokov)

Одной из основных ошибок в многопоточных программах является так называемое состояние гонки (race condition). Это случается, если программист считает, что один поток закончит выполнение своих действий, например, подготовку каких-либо данных, до того, как эти данные потребуются другому потоку.

www.viva64.com (https://www.viva64.com/ru/t/0042/)

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

support.microsoft.com (https://support.microsoft.com/ru-ru/help/317723/description-of-race-conditions-and-deadlocks)

Состояние гонки возникает, когда два потока доступа к общей переменной в то же время. Оба потока считывают одно и тоже значение переменной. Оба потока производят какие-либо действия со значением и далее возникает гонка за то, кто последним сможет записать новое значение. Поток, который запишет значение последним перезапишет значение, которое записал предыдущий поток.


Видишь? Везде говорится о том, что гонка потоков возникает, когда НЕСКОЛЬКО ПОТОКОВ ОДНОВРЕМЕННО РАБОТАЮТ С ОБЩИМИ ДАННЫМИ. В этом главная суть гонки потоков. Имеется несколько независимых потоков, которые могут влиять на какие-то одни данные, что и приводит к проблемам.

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


Хотя я, кажется, понимаю в чём именно заключается причина твоего заблуждения. Ты говоришь именно о потоках, в которых отправляются запросы, да? Мол считаешь, что может случится ситуация, при которой поток от вышедшего игрока будет обрабатываться медленнее, чем от только зашедшего? Только в этой ситуации я вижу хоть какое-то подобие гонки потоков (хотя, опять же, это не она, ибо отсутствует главный показатель: влияние одного потока на те данные, с которыми работает другой поток). Но такое просто физически невозможно, ибо если БД долго обрабатывает запрос одного пользователя, то логично, что проблема именно в запросе/таблице и все последующие запросы будут обрабатываться так же долго.
Хотя если даже представить, что такая ситуация возможна, то игрока всё равно кикнет, когда первый запрос всё же обработается, ибо проверка всё равно сработает. Так что я не совсем понимаю какой логикой ты руководствуешься

$continue$
29.03.2018, 11:02
* Многобукаф *

И все равно , до чего ты докапался и пытаешься другими, более развернутыми словами, что-то доказать?


Ты писал thread приложения?

DeimoS
29.03.2018, 11:18
https://www.blogcdn.com/wow.joystiq.com/media/2010/09/facepalm.jpg

Вот если бы ты не ленился читать "многобукафные" статьи, то не нёс бы чушь сейчас.

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

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