Перейти к содержимому
Безопасность
Открыть .md
На странице

Безопасность

Узнайте, как Paymos защищает балансы токенов изолированной подписью выводов, белым списком адресов, HMAC-аутентификацией, подписанными вебхуками и аудитом.

Paymos — кастодиальный шлюз: мы держим ключи, которыми ваши средства двигаются в блокчейне. У любого мерчанта тут законный вопрос: что мешает Paymos забрать мои деньги — и что будет, если что-то сломается?

Эта страница отвечает на оба — сначала коротким списком обещаний, потом простым языком с объяснением, почему так. Здесь — гарантии платформы и то, что каждая из них вам даёт, а не «чертёж» внутренностей. То, что относится к публичному API (как подписать запрос, как проверить вебхук), описано точно — без этого не подключиться.


Почему ваши деньги в безопасности

Контроль адресов и изолированная подпись

  • Изолированная инфраструктура подписи. Paymos исполняет кастодиальную подпись вне публичного веб-контура. Это управляемое хранение, а не прямой контроль ключей со стороны бизнеса.
  • Белый список включён по умолчанию. Деньги уходят только на адреса, которые вы одобрили заранее, и даже полный угон API-ключей не позволит вписать новый адрес для вывода. Отключить список можно только по запросу владельца через поддержку — и тогда этой защиты нет: тот, кто получит доступ к аккаунту или ключу Payout, выведет средства на свой адрес.
  • Кто одобряет получателя и кто двигает деньги — разные права. Белый список правит только владелец аккаунта. Роль «Финансы» отправляет выводы, но вписать в список новый адрес не может: тот, кто двигает деньги, работает по списку, который утвердил не он. При отключённом списке этой границы нет: адрес получателя вписывает тот, кто отправляет вывод. Любая выдача прав пишется в журнал.
  • Вывод — по вашему графику. Баланс ваш с момента финальности платежа. Мы не блокируем средства. Выводите хоть раз в час, хоть никогда: между запросом и отправкой транзакции нет ни расчётного окна, ни очереди, а дальше время в пути определяет сама сеть.
  • Раздельные балансы. Баланс каждого мерчанта учитывается отдельно. Мы не складываем средства в общий котёл и не пускаем их в оборот.

Деньги не пропадут незаметно

  • На баланс попадают платежи с глубиной подтверждения, выбранной по сети и сумме — достаточной, чтобы реорг был редкостью, но не такой, чтобы называть его невозможным.
  • Никаких откатов. Подтверждённый платёж не отменяется. Если он всё же выпадет из цепочки при реорге, убыток берёт Paymos, а не вы.
  • Вывод не уйдёт дважды. У каждого вывода есть ваш ключ идемпотентности.
  • Многоуровневые заморозки могут автоматически остановить один актив, если картина в блокчейне разойдётся с учётом.
  • Вывод сверяется с вашим балансом до приёма — если суммы вместе с комиссией сети на балансе нет, ошибка приходит сразу, а вывод не создаётся.
  • Записи, которые не подделать: каждое значимое действие попадает в аудит, а секреты и подписи вычищаются из записи до её сохранения.

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

Дальше — каждый пункт простыми словами. Если встречали слова HMAC или SSRF и хотелось понять, что это, — читайте ниже.


Модель угроз

Мы защищаемся от:

  • Средства в покое — ключи, которыми можно двигать балансы в блокчейне
  • Средства в движении — авторизация вывода и подмена адреса назначения
  • Доступ к API — кража ключей, повтор запроса (replay), расширение прав
  • Доставка вебхуков — поддельные тела запросов и использование нашей инфраструктуры как SSRF-плацдарма для атаки на вашу
  • Операционные риски — случайные разрушительные действия, гонки между серверами, пробелы в аудите

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


Подпись выводов и контроль адресов

В чём проблема. Средствами в блокчейне управляют ключи подписи. Украденные реквизиты, подменённый адрес или компрометация контура подписи могут привести к потере денег, если окружающие ограничения не закрываются безопасно.

Что делает Paymos. Исходящие транзакции подписываются в изолированной инфраструктуре. По умолчанию вывод возможен только на адрес из белого списка бизнеса, а пустой список блокирует выводы целиком. Правка списка — отдельное действие, и оно попадает в журнал аудита. Если у сотрудника подключён второй фактор, правка дополнительно потребует свежего подтверждения. Если второго фактора нет, подтверждать нечем: этот слой начинает работать в тот день, когда вы его включите. Если владелец через поддержку отключил белый список, адрес назначения ни с каким списком уже не сверяется; что остаётся в этом случае — ниже, в разделе о защите вывода.

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

Инфраструктура остаётся кастодиальной: Paymos управляет контуром подписи. Белый список, заморозки, аудит и сверка учёта снижают риск вокруг хранения, но не превращают его в некастодиальную или пороговую модель.

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


HMAC — как API понимает, что запрос реально от вас

HMAC (Hash-based Message Authentication Code — «код проверки подлинности на основе хеша»). Звучит страшно, суть простая.

В чём проблема. Ваш сервер шлёт нам «создай вывод на 1 000 $». У нас два вопроса: это правда вы, а не самозванец? И не подменил ли кто-то запрос по дороге — сумму или адрес? Если просто класть пароль внутрь запроса, любой, кто перехватит трафик, украдёт его и будет слать запросы от вашего имени.

Что делает HMAC. У вас и у нас есть общий секрет (ваш API-секрет). На каждый запрос вы считаете «отпечаток» (подпись) — это хеш от содержимого запроса вместе с секретом. Шлёте запрос и отпечаток, но не сам секрет. Мы своим экземпляром секрета считаем такой же отпечаток. Совпало — значит, это точно вы, и ничего не подменили: измените хоть один символ, и отпечаток не сойдётся.

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

Ключевой момент: сам секрет никогда не путешествует по сети. Поэтому, даже записав весь ваш трафик, злоумышленник не вытащит секрет и не сделает новый запрос — у него будут лишь подписи к тем запросам, что вы и так уже отправили. (SHA-256 — это «мельница», перемалывающая любой вход в отпечаток фиксированной длины, не раскручиваемый обратно.)

Точный формат (для интеграции)

Каждый аутентифицированный запрос несёт два заголовка:

Authorization: HMAC-SHA256 {api_key_id}:{base64(signature)}
X-Request-Timestamp: {unix_seconds}

Подпись — это HMAC-SHA256 по канонической строке:

{timestamp}\n{METHOD}\n{path}\n{query}\n{sha256_hex_lower(body)}

Пустое тело подставляется в этот слот как пустая строка — его не хешируют; параметры запроса подписываются ровно в том виде, в каком они в URL. Подробности — на странице Аутентификация.

Защита от повтора (anti-replay)

А переслать ваш старый, записанный запрос — повторить «создай вывод» сто раз? В подпись входит метка времени, и мы отвергаем запрос, если X-Request-Timestamp отстаёт от времени сервера больше чем на 5 минут или опережает его больше чем на 60 секунд (ответ 401). Записанный запрос живёт пять минут и умирает, а подписанный по спешащим часам — не больше чем на минуту дольше. А вместе с идемпотентностью (см. ниже) даже внутри этих минут повтор не отправит средства дважды.

Аналогия. Билет с окном входа на пять минут — вчерашний не сработает.

Сравнение «за постоянное время»

Когда мы сверяем две подписи, наивное сравнение обрывается на первом неверном символе — и по времени ответа можно угадать, сколько символов уже верны, и подобрать подпись по байту. Мы сравниваем за постоянное время: ответ «нет» занимает одинаково долго, сколько бы вы ни угадали.

Аналогия. Кодовый замок, который говорит «нет» за одно и то же время — угадали вы одну цифру или пять. Понять, что «теплее», нельзя.

Типы ключей и ротация

Два типа ключей. У каждого — жёстко закреплённый набор прав, и сервер проверяет его при каждом вызове:

  • Payment-ключ — всё, что про деньги на входе: создавать и читать инвойсы, управлять платёжными каналами и читать их депозиты. Не может читать балансы и создавать выводы.
  • Payout-ключ — создавать, читать и отменять выводы, читать балансы. Не может создавать инвойсы и не достаёт до платёжного канала.

Секреты меняются без простоя: вы генерируете новый, а предыдущий работает до previous_secret_expires_at — это ровно 24 часа с момента смены. Окно фиксированное, параметром его не задать. Пока оно открыто, принимаются оба ключа, затем — только новый.


Безопасность вебхуков — тот же HMAC, только наоборот

HMAC выше защищает ваши запросы к нам. Вебхук — это мы стучимся к вам («инвойс оплачен»). Тот же приём наоборот: мы подписываем каждый вебхук секретом вашего эндпоинта, а вы проверяете подпись, прежде чем поверить. Иначе любой, кто узнает адрес вашего вебхука, мог бы прислать поддельное «оплачено» и выманить товар.

X-Webhook-Signature: t={unix_seconds},v1={hex_hmac}

Подписывается строка {timestamp}.{request_body}. Схема совпадает со Stripe, поэтому библиотеки проверки от Stripe работают почти без правок; во время ротации секрета мы кладём в заголовок обе подписи, а утёкший секрет можно заменить и без этого перекрытия. См. Проверка вебхуков.

Защита от SSRF

SSRF (Server-Side Request Forgery — «подделка запроса со стороны сервера»). Вы задаёте адрес вебхука, и наши серверы ходят на него. Хитрый злоумышленник укажет URL не наружу, а внутрь нашей сети — на адрес облачных метаданных или внутреннюю панель — и наш сервер сходит туда за него, превратив Paymos в «прокладку» к тому, что видно только из нашей сети.

Мы это предотвращаем: адрес вебхука проверяется на то, что ведёт на публичный адрес — loopback, приватные, внутренние диапазоны и метаданные отклоняются, — а соединение «прибивается» к проверенному адресу, чтобы не было окна для DNS-rebinding. Редиректы не выполняем. Адрес, не прошедший проверку, сразу отбрасывается, поэтому «прощупывать» бесполезно. Проверяется и порт: в URL вебхука допустим 443 или любой от 1024 и выше, так что доставку не направить на стандартный порт SSH, почтового сервера или другого известного сервиса на чужой машине.

Аналогия. Курьер, который доставляет только на реальные внешние адреса, отказывается нести «в серверную этого же здания», проверяет адрес до выхода и не ведётся на записку «вообще-то отнеси вон туда».

Семантика доставки

URL вебхука должен быть на HTTPS (проверяется при сохранении). Доставка — не реже одного раза: дедуплицируйте по идентификатору события на своей стороне (так делают Stripe, GitHub, PayPal). Неуспешные доставки повторяются с экспоненциальной задержкой — всего 11 попыток примерно за 16 часов, полное расписание см. в Доставке и повторах, — затем помечаются неуспешными и доступны для переотправки из дашборда. У каждой попытки свой тайм-аут.


Защита вывода — несколько замков подряд

Вывод средств — самое уязвимое место кастодиального шлюза, поэтому слоёв тут больше всего:

  • Белый список (по умолчанию включён). Пока список включён, в том числе во время рассмотрения запроса на отключение, вывод возможен только на заранее одобренный адрес. Если для семейства сетей назначения список пуст, выплату создать нельзя: первый вывод сам адрес не добавляет. Получателем может быть и ваш клиент — список не ограничен вашими кошельками. Украденный выплатной ключ не позволяет отправить средства на адрес вне списка, пока эта защита действует.
  • Отключение белого списка. Запросить его может только владелец аккаунта, в карточке «Адреса для вывода». Детали поддержка уточнит в чате, решение примет сотрудник Paymos. Без списка вывод уходит туда, куда его направили. В дашборде адрес вводят вручную и подтверждают через 2FA, если она включена; через API выводит только рабочий ключ Payout со списком разрешённых IP, а ключу без такого списка придёт отказ с кодом ip_allowlist_required. Защиты при этом меньше: тот, кто получит доступ к аккаунту или ключу, сможет вывести средства на свой адрес. Включить список обратно владелец может сам и в любой момент, на странице «Баланс», — сохранённые адреса вернутся вместе с ним. Пока запрос на рассмотрении, белый список действует. Если активный рабочий выплатной ключ уже создан, для одобрения в нём должен быть хотя бы один разрешённый IP. Создавать ключ ради вывода из дашборда не требуется.
  • Роли и права на вывод. По умолчанию управлять белым списком может владелец, а создавать выводы — владелец и участник с ролью «Финансы». У администратора этих прав по умолчанию нет; дополнительные права можно выдать отдельно, и выдача попадёт в аудит. Запросить отключение белого списка, отменить запрос или включить список обратно может только владелец: дополнительные права эти действия не передают.
  • Второй фактор (2FA). Шестизначный код из приложения, меняется каждые 30 секунд; добавленный passkey работает вместо него. По умолчанию он выключен, и подключают его вручную — но именно он включает повторное подтверждение на опасных действиях: изменить белый список выводов, запросить его отключение, вывести на адрес, введённый вручную, поправить список разрешённых IP у API-ключа или отключить сам второй фактор без свежего кода уже не выйдет.
  • Заморозки (стоп-кран). Можем заморозить всё сразу, один токен в одной сети или одного мерчанта. Заморозка по активу включится сама, если балансы в блокчейне разойдутся с учётом сверх безопасного порога.
  • Проверка баланса до приёма. Сумма вывода вместе с комиссией сети сверяется с вашим доступным балансом ещё до того, как запрос принят. Не хватает — приходит insufficient_balance, и вывод не создаётся: ничего не повисает.
  • Идемпотентность. Ваш идентификатор заказа — ключ идемпотентности: пришлёте его дважды — получите тот же единственный вывод, а не второй перевод. Аналогия: номерок гардероба; сдадите его дважды — получите одно и то же пальто.
  • Безопасность при гонках. Параллельные запросы на вывод для одного аккаунта выстраиваются в очередь на сервере, поэтому два одновременных вызова не проскочат мимо одной проверки баланса.

Авторизация и изоляция

  • Каждый запрос проверяется на сервере перед любым действием: среда ключа должна совпадать со средой ресурса, прав ключа должно хватать на операцию, а ресурс должен принадлежать вызывающему. Интерфейс лишь показывает результат этих проверок.
  • 404, а не 403. Если ресурса нет — или он есть, но не ваш — вы получите 404. Так не отличить «такой ID существует, но не твой» от «такого ID нет». Аналогия: швейцар говорит «такого нет» и когда человека нет, и когда он есть, но вам нельзя.
  • Кто вы — берётся из ключа, а не из тела запроса. Подставить чужой идентификатор бесполезно: действовать от имени другого мерчанта, подменив ID, нельзя.
  • Гранулярные права. Доступ управляется тонкими ролевыми правами (например: вывод, просмотр баланса, управление вебхуками), каждое выдаётся отдельно. Граница — серверная проверка; дашборд лишь отражает её.

Ограничение частоты запросов

У каждого мерчанта свои лимиты. Превысили — приходит 429 Too Many Requests с заголовком Retry-After, поэтому одна «сбойная» интеграция бьёт только по своей пропускной способности, а не по платформе и не по другим мерчантам.


Финальность в блокчейне — почему «деньги не пропадут»

В блокчейне транзакция «появляется» в блоке быстро, но недавнюю историю цепочка ещё может переписать (реорг) — и то, что выглядело подтверждённым, исчезает. Как сырые чернила: вроде написано, но ещё может смазаться.

Финальность — это дождаться, пока транзакция «закопается» достаточно глубоко, чтобы откатить было нельзя. Чернила высохли. Баланс меняется только после финальности, принятой в конкретной сети. Там, где финальность измеряется глубиной подтверждений, глубина зависит от суммы: небольшой платёж закрывается быстро, крупный ждёт дольше. Там, где сеть даёт финальность сама, зачисление идёт по финальному блоку. Пороги подстраиваются под состояние сети, а не зафиксированы навсегда.

Главное обещание: если уже подтверждённый платёж всё же выпадет при реорге (большая редкость) — убыток берёт Paymos, а не вы. Как пришёл вебхук о подтверждении — на него можно реагировать сразу. Бонусом: нет возвратных платежей (chargeback) — в отличие от карт, оплату по которым покупатель отменяет много месяцев спустя. Истёкший инвойс так и остаётся истёкшим: деньги, пришедшие после срока, заново его не открывают. Если поздние переводы в токене инвойса вместе с прежними набрали нужную сумму, придёт вебхук invoice.paid_late, статус при этом не изменится, а выдавать ли заказ, решаете вы.


Защита данных

В пути: весь трафик по TLS 1.2+, в рабочей среде включён HSTS, незашифрованные запросы перенаправляются на HTTPS.

В покое: сессионные куки — HttpOnly, Secure, SameSite=Lax; ссылки для входа одноразовые, быстро истекают и хранятся зашифрованными.

Защита от подделки запроса (CSRF): запросы на вход и на работу с сессией сервер принимает, только если они отправлены с сайта Paymos, а действия в дашборде, меняющие состояние, несут анти-CSRF-токен. Куки SameSite=Lax добавляют к этому ещё один слой.

Журнал аудита: по каждому значимому действию записывается, кто его выполнил, что именно сделано, когда и с каким результатом. Чувствительные значения — секреты, пароли, токены, хеши, подписи — затираются ещё до записи.


Операционная устойчивость

  • Безопасность на нескольких серверах. Работа в несколько серверов не приводит к повторной обработке платежа, вывода или вебхука: параллельные операции над одним объектом согласованы так, чтобы выполниться ровно один раз. Проверяется автотестами, а не «на честном слове».
  • Отчёты об ошибках без утечки данных. Из отчётов о сбоях вычищаются персональные данные и содержимое запросов до того, как они покинут наши системы.
  • Безопасные изменения схемы. Миграции базы применяются один раз, по порядку и только «вперёд» — без разрушительных откатов по рабочим данным.

Комплаенс и работа с данными

KYC в Paymos нет. Начать тестирование можно без документов о личности, адресе и бенефициарах; Paymos также не собирает такие документы у ваших клиентов. В продукте нет ни анкеты, ни загрузки документов, ни отдельного шага, который открывал бы рабочий режим. Paymos не проверяет бизнес, лицензии и категории мерчантов. Зато автоматически проверяет блокчейн-адреса: с какого пришёл платёж и на какой уходит вывод. Это проверка адресов, личность ваших клиентов она не устанавливает. Обязанности по AML и санкциям остаются у мерчанта; как устроена проверка и где проходит граница, описано в политике AML.

Данные на стороне клиента. Изначально Paymos не собирает персональные данные ваших клиентов на странице оплаты — ни email, ни телефон, ни имя, ни данные карты. Поток: инвойс → платёжная страница → кошелёк платит → готово. Мы видим адреса кошельков и суммы, а не личности, поэтому ваши риски по GDPR/CCPA через Paymos практически нулевые.

Данные на стороне мерчанта. По вашему аккаунту мы храним название бизнеса, контактный email, страну и метаданные проектов (URL вебхуков, идентификаторы API-ключей). Права по GDPR, включая удаление, и адрес для запроса — в Политике конфиденциальности.


Чего мы не делаем

  • Не заявляем то, чего не построили. Эта страница описывает систему как она развёрнута. Планы развития не появляются здесь, пока не выпущены.
  • Не держим средства дольше, чем нужно. Деньги на балансе с момента подтверждения; когда выводить — решаете вы.
  • Не складываем балансы в общий котёл. Каждый баланс раздельный. Неплатёжеспособность или спор одного мерчанта не дотянется до средств другого. Именно смешение средств в общий котёл погубило биржи вроде FTX.
  • Не обещаем безопасность на стороне получателя. После подписи вывода транзакция уже в блокчейне и необратима. Пока белый список включён, он спасает от опечаток и кражи ключей — но не проверит, как поведёт себя одобренный вами адрес.

Сообщить об уязвимости

Присылайте на [email protected].

  • Подтверждение получения: в течение двух рабочих дней после полного отчёта
  • Область программы: рабочие paymos.io и *.paymos.io, публичный REST API, опубликованные Paymos SDK и модули CMS
  • Вне области: отказ в обслуживании через лимиты частоты, социальная инженерия, сторонние сервисы (ваш CDN, хостинг и т.п.)
  • Вознаграждение за уязвимости (bug bounty): публичной программы пока нет; приватное раскрытие значимых находок вознаграждается индивидуально, с упоминанием по запросу.

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