目次

Webフックの保護

Deep Security Smart Check を使用すると、Webサーバが受信しているイベントが Deep Security Smart Check からのものであり、送信中に変更されていないことを簡単に確認できます。

Deep Security Smart Check がサーバにコールバックすると、シークレットをキーとして使用してイベントの署名(HMAC-SHA-256)が計算され、 X-Scan-Event-Signature HTTPヘッダに署名値が格納されます。

サーバに対するリクエストは次のようになります。

POST https://server.example.com/ HTTP/1.1
X-Scan-Event-Signature: {signature}
Content-Type: application/json

{
    "event": "scan-completed",
    "source": "/api/webhooks/7a2f1d8c-7780-41d2-821b-7230005d4be8",
    "timestamp": "2018-05-01T00:00:00Z",
    "scan": {
        ...
    }
}

scan 属性の値は、 APIドキュメントに記載されている検索の詳細オブジェクトです。

Webフックを作成する

Webフックを作成するときは、 secret 属性を、 Deep Security Smart Check とサーバーだけが認識できる値に設定します。この例では共有シークレットとして correct horse battery staple を使用していますが、ランダムな文字の長い文字列を使用する必要があります。

POST https://dssc.example.com/api/webhooks HTTP/1.1
Authorization: Bearer {token}
Content-Type: application/json

{
  "name": "secure webhook",
  "hookUrl": "https://server.example.com/",
  "active": true,
  "events": [ "*" ],
  "secret": "correct horse battery staple",
}

署名を計算して確認する

署名を確認するには、秘密鍵をキーとして使用してペイロードのHMAC-SHA-256署名を計算し、 X-Scan-Event-Signature HTTPヘッダの値と比較します。この例では、シークレットは HMAC_SECRET 環境変数に格納されています。

export HMAC_SECRET="correct horse battery staple"
# Get the secret from the environment -- don't store it in code!
secret = os.environ.get('HMAC_SECRET')

# Get the size of the payload
content_length = int(self.headers.get('Content-Length', 0))
if content_length == 0 or content_length > MAX_PAYLOAD_SIZE:
    raise InvalidPayloadSizeException()

# Read the full event payload from the request
payload = self.rfile.read(content_length)

# Calculate the HMAC-SHA-256 signature of the payload using the secret as the HMAC key
actual = hmac.new(bytes(secret, 'utf-8'),
            msg=bytes(payload),
            digestmod=hashlib.sha256).hexdigest()

# Get the expected HMAC-SHA-256 signature value from the request header
expected = self.headers.get('X-Scan-Event-Signature', '')

# Use compare_digest to reduce vulnerability to timing attacks
if not hmac.compare_digest(actual, expected):
    # the event has been tampered with or is not from the right sender

実例

テストイベントを送信する

Webフック ping APIエンドポイントを使用して、テストイベントをWebフックに送信できます。

POST https://dssc.example.com/api/webhooks/7a2f1d8c-7780-41d2-821b-7230005d4be8/ping HTTP/1.1
Authorization: Bearer {token}

Deep Security Smart Check から、次のようなサンプルイベントが送信されます。

POST https://server.example.com/ HTTP/1.1
X-Scan-Event-Signature: {signature}
Content-Type: application/json

{
    "event": "ping",
    "source": "/api/webhooks/7a2f1d8c-7780-41d2-821b-7230005d4be8",
    "timestamp": "2018-05-01T00:00:00Z",
}

検証コードが想定どおりに機能することを確認できます。