Tidak suka iklan? Pergi Bebas Iklan Hari ini

HMAC — Bagaimana Webhook Tahu Anda Tidak Berbohong

Diterbitkan pada

Setiap server dapat mengirimkan permintaan POST ke endpoint webhook Anda. Tanda tangan HMAC adalah cara pengirim yang sah membuktikan mereka menulis payload — dan cara Anda memverifikasinya.

HMAC — Bagaimana Webhook Tahu Anda Tidak Menipu 1
IKLAN · HAPUS?

Setiap kali Stripe melakukan pembayaran dengan kartu, sistem mengirimkan notifikasi webhook. Setiap kali GitHub menggabungkan permintaan penggabungan, sistem mengirimkan notifikasi webhook. Platform-platform ini mengirimkan permintaan POST ke URL yang Anda berikan — namun ada kebenaran yang tidak nyaman: siapa pun dapat mengirimkan permintaan POST ke URL yang sama.

Maka bagaimana server Anda tahu bahwa permintaan tersebut benar-benar berasal dari Stripe dan bukan dari penyerang yang menebak URL endpoint Anda? Jawabannya adalah HMAC — dan setelah Anda memahaminya, Anda akan menyadari mengapa HMAC menjadi pendekatan standar di setiap platform API yang serius.

Masalah: Siapa Saja Bisa Mengirimkan POST ke Endpoint Anda

Endpoint webhook hanyalah URL. Mereka dapat diakses secara publik (karena harus, agar pengirim dapat mencapainya), dan mereka menerima permintaan POST. Tidak ada yang mencegah penyerang jahat membuat payload palsu dan mengirimkannya ke endpoint Anda.

Bayangkan handler webhook Anda melakukan hal ini saat menerima peristiwa:

if event["type"] == "payment.completed":
    fulfill_order(event["data"]["order_id"])

Seorang penyerang yang tahu URL endpoint Anda dapat mengirimkan peristiwa palsu dengan ID pesanan apa saja yang mereka inginkan. Tanpa verifikasi, server Anda akan dengan senang hati memenuhi pesanan yang tidak pernah dibayar. payment.completed Anda membutuhkan cara untuk memverifikasi bahwa payload tersebut dibuat oleh seseorang yang memiliki rahasia yang Anda bagikan bersama — tanpa mengirimkan rahasia tersebut dalam permintaan.

Apa Itu HMAC?

. Ini adalah konstruksi yang menggabungkan fungsi hash kriptografi (biasanya SHA-256) dengan kunci rahasia untuk menghasilkan tanda tangan. Tanda tangan ini membuktikan dua hal:

HMAC berarti Kode Autentikasi Pesan Berbasis Hash— pesan dibuat oleh seseorang yang memiliki kunci rahasia

  • Keaslian Integritas
  • — pesan tidak diubah selama perjalanan Sifat kunci HMAC: Anda tidak dapat menghasilkan tanda tangan yang valid tanpa tahu rahasia. Dan Anda tidak dapat membalikkan tanda tangan untuk memulihkan rahasia. Ini adalah bukti satu arah.

HMAC dibandingkan dengan hash biasa

Hash biasa (seperti SHA-256) dari payload menyelesaikan masalah integritas tetapi tidak menyelesaikan masalah autentisitas. Seorang penyerang yang mengintersepsi payload yang valid dapat menghitung hash dari payload yang diubah. HMAC menggabungkan kunci rahasia Anda dalam setiap langkah proses hashing, sehingga tanpa kunci, Anda tidak dapat menghasilkan tanda tangan yang sesuai bahkan jika Anda tahu algoritma hash yang digunakan.

Cara HMAC Webhook Bekerja

Alur ini memiliki tiga langkah: pertukaran kunci, penandatanganan, dan verifikasi.

Langkah 1: Pertukaran kunci (terjadi sekali)

Ketika Anda mengonfigurasi webhook dengan platform seperti Stripe atau GitHub, mereka menghasilkan

kunci webhook dan menunjukkannya kepada Anda sekali. Anda menyimpannya di sisi server (tidak pernah di kode sisi klien atau repositori publik). Itu saja — kunci tidak pernah dikirim lagi melalui jaringan. Langkah 2: Pengirim menandatangani payload

Sebelum mengirimkan webhook, platform menghitung tanda tangan HMAC atas tubuh permintaan mentah menggunakan kunci bersama Anda:

Tanda tangan ini kemudian ditambahkan ke permintaan, biasanya dalam header seperti

signature = HMAC-SHA256(secret_key, request_body)

(GitHub) atau X-Hub-Signature-256 (Stripe). Tubuh payload bergerak tanpa perubahan. Stripe-Signature Langkah 3: Anda memverifikasi saat menerima

Ketika server Anda menerima webhook, Anda menghitung HMAC yang sama menggunakan tubuh mentah dan kunci yang disimpan, lalu membandingkannya dengan tanda tangan di header. Jika keduanya cocok, payload tersebut autentik dan tidak diubah. Jika tidak, tolak permintaan tersebut.

perbandingan waktu konstan

expected = HMAC-SHA256(your_secret, raw_body)
if not constant_time_equal(expected, header_signature):
    return 401

Melihat — kita akan kembali ke alasan mengapa ini penting. header yang mengandung waktu dan satu atau lebih tanda tangan:

untuk pratinjau.

Stripe

Stripe mengirimkan header Stripe-Signature Tanda tangan dihitung atas

Stripe-Signature: t=1679000000,v1=abc123...,v0=oldformat...

(dikonkatenasi dengan titik). Memasukkan waktu memungkinkan Stripe melindungi terhadap serangan replay — jika penyerang mencatat permintaan yang valid dan mengirimkannya kembali nanti, Anda dapat menolaknya karena waktu sudah terlalu tua. timestamp.payload GitHub mengirimkan header

GitHub

dalam format X-Hub-Signature-256 . Tanda tangan dihitung sebagai HMAC-SHA256 dari tubuh mentah menggunakan kunci webhook yang Anda konfigurasi di pengaturan repositori Anda. sha256=<hex_digest>Shopify menggunakan header

Shopify

dengan tanda tangan HMAC-SHA256 yang dienkripsi dalam Base64 — konsep yang sama, hanya dengan pengekodan yang berbeda. X-Shopify-Hmac-Sha256 Verifikasi dalam Kode

Berikut ini adalah bagaimana verifikasi terlihat di tiga bahasa umum. Pola yang sama identik — hanya perintah library yang berbeda.

Kesalahan yang Menghancurkan Keamanan

Ular piton

import hmac
import hashlib

def verify_webhook(secret: str, payload: bytes, signature_header: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    received = signature_header.removeprefix("sha256=")
    return hmac.compare_digest(expected, received)

Bahasa pemrograman Node.js

const crypto = require('crypto');

function verifyWebhook(secret, rawBody, signatureHeader) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  
  const received = signatureHeader.replace('sha256=', '');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(received)
  );
}

PHP

function verifyWebhook(string $secret, string $rawBody, string $signatureHeader): bool {
    $expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
    return hash_equals($expected, $signatureHeader);
}

1. Menggunakan == daripada perbandingan waktu konstan

Perbandingan string standar (

) mempercepat proses segera saat menemukan ketidaksesuaian. Ini menciptakan==, ===saluran waktu samping : penyerang dapat mengukur berapa lama server Anda menolak tanda tangan yang berbeda. String yang memiliki prefix yang lebih panjang membutuhkan waktu sedikit lebih lama untuk ditolak. Dengan cukup permintaan, penyerang dapat menggunakan ini untuk membangun tanda tangan yang valid secara per byte.Selalu gunakan perbandingan waktu konstan:

di Node.js, hmac.compare_digest() dalam Python, crypto.timingSafeEqual() di PHP. hash_equals() 2. Memarsing tubuh sebelum verifikasi

HMAC dihitung atas

byte mentah dari tubuh permintaan. Jika Anda memarsing JSON terlebih dahulu lalu mengubahnya kembali, Anda mungkin mendapatkan urutan byte yang berbeda (urutan kunci yang berbeda, spasi, pengkodean). Selalu tangkap tubuh mentah sebelum parser tubuh di framework Anda mengaksesnya, lalu verifikasi terhadap yang tersebut. 3. Tidak memeriksa serangan replay

Permintaan yang ditandatangani secara valid berlaku selamanya — kecuali Anda memeriksa waktu. Jika platform mencakup waktu dalam skema tanda tangan (Stripe melakukannya; GitHub tidak), tolak permintaan yang waktu sudah lebih dari beberapa menit. Ini mencegah penyerang mencatat dan mengulang permintaan yang sah.

4. Menyimpan kunci secara langsung dalam kode sumber

Kunci webhook harus berada di variabel lingkungan atau manajer rahasia, tidak pernah disimpan dalam kontrol versi. Jika kunci bocor, penyerang dapat membuat payload palsu selamanya — sampai Anda mengganti kuncinya.

Apa yang Tidak Dilindungi oleh HMAC

HMAC membuktikan bahwa payload ditandatangani oleh seseorang yang memiliki kunci. Namun, ini

tidak melindungi terhadap: bukan Penggunaan pengirim yang terkompromi

  • — jika infrastruktur penandatanganan Stripe terkompromi, peristiwa palsu tetap akan memiliki tanda tangan yang valid — kecuali Anda juga memverifikasi waktu atau nonce
  • Serangan ulang Kerahasiaan
  • — HMAC tidak mengenkripsi apa pun; payload bergerak dalam bentuk teks biasa (meskipun HTTPS menangani ini) Untuk kebanyakan integrasi webhook, HMAC atas HTTPS mencakup semua yang Anda butuhkan.

HMAC — Bagaimana Webhook Tahu Anda Tidak Menipu 2

Ingin bebas iklan? Bebas Iklan Hari Ini

Instal Ekstensi Kami

Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat

Ke Ekstensi Chrome Ke Ekstensi Tepi Ke Ekstensi Firefox Ke Ekstensi Opera

Papan Skor Telah Tiba!

Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!

IKLAN · HAPUS?
IKLAN · HAPUS?
IKLAN · HAPUS?

Pojok Berita dengan Sorotan Teknologi

Terlibat

Bantu kami untuk terus menyediakan alat gratis yang berharga

Belikan aku kopi
IKLAN · HAPUS?