TGViewer
ryzhov_dev ryzhov_dev @ryzhov_dev · 11 subscribers
Post #9 53
Вебхуки в Go — как тихо сломать себе безопасность

Вебхуки выглядят как самая скучная часть интеграции: пришёл POST, распарсил, ответил 200. Но в e-commerce через них ходят деньги и заказы — от маркетплейсов, от платёжных провайдеров. И проверка подписи там — это место, где легко сделать "почти правильно", что на самом деле неправильно.

Три грабли, на которые я сам наступал или видел рядом:

1. Сравнение подписи через == или bytes.Equal. Это не constant-time, и теоретически подпись можно подобрать по утечкам времени. Надо hmac.Equal.
2. Нет проверки таймстемпа — значит, перехваченный запрос можно переиграть хоть через сутки. Окно в 5 минут закрывает 99% проблем.
3. Парсинг JSON до проверки подписи ломает всё: ты re-сериализуешь тело, порядок ключей и пробелы меняются, и подпись уже не сходится. Хешировать надо ровно те байты, что пришли.

Примерно так:


body, _ := io.ReadAll(r.Body)
ts := r.Header.Get("X-Signature-Timestamp")
unix, _ := strconv.ParseInt(ts, 10, 64)
if time.Since(time.Unix(unix, 0)).Abs() > 5*time.Minute {
return errors.New("stale")
}
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(ts + "."))
mac.Write(body)
got, _ := hex.DecodeString(r.Header.Get("X-Signature"))
if !hmac.Equal(got, mac.Sum(nil)) {
return errors.New("bad sig")
}


Мало кода, много смысла. И главное — сначала проверяем байты, потом парсим JSON, а не наоборот.
  • 🔥 2
More from @ryzhov_dev
  1. Aug 21, 2026Мой райтап неожиданно залетел в топ-10 и Авито прислали свой мерч 🎉
  2. Jul 24, 2026На прошлых выходных принял участие в AvitoCTF и решил сделать райтап для задания МедоИИд �…
  3. Jun 1, 2026Rate limiting в Go — без магии, по делу Рейт-лимитер — штука, которую обычно добавляют в п…
  4. May 26, 2026Индексы в MariaDB, которая тянет и OLTP, и OLAP Писал недавно про одну базу под две нагруз…
  5. May 14, 2026Вчера у меня приняли финальный проект на курсе Go разработчика в Яндекс Практикуме 🥳 Тепе…
  6. May 12, 2026Nginx как reverse proxy — баги, которые вылезают только после деплоя Nginx выглядит просты…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →