Проблема:
Есть голосование, на странице рандомно появляется несколько вариантов ответа. В БД их очень много. Эти варианты постоянно меняются и у каждого есть свой идентификатор. В сессию записывается md5 хэш сформированный из зайди выведенных на страницу вариантов+соль. При отправке данных на сервер, скрипт получает все эти айди, формирует из них хэш и сверяет с записанным в сессию. Т.е. простая подмена айди при отправке данных на сервер не пройдет. Но, теоретически, злоумышленник может запомнит все айди из прошлого голосования, запомнить какой при них выдавался хэш и при следующем обновлении страницы, подменит все эти айди и подменить в сессии хэш, так что голосование снова пройдет проверку.
Вопрос:
Как от этого можно защититься? Авторизацию не предлагать, голосование открыто для всех. Думал дополнительную какую-инку в куки сохранять, но опять же, можно все подменить. Или может как-то динамический хэш сделать? Чтоб всегда разный получался? И как это лучше сделать? В общем, жду совета.
Через Flash-приложение формируете хэш (ваш ключ, сессия, IP, capabilites и прочее) и сверяете на сервере.
Декомпилировать можно, конечно, но уже меньше будет ложных срабатываний и "накруток" голосов.
злоумышленник может запомнит все айди из прошлого голосования
уникальный ID формируете и хеш для каждого голосования и нет проблем.
Экстра!: Блокировка голосовавших IP+DNS - должна помочь.
Спасибо за ответ, но с флешем не знаком и не думаю, что стоит с ним разбираться ради этого. По-сути, чтобы уникальные айди формировать, надо записывать эти временные данных в бд, после чего очищать через некоторое время, если не были использованы. Обращений к странице голосования очень много, может куча мусора постоянно копиться, т.к. пользователь может зайти на страницу, варианты ответа появятся, сессия создастся, все эт дело запишется в бд, но сам пользователь может не голосовать и уйти со страницы. Запариваться над этим не охота. Айпи+Днс - в процессе голосования пользователю теоретически могут иногда выпадать те же вариантов ответа, которые уже когда то выпадали. Так что этот вариант не подходит.
Хеш в сессии он никак не сможет подменить, максимум сменить id сессию на другого пользователя, просто сверяйте пришедшие к вам данные (сделайте уникальное имя в каждом чекбоксе) со страницы с теми которые хранятся в сессии (пусть даже те же уникальные имена или их хеш), если совпадают то записывайте результат, если нет то нет. Но всегда удаляйте данные из сессии после валидации.
xmoonlight: У меня на сервере в сессии хранится список показанных вам вариантов ответов к голосованию, + в базе история по вашему user_id и показанным вам вариантам. Как вы сможете меня накрутить?
xmoonlight: ID пользователя сайта, если проводить голосование на не авторизированных пользователях, то никакой гарантии от накручивания не существует. Ведь у нас может быть целая армия ботнетов.
xmoonlight: Ну создадите вы новую сессию, а то что вам уже показывались те или иные варианты (история) хранятся в базе. Так что два раза одному и тому же пользователю не будет выведены теже варианты.
Спасибо за ответ. В общем, объясняю как работает. Пользователь заходит на страницу, ему показаны два варианта ответа, выбраны из огромной бд абсолютно рандомно. Каждый со своим айди. Первый например имеет айди 25, второй 340. Зная, что мы показали именно эти два варианта, я формирую хэш md5(соль+ айди_первого (25) + айди второго (340) + соль) и записываю все это дело в $_SESSION['idsess'], например. Когда человек проголосовал, мне отправляются эти два варианта, я их ставлю в том порядке, в котором формировал хэш, снова все это дело составляю через md5(соль + айди_первого_полученного + айди второго_полученного + соль) и сравниваю с записанным значением в $_SESSION['idsess']. Если равны, результаты приняты и голосование проходит, выдавая новые два варианта пользователю на странице и соответственно переписывая сессию по алгоритму описанному выше.
Я так понял, что данные записанные в $_SESSION сохраняются в куках, либо если те отключены - в адресной строке, так что по сути, можно запомнить какой айди сессии был при вариантах с айди 25 и 340, в результате можно все эти значения подставлять постоянно заново и отправлять на сервер, так что проверка всегда будет проходить. Или все таки на значение в $_SESSION никак повлиять нельзя и я эту тему не совсем правильно понял?
Максон: массив $_SESSION[] хранится на сервере, в куках браузера автоматом формируется id-сессии при её запросе сервером. Если нужно сохранить у пользователя - делается это через setcookies().
рандомно 2 варианта ответа - а почему рандомно?
у меня есть подобная голосовалка:
я делал линки: /?left и /?right
проверку: isset($_GET['left']) и isset($_GET['right'])
ну а на сервере я точно знаю что есть left, а что - right
xmoonlight: все, понял! просто неправильно с принципом работы сессии разобрался. Сделаю как вы предложили, это даже код упросит порядочно и в принципе как-то повлиять и подсунуть свои данные будет невозможно. На всякий случай, распишу как сделаю, если что-то не так понял, поправите.
Когда пользователь попадает на сайт, ему присваивается уникальный айди сессии, который сохраняется в куках. Если я в $_SESSION записываю какие-то данные, то они относятся именно к тому айди, который присвоен зашедшему человеку и хранятся у меня на сервере. Когда этот человек обращается к какой-то странице сайта, на которой открывается сессия, то сервер получает записанный в куках айди этой сессии и соответственно после этого можно из $_SESSION извлекать данные, которые относятся к этому айди. Человек эти данные получить никак не может. Правильно?
Так что если я буду отправлять только left или right, как Вы написали, а дальше сверять со своими данными, записанными в переменные сессии на сервере, то накрутить это дело никак не получится.
xmoonlight: Большое спасибо за помощь! Собственно упомянутые проблемы решены, уже переписал код. Теперь все работает гораздо проще и надежнее чем раньше.
Да ничто вам не поможет. Если кто-то захочет накрутить голосование, он это сделает, чтобы вы там не изобретали. Единственный более-менее вариант это привязка к IP, т.к. его теоретически сложнее всего менять, все остальные значения легко подделываются в запросах.
Просто посмотрите на все заголовки и параметры в запросе и подумайте, насколько легко менять тот или иной, чтобы пользователь выглядел как новый/старый