什么是保护你的facebook聊天机器人网络挂钩的最佳做法



我正在facebook信使平台上开发一个聊天机器人。我浏览了Facebook的文档,找不到如何保护我的webhook免受随机呼叫的影响。

例如,如果用户可以用我的机器人购买东西,那么知道某人userId的攻击者可以通过拨打我的webhook来开始下未经授权的订单。

关于如何保护这一点,我有几个想法。

  1. 将我的API白名单仅限于来自Facebook的呼叫
  2. 创造一些东西比如具有回发调用的CSRF令牌

有什么想法吗?

Facebook当然已经实现了一种机制,通过该机制,您可以检查对回调URL的请求是否真实(其他一切都只是他们的疏忽)-请参阅https://developers.facebook.com/docs/graph-api/webhooks/getting-started#validate-有效载荷

我们使用SHA256签名对所有事件通知有效载荷进行签名,并将签名包含在请求的X-Hub-Signature-256标头中,以sha256=开头。您不必验证有效负载,但您应该验证。

验证有效载荷:

  1. 使用有效负载和应用程序的应用程序机密生成SHA256签名
  2. 将您的签名与X-Hub-Signature-256标头中的签名(sha256=之后的所有内容)进行比较。如果签名匹配,则有效载荷是真实的

请注意,我们使用有效负载的转义unicode版本生成签名,该版本使用小写十六进制数字。如果你只是根据解码的字节进行计算,你最终会得到一个不同的签名。例如,字符串äöå应该转义为u00e4u00f6u00e5

除了CBroe的答案外,下面的片段还将签名验证实现表示为NestJS保护。

// src/common/guards/signature-verification.guard.ts
@Injectable()
export class SignatureVerificationGuard implements CanActivate {
  constructor(private readonly configService: ConfigService) {}
  canActivate(context: ExecutionContext): boolean {
    const {
      rawBody,
      headers: { 'x-hub-signature': signature },
    } = context.switchToHttp().getRequest();
    const { sha1 } = parse(signature);
    if (!sha1) return false;
    const appSecret = this.configService.get('MESSENGER_APP_SECRET');
    const digest = createHmac('sha1', appSecret).update(rawBody).digest('hex');
    const hashBufferFromBody = Buffer.from(`sha1=${digest}`, 'utf-8');
    const bufferFromSignature = Buffer.from(signature, 'utf-8');
    if (hashBufferFromBody.length !== bufferFromSignature.length)
      return false;
    return timingSafeEqual(hashBufferFromBody, bufferFromSignature);
  }
}
// src/modules/webhook/webhook.controller.ts
@UseGuards(SignatureVerificationGuard)
@Post()
@HttpCode(HttpStatus.OK)
handleWebhook(@Body() data) {
  // ...
}

相关内容

  • 没有找到相关文章

最新更新