PDA

Просмотр полной версии : [Вконтакте] Защита! Инъекции! auth_key! Как защитить проект?


Azo
17.02.2012, 10:53
Вот и научились создавать приложения. А защитить его не научились.
Перечислю несколько методов защиты и ниже напишу почему этого не достаточно.
Нужна помощь!

1
например получаем число переданное от прила на сервер в пхп
Не правильно - $num=$_POST["num"];
Правильно - $num=(int)$_POST["num"];


например получаем текст типа имени пользователя или другого размером до 10 символов
Не правильно - $name=$_POST["name"];
Правильно - $name=substr($_POST["name"],0,10);


// и тогда злоумышленники не смогут запихать в переменную целые строчки кода типа AND DELETE FROM table



2
передаем серверу значение viewer_id, auth_key
в скрипте должны присудствовать заранее переменные api_id, secret
И проверяем if ($auth_key=md5($viewer_id."_".$api_id."_".$secret)) то пропускаем , иначе блокируем запрос



3
Есть третий вариант защиты , он пока для меня самый действенный и 100% защищающий (если не учитывать возможность декомпиляции приложения)
Действенный то он и действенный но его считаю как "экспериментальны" так как требует лишней таблицы в mysql для хранения ключей

Я на сервере создал табличку с полями ид пользователья, время запроса, рандомное число
А в приложении создал класс который хеширует(свой алгоритм) секретное_слово+","+random()*1000000
И с каждым запросом отправляет на сервер...
Сервер дехеширует и делает split. То есть разделяет на 2 части получая : секретное слово и рандом.
Ид, Времья и рандом записывается в табличку
А теперь фокус:
Если секрет правильный то
И если в табличке не было такого рандома от такого этого user_id за последний ЧАС, то пропускаем.
Иначе: die("код не уникален");

Фишка 3го способа в том что для каждого пользователя и для каждого запроса к серверу от этого пользователя будут уникальные ключи и 2 раза по одному и тому же ключу не пропустим. В отличаи от auth_key, где пользователь изначально может узнать этот код в исходном коде страницы и от лица себя может делать сколько угодно запросов. Да, он не знает authkey других пользователей и поэтому не может повлеять на числа других.. Но может например поднять свой рейтинг в приложении, увидев один раз какой auth_key и viewer_id отправляется




Поэтому вопрос к тем кто уже одолел этот вопрс:
КАК ДОСТИЧЬ ТАКОГО УРОВНЯ ЗАЩИТЫ КАК В п.3 без всяких записей в базу и лишьших запросов mysql...?

Psycho Tiger
17.02.2012, 12:13
он пока для меня самый действенный и 100% защищающий (если не учитывать возможность декомпиляции приложения)
А для меня это самый смешной алгоритм, потому что я могу декомпилировать приложение.
Но может например поднять свой рейтинг в приложении, увидев один раз какой auth_key и viewer_id отправляется
Значит, не стоит хранить их на БД вконтакте.

Genzo
17.02.2012, 12:31
1 - защита от SQL-инъекций - должна быть всегда
2 - самый нормальный способ "псевдо-авторизации", а не способ защиты приложения, просто без этого действия не отловить уникальность пользователя.
3 - слишком заморочено и не защищено на 100%.

не нужно изобретать велосипед, используйте 1,2 и будет вам счастье.

Azo
18.02.2012, 02:38
Да но что такое псевдо авторизация и как ее делать?

incoob
13.03.2012, 19:54
например получаем текст типа имени пользователя или другого размером до 10 символов
Не правильно - $name=$_POST["name"];
Правильно - $name=substr($_POST["name"],0,10);


// и тогда злоумышленники не смогут запихать в переменную целые строчки кода типа AND DELETE FROM table


Посмотрите на функцию mysql_real_escape_string (http://docs.php.net/manual/en/function.mysql-real-escape-string.php). Вроде обычно ее используют для предотвращения инъекций.

Андрей911
19.03.2012, 16:00
Если Вы верите что флеш не декомпилируеют, то 3 вариант можно упростить и сделать вообще без таблицы.
Делайте хеш не со случайным числом, а с текущим серверным временем.
Передайте пользователю при старте приложения серверное время и там запустите таймер. При выполнении запроса передавайте и время когда он сделан. Время можно передавать открыто, так как алгоритм хеширования неизвестен. И если |Время на сервере - время на клиенте|> 3 сек, то запрос уже был.

Добавлено через 2 минуты
3 секунды - это на вскидку максимум сколько пройдет от момента отправки текущего времени сервером, до получения его клиентом

Добавлено через 14 часов 31 минуту
Кстати, на счет например получаем число переданное от прила на сервер в пхп
Не правильно - $num=$_POST["num"];
Правильно - $num=(int)$_POST["num"];

Если в num передается 100% число, а пришло не число, то значит запрос левый и правильнее

if(!is_numeric($_POST["num"])) die("Положительный ответ сервера. Типа молодец чувак у тебя получилось записать мне что-то в БД");

Azo
21.03.2012, 19:19
в том то и дело что за 1 секунду можно успеть 100 запросов. это не выход!

Андрей911
21.03.2012, 20:43
Ну тогда можно запоминать в таблице последнее значение времени запроса (в миллисекундах с 1970) и проверять, чтобы каждое следующее было строго больше предыдущего.
Получится по одной ячейке в БД на пользователя, а не на каждый запрос

udaaff
21.03.2012, 21:03
Если не учитывать возможность декомпиляции приложения, то достаточно передавать в запросе хэш(данные + секретный ключ), а на сервере вычислять этот же хэш и сверять с полученным. Или зачем столько телодвижений по третьему пункту?
Многое от приложения зависит.

Андрей911
22.03.2012, 09:11
если просто хэш(данные + секретный ключ), то можно перехватить запрос и отправить его еще 100 раз. А если там например покупка, то таким образом можно заплатить один раз, а купить 100.
Это конечно вопрос реализации и можно продумать приложения так чтобы повторный запрос не принес никакой выгоды пользователю. Ну а если выгода есть, то нужно как-то различать одинаковые запросы по времени, это менее затратно, чем хранить данные о каждом запросе и отправлять их со случайным числом.

Psycho Tiger
22.03.2012, 16:20
Клиент-сервер:
На клиент передается некоторый сессионный ключ. В открытом виде. И, например, userID.
При каждом запросе на сервер передается как userID, так и ключ. Происходит проверка, совпадает ли ключ для этого userID'a. Если нет - ошибка. Таким образом человек может делать покупки только от своего userID'a, т.к. ключ сессии для другого userID'а ему не получить никак.
Да, запрос покупки можно перехватить. И отправить его ещё 100 раз. Но это будет эквивалентно, если бы человек решил купить эту вещь 100 раз и с клиента.

Клиент-соцсеть:
Защиты никакой. Можно отправить любой запрос на всё что угодно. Поэтому запросы к соц. сети должны быть чисто информационными. Например, узнать список друзей.

Сервер-соцсеть:
Есть специальный секретный ключ для транзакций (обычно называют солью), который доступен только серверу и администратору приложения. С сервера его не получить никак - он зашит в скриптах сервера, и из контакта никак - меняется и виден только из админки. Вот он и является верификацией. Обычно используют с приблудами - вычисляют MD5 от соединения разных параметров и него.

Azo
23.03.2012, 23:29
Клиент-сервер:
На клиент передается некоторый сессионный ключ. В открытом виде. И, например, userID.
При каждом запросе на сервер передается как userID, так и ключ. Происходит проверка, совпадает ли ключ для этого userID'a. Если нет - ошибка. Таким образом человек может делать покупки только от своего userID'a, т.к. ключ сессии для другого userID'а ему не получить никак.
Да, запрос покупки можно перехватить. И отправить его ещё 100 раз. Но это будет эквивалентно, если бы человек решил купить эту вещь 100 раз и с клиента.

Клиент-соцсеть:
Защиты никакой. Можно отправить любой запрос на всё что угодно. Поэтому запросы к соц. сети должны быть чисто информационными. Например, узнать список друзей.

Сервер-соцсеть:
Есть специальный секретный ключ для транзакций (обычно называют солью), который доступен только серверу и администратору приложения. С сервера его не получить никак - он зашит в скриптах сервера, и из контакта никак - меняется и виден только из админки. Вот он и является верификацией. Обычно используют с приблудами - вычисляют MD5 от соединения разных параметров и него.

Это то все понятно. Но неужели никто не понимает о чем я? Да, проблемы по защите пользователя от других пользователей -нет. Так как хеш разный.

Ладно вот привиду пример, как прило мое на днях взломали:

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

Вот и получается что без сохранения неких переменных или времени запроса никак

Psycho Tiger
25.03.2012, 12:58
Сервер должен вводить какие-то ограничения. Мол, тыкать можно не чаще чем раз в полсекунды. Но бота, или кликера, всегда можно сделать. Их ведь делают для разных ММОРПГ.

Azo
26.03.2012, 01:54
Я почему то всегда думал что чтобы взломать приложение надо быть хакером. А на деле получается что чтобы защетить приложение - надо жертвовать процессами