在Python REST API中实现CSRF保护

时间:2016-01-31 15:17:18

标签: python rest security encryption csrf

使用JWT编写带有Pyramid / Cornice的REST API进行身份验证,我必须实施一些CSRF保护。 在仔细阅读了这个主题之后,我理解了这个问题,但我对实现它的最佳方法感到很困惑,考虑到所有可能的攻击向量,它有点棘手。

由于此API可以访问敏感数据并将作为开源软件发布,因此需要一个独立的保护。它将用于具有不受信任的子域的环境中,我不能依赖用户遵循安全准则。

对于我的无国籍服务,我可以使用" Double Submit Cookies"或者" Encrypted Token Pattern" -method。

Double Submit Cookies

要防止"cookie tossing",Double Submit方法中的令牌需要是可验证的。 MiTM attacks是一个额外的威胁,我希望通过仅强制使用HTTPS-cookies来充分缓解这种威胁。

要获得一个无法通过攻击者轻易猜到并复制的可验证令牌,我想像这样的哈希标记应该可以正常工作:

pbkdf2_sha256.encrypt($userid + $expire + $mycsrfsecret, salt=$salt)

"&EXP#34;是JWT的到期值。 JWT将与CSRF-cookie和" exp"一起发布。可以被服务器读取,它增加了一些额外的保护,因为它的变量和攻击者都不知道它(可能是多余的?)。

根据请求,我可以轻松地比较我收到的两个令牌,并使用pbkdf2_sha256.verify($tokenfromrequest, $userid + $exp + $mycsrfsecret)将其与JWT令牌中的值进行比较(' Verifiablity')。

这种方法会遵循建议的做法吗?

我已经选择pbkdf2 over bcrypt,因为它的验证方法明显更快。

到期将设置为7天,之后JWT和CSRF令牌将通过新登录续订(它们也将在中间重新登录时续订)。

加密令牌模式

The alternative是向客户端发送一个字符串,由userid,expiry和nonce组成,用服务器端密码加密。在请求中,此字符串将被发送,服务器可以对其进行解密并验证用户ID和到期日期。

这似乎是一种更简单的方法,但我不确定如何实现它,我不打算推​​出自己的加密,我没有找到好的例子:

  • 我应该在Python中使用什么密码/库?我该怎么做Encrypt-then-MAC?
  • 如何将令牌持续到其自然过期?我不希望用户每次重新启动浏览器时都必须重新登录。本地存储不是一个安全的地方 - 但没有其他选择。

1 个答案:

答案 0 :(得分:1)

  

使用JWT编写带有Pyramid / Cornice的REST API进行身份验证

虽然我不熟悉这些框架,但我建议您确保JWT令牌在HTTP头(例如My-JWT-Token: ...)内传递,而不是cookie。然后您不必担心CSRF向量。

跨站点请求伪造是一个问题,因为浏览器的性质总是倾向于将cookie(通常包含身份验证信息)提交到特定域。浏览器不会自动提交自定义标题,您不必担心。

  

Double Submit Cookies

您的方法过于复杂,您只需使用GUID即可。将该GUID放入cookie中,并将其放入请求的任何其他部分。如果他们相等,CSRF检查通过。您还可以将GUID放入JWT,然后验证GUID也在标题/正文/查询参数中。

  

加密令牌模式

这几乎就是JWT,只需按照建议的标题传递令牌

回答问题:

  • 我建议hmacimport hmac一样。我不打扰加密,只是确保令牌中没有敏感信息。其他PyCrypto也可以帮到你。
  • 这就是存在cookie的原因,这确实会再次引发CSRF问题。如果这是一个硬性要求,那么我建议使用双提交cookie方法。