webhook のセキュリティ保護

セキュリティ上の理由から、サーバーが想定されているる GitHub リクエストのみを受信していることを確認する必要があります。

ペイロードを受信するようにサーバーが設定されると、設定したエンドポイントに送信されたペイロードがリッスンされます。 セキュリティ上の理由から、GitHub からのリクエストに制限することをお勧めします。 これを行うにはいくつかの方法があります。たとえば、GitHub の IP アドレスからのリクエストを許可することですが、はるかに簡単な方法は、シークレットトークンを設定して情報を検証することです。

The webhook REST APIs enable you to manage repository, organization, and app webhooks. You can use this API to list webhook deliveries for a webhook, or get and redeliver an individual delivery for a webhook, which can be integrated into an external app or service. You can also use the REST API to change the configuration of the webhook. For example, you can modify the payload URL, content type, SSL verification, and secret. For more information, see:

シークレットトークンを設定する

シークレットトークンは、GitHub とサーバーの 2 か所に設定する必要があります。

GitHub にトークンを設定するには:

  1. webhook を設定しているリポジトリに移動します。
  2. シークレットテキストボックスに入力します。 エントロピーの高いランダムな文字列を使用します (たとえば、ruby -rsecurerandom -e 'puts SecureRandom.hex(20)' を端末で取得することによって)。 webhook シークレットトークンフィールド
  3. [Update Webhook] をクリックします。

次に、このトークンを保存する環境変数をサーバーに設定します。 通常、これは実行と同じくらい簡単です。

$ export SECRET_TOKEN=your_token

トークンをアプリケーションにハードコーディングしないでください

GitHub からのペイロードを検証する

シークレットトークンが設定されると、GitHub はそれを使用して各ペイロードでハッシュ署名を作成します。 このハッシュ署名は、X-Hub-Signature-256

注釈: 下位互換性のために、SHA-1 ハッシュ関数を使用して生成される X-Hub-Signature ヘッダーも含まれています。 可能であれば、セキュリティを向上させるために X-Hub-Signature-256 ヘッダを使用することをお勧めします。 The example below demonstrates using the X-Hub-Signature-256 header.

たとえば、webhook をリッスンする基本的なサーバーがある場合、次のように設定されている可能性があります。

require 'sinatra'
require 'json'

post '/payload' do
  request.body.rewind
  push = JSON.parse(request.body.read)
  "I got some JSON: #{push.inspect}"
end

目的は、SECRET_TOKEN を使用してハッシュを計算し、結果が GitHub のハッシュと一致することを確認することです。 GitHub は HMAC hex digest を使用してハッシュを計算するため、サーバーを次のように再設定できます。

post '/payload' do
  request.body.rewind
  payload_body = request.body.read
  verify_signature(payload_body)
  push = JSON.parse(payload_body)
  "I got some JSON: #{push.inspect}"
end

def verify_signature(payload_body)
  signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], payload_body)
  return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])
end

Note: Webhook payloads can contain unicode characters. If your language and server implementation specifies a character encoding, ensure that you handle the payload as UTF-8.

言語とサーバーの実装は、この例で使用したコードとは異なる場合があります。 ただし、次のようないくつかの非常に重要な事項があります。

  • No matter which implementation you use, the hash signature starts with sha256=, using the key of your secret token and your payload body.

  • プレーンな == 演算子を使用することはお勧めしませんsecure_compare のようなメソッドは、「一定時間」の文字列比較を実行します。これは、通常の等式演算子に対する特定のタイミング攻撃を軽減するのに役立ちます。

このドキュメントは役立ちましたか?

プライバシーポリシー

これらのドキュメントを素晴らしいものにするのを手伝ってください!

GitHubのすべてのドキュメントはオープンソースです。間違っていたり、はっきりしないところがありましたか?Pull Requestをお送りください。

コントリビューションを行う

OR, コントリビューションの方法を学んでください。

問題がまだ解決していませんか?