Как защитить денежный баланс на сайте от накрутки?

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

Думал подписывать каждую награду md5 но, и копировать таблицу на 2 базы данных, при выводе проверять подпись и сверять со второй бд. На сколько это может обезопасить? или может посоветуйте что то пожалуйста.
  • Вопрос задан
  • 927 просмотров
Пригласить эксперта
Ответы на вопрос 6
stasuss
@stasuss
быдлокодер со стажем
проверять все на сервере и не доверять никакой информации от пользователя

т.е. сам сайт это как монитор компьютера, а все самое интересное происходит на сервере (типа системный блок, который рядом с монитором)
Ответ написан
copist
@copist
Empower people to give
Пользуйтесь ключами RSA, у каждого пользователя своя пара ключей. Один (публичный) передаётся на сервер, другой (приватный) остаётся у пользователя. Когда делается транзакция, например покупка, то на сервер должна поступать информация:
  1. идентификатор покупателя
  2. номер счёта покупателя
  3. идентификатор продавца
  4. номер счёта продавца
  5. идентификатор покупки
  6. валюта
  7. точная сумма покупки
  8. точное время транзации в таймзоне UTC

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

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

Проверяйте время транзакций. У каждого покупателя все транзакции должны быть строго хронологическими. Не должно быть чтобы покупка N+1 была ДО покупки N.

Это вычисляется долго. Чтобы ускорить вычисление остатка, можно ввести специальный тип транзакции "состояние на начало месяца". Его должны выполнять сторонний доверенный сервер, имеющий свою специальную пару ключей. Тогда текущий баланс = последний остаток на начало месяца + все поступления - все оплаты. Вычисляется значительно быстрее.

Если злоумышленник взломает базу данных, то внесёние записей будет чрезывычайно затруднительным, потому что подделать отпечаток транзакции будет невозможно. Слабое звено - можно просто выгрузить базу или таблицу в файл и затем дропнуть таблицу или базу и шантажировать вас потерянными данными. Чтобы исключить такое, запретите пользователям (не покупателям, а тем, которые подключаются к базе) делать DROP TABLE/DATABASE. Ещё делайте резервные копии. Ещё держите зеркало базы данных.

Всё что я описал, будет бесполезно, если злоумышленник заменит исходный код платёжного сервера, так как он сможет просто вырубить все проверки на отпечатки. Поэтому платёжный сервер не должен быть скриптовым. То есть не PHP, node, Python, Ruby. Это должен быть компилируемый код. С цифровой подписью. Сервер не должен исполнять приложения с отсутствующей или неправильной цифровой подписью.

Но это не мешает подменить список доверенных центров сертификации на сервере, чтобы запустить поддельное приложение вместо платёжного сервера. Поэтому на стороне СУБД нужно реализовать механизм, который не даёт подключиться к базе любому приложению. Это приложение должно иметь специальный механизм доступа. Ограничение по IP, специальные заголовки, особенная сессия. Значит это не MySQL и, скорее всего, не PostgreSQL.

Ещё о каком-нибудь головняке рассказать или уже достаточно?

Специалисты из WebMoney, PayPal, Yandex.Деньги и онлайн-банков сейчас не скрывая улыбки смотрят на мой алгоритм. Привет вам всем, друзья!

Относительно реализации на PHP. Два сервера с запросами через AJAX не сделают сервер надёжнее, потому что всё можно подделать в браузере.

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

Вот списочек способов проникнуть на сервер:
  • Через уязвимости серверных компонентов;
  • Через уязвимости в веб-окружении сервера;
  • Через удаленное выполнение произвольного кода;
  • Через наличие переполнений;
  • Через инъекции (внедрение кода) (например, SQL Injection);
  • Через обход системы аутентификации веб-ресурса;
  • Через XSS / CSRF;
  • Через перехват привилегированных аккаунтов (или сессии таких аккаунтов);
  • Через Remote File Inclusion / Local File Inclusion;
  • Через компоненты CMS, CMF и фреймворков с известными уязвимостями;
  • Через перенаправление на другие сайты c помощью открытых редиректов;
  • Через сканирование директорий и файлов (поиск дампов, данных про git, svn);
  • Через подбор паролей.


И вот списочек способов снижения вероятности проникновения и нанесения непоправимого ущерба:

Состояние серверов
  • Держи сервера в актуальном состоянии, следи за найденными уязвимостями, обновляй серверные приложения
  • Делай бакапы файлов и баз данных, держи зеркальную базу данных; в случае беды - используй копию
  • Используй виртуальные машины, делай периодически снимки, а в случае взлома восстанавливай машины из снимков
  • Больше не вспомню. Держи админа под рукой.


Доступ к серверам
  • Не подключайся от имени пользователя root, заведи другого.
  • Установи на всех пользователей длинный пароль.
  • Запрети всем пользователям делать sudo. Можно разрешить делать некоторые отдельные операции, например, nginx reload.
  • Для подключения к серверам пользуйтя SSH или SFTP, авторизация по ключам
  • Смени порты сервисов SSH и SFTP
  • Установи ограничение на список IP, с которых можно подключиться к серверу. Сделай себе белый IP адрес.


Внутренние сервисы
  • Если всё приложение на одном сервисе, то все внутренние службы (mysql, memcached, raddis, rabbit) должны слушать только интерфейс 127.0.0.1. ( habrahabr.ru/post/212265 )
  • Если приложение включает несколько серверов (отдельно база, отдельно PHP), то есть представляет собой кластер, то службы должны слушать только те IP, которые относятся к кластеру.
  • Смени стандартные порты всех сервисов
  • Пользователю UNIX от которого работает PHP-FPM / NGINX/ APACHE, должны быть открыты для записи только несколько директорий (upload, логи, временные файлы), а для исполнения - вообще ничего нельзя.
  • Пользователю базы данных не должны быть доступны деструктивные и небезопасные операции (DROP/ALTER/CREATE PROCEDURE), может быть даже для INSERT/UPDATE/DELETE в данных по финансам использовать другой аккант в базе данных


Приложение PHP
  • Защищай сайт с помощью SSL
  • Используй дополнительный платёжный пароль, ограничивай количество попыток оплаты с неверным паролем
  • Используй server side http cookie, короткие сессии с привязкой ключа сесии к IP и UserAgent клиента
  • Все запросы к базу должны быть только с использованием связываемых параметров, никаких конкатенаций запроса с параметрами (Внедрение SQL-кода, SQL injection, php.net/manual/ru/security.database.sql-injection.php и другое по фразе SQL injection )
  • Не доверяй проверкам данных на стороне клиента. Да, они ускоряют работу, но их можно легко подделать. Поэтому все проверки дублируй в коде на сервере.
  • Не доверяй данным пользователя: фильтруй строки, отрезай теги, укорачивай до допустимой длины, приводи к числам все числа (wikipedia: CSS, Cross Site Scripting — «межсайтовы..., XSS для новичков, Яндекс: XSS-атаки и другое по фразе "XSS")
  • Все запросы на сервер должны сопровождаться токеном безопасности ( https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B6%D... https://learn.javascript.ru/csrf habrahabr.ru/post/235247 и другое по фразе "CSRF" )
  • Нигде не делай авто-редирект на страницу, указанную в параметрах запроса - так обычно делают, чтобы после логина вернуться туда, откуда была вызвана форма логина
  • Про содержимое транзакций уже писал, не знаю что из этого тебе пригодится
Ответ написан
webinar
@webinar Куратор тега PHP
Учим yii: https://youtu.be/-WRMlGHLgRg
Пользователь не должен иметь доступ к определенным действиям. Это вопрос безопасности. А Ваша задача лишь частный случай из этой задачи. Поэтому эту проблему надо решать глобально, а не в рамках данной задачи.
Если просто - читайте что написал Вам Curly Brace
Другой вопрос как защититься от бота, который может по несколько раз в секунду выполнять действие за которое Вы начисляете деньги. Но это другая задача и ее решение будет зависеть от Ваших скилов и архитектуры приложения.
Ответ написан
orlov0562
@orlov0562 Куратор тега PHP
I'm cool!
Если злоумышленник получит доступ к серверу, то никакие другие базы не помогут, т.к. он сможет получить пароли и ключи доступа к другим базам/сервисам. Единственный верный способ, это не пускать хакеров к себе на сервер, следить за подозрительной активностью и делать регулярные бэкапы.
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Не дай БОГ Вам игровую (и не только!) бизнес-логику веб-приложения получать с клиента (из браузера и т.д.)!
1. Все контрольные точки - проверяем на сервере через socket/ajax.
2. Самая важная проверка - растяжение/сжатие времени: не допускайте телепортации и эффекты матрицы там, где их быть не должно!
3. Валидируйте ВСЕ входные данные перед обработкой через регулярные выражения.
Ответ написан
Комментировать
@lehha
Рядом с балансом храните его хэш (uid+balance+salt). Соль для хэша храните в коде приложения, чтобы его было сложно достать. Таким образом без глубокого изучения кода понять какой именно ключ и как формируется хэш будет тяжело. А если код еще и компилируется, то практически идеальное решение.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы