从HTML表单发布JSON

2020-11-24 22:15:19

今天,我和一位同事正在研究一个应用程序,该应用程序与许多其他现代Web应用程序一样,提供了RESTful API,其中JSON被用于对请求/响应进行序列化。她指出,该应用程序未包含任何CSRF令牌,并且似乎未将任何标头(X-Requested-With,Referer,Origin等)用作“穷人的CSRF令牌”,但因为发布JSON,它真的容易受到CSRF的攻击吗?是的,是的,肯定是的!

有趣的是,这让人联想到Michal Zalewski的The TangledWeb中描述的服务器和浏览器之间的许多混淆。

使用特定编码是安全边界的想法,至少是完全错误的安全概念,充其量只是在W3C,浏览器供应商或聪明的攻击者掌握您的API之前的权宜之计。让我们研究一下JSONencoding作为一种针对CSRF的保护措施,并演示一个迷你PoC。

我们有一个用Go编写的基本应用程序。无需进行验证检查,以确保帖子大小,但这不仅仅是未经身份验证的端点。

包主要导入(“ encoding / json”“ fmt”“ net / http”)类型Secrets struct {Secret int} var storage Secrets func handler(w http。ResponseWriter,r * http。Request){if r。方法==“ POST” {json。 NewDecoder(r.Body)。解码(和存储)} fmt。 Fprintf(w,“秘密是%d”,存储。秘密)} func main(){http。 HandleFunc(“ /”,handler)http。 ListenAndServe(“:8080”,nil)}

如您所见,它基本上是一个秘密号码,可以通过JSON对象的HTTP POST进行更新。如果我们尝试使用URL编码或多部分POST,则JSON解码会失败,并且机密保持不变。我们必须POSTJSON才能更改秘密值。

因此,让我们在这里探讨我们的选择。该站点可以通过XMLHTTPRequest API在本地使用AJAX,但是由于Same-OriginPolicy,攻击者的站点无法使用它。对于大多数CSRF,解决此问题的方法是普通的HTML表单,因为表单提交不受Same-OriginPolicy的约束。 W3C拥有针对JSONforms的规范草案,但自2015年末以来已被放弃,并且不受任何浏览器的支持。可能有一些技术可以利用Flash或其他浏览器插件(不是吗?),但是甚至可以使用基本形式来完成,只需要一点工作。

通常,如果我们尝试将JSON作为表单值发布,则最终以URL编码,更不用说包含字段名了。

事实证明,您可以将表单的enctype设置为text / plain,并避免对表单数据进行URL编码。此时,您将获得类似以下内容的信息:

不幸的是,我们仍然必须与表单字段名称和theseparator(=)竞争。这很简单,只需将我们的有效负载分配到字段名称和值之间,然后将等号放在未使用的字段中。 (或者,如果需要,可以将其用作有效负载的一部分。)

这篇文章包含会员链接。如果您单击链接,我可能会为您免费赚取少量佣金。