GuardAPI Logo
GuardAPI

Fix Insecure Webhooks in Yii

Webhooks are essentially blind entry points. In Yii, developers often treat webhook endpoints as standard POST actions, failing to verify the origin or integrity of the payload. This leads to unauthorized state changes or remote code execution via spoofed requests. If you aren't verifying HMAC signatures using constant-time comparisons, your 'secure' integration is a lie.

The Vulnerable Pattern

public function actionHandleWebhook() {
    // VULNERABLE: No authentication or signature verification
    $data = \Yii::$app->request->post();
    $orderId = $data['order_id'];
    $status = $data['status'];
$order = Order::findOne($orderId);
if ($order && $status === 'paid') {
    $order->markAsPaid(); // Triggered by anyone who knows the URL
}
return ['status' => 'success'];

}

The Secure Implementation

The fix enforces three layers of security: 1. Raw Body Access: Using getRawBody() ensures the signature is checked against the exact bytes received, preventing issues with PHP's auto-parsing. 2. HMAC Verification: We use a shared secret and SHA256 to verify that the sender is authentic and the data hasn't been tampered with. 3. Constant-Time Comparison: hash_equals() is used to compare the computed hash against the provided signature. This prevents side-channel timing attacks where an attacker could guess the signature character-by-character based on response times.

public function actionHandleWebhook() {
    $request = \Yii::$app->request;
    $signature = $request->headers->get('X-Payload-Signature');
    $payload = $request->getRawBody();
    $secret = \Yii::$app->params['webhook_secret'];
if (!$signature) {
    throw new \yii\web\BadRequestHttpException('Missing signature');
}

$computed = hash_hmac('sha256', $payload, $secret);

// SECURE: Use hash_equals to prevent timing attacks
if (!hash_equals($computed, $signature)) {
    \Yii::error('Webhook signature mismatch', 'security');
    throw new \yii\web\ForbiddenHttpException('Invalid signature');
}

$data = json_decode($payload, true);
$order = Order::findOne($data['order_id'] ?? null);
if ($order && ($data['status'] ?? '') === 'paid') {
    $order->markAsPaid();
}
return ['status' => 'verified'];

}

System Alert • ID: 3232
Target: Yii API
Potential Vulnerability

Your Yii API might be exposed to Insecure Webhooks

74% of Yii apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.