request.getHeader(" Origin")如何防止跨站点请求伪造攻击?

时间:2016-09-02 14:36:20

标签: security spring-security cors csrf csrf-protection

我正在处理Web应用程序,并要求在发布之前对其进行VAPT运行。

然后我下载了Vega并快速扫描了我的网络应用程序并遇到了VAPT问题,如下所示:

  

Vega检测到该资源设置了一个不安全的Cross-Origin   资源共享(CORS)访问控制。 CORS提供了一些机制   允许服务器限制对跨站点请求的资源访问   某些可信域。有问题的服务器允许资源   通过设置值的任何来源   "访问控制允许来源"响应标头到通配符值。   这会带来安全风险,因为任何站点都可以向其发出请求   访问资源,无论其来源如何。

然后我开始寻找解决方案来修复它并遇到this帖子并按照以下建议实施filter

@Component
public class CORSFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods",
                "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(request, response);
    }

    public void destroy() {
    }
}

现在,当我再次针对webapp扫描Vega时,它再次没有列出同样的问题,我认为我保存了我的webapp以防范CSRF攻击。

现在,在阅读this帖后,我正在考虑request.getHeader("Origin")如何阻止Cross Site Request Forgery attackshttps://webapp.comhttps://evil.com的来源,请求始终对应用程序有效,因为我从请求标头本身中选择"Access-Control-Allow-Origin"

任何人都可以帮助我理解这个概念,设置request.getHeader("Origin")如何保存CSRF attacks

感谢。

阅读@rism回答和Patrick Grimard后了解post

当客户端应用程序发出AJAX请求时,浏览器最初会向服务器发送预检OPTIONS请求,以确定允许客户端执行的操作,以及GET以外的请求以及该请求。我们应该将Access-Control-Allow-Origin设置为原点或特定域作为响应标题的一部分。

POST为例,当客户端发送请求时,浏览器首先向服务器发出预检OPTIONS请求,服务器对OPTIONS请求的响应包含指示浏览器的标头允许所有origin请求。除了添加response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));站点之外,仍然容易受到攻击,因此我们需要在Apache(对于部署在集群中的应用程序)中显式whitelist IP已完成here或在Tomcat中明确"Access-Control-Allow-Origin" { {3}}

我还有一个疑问,如果我们在服务器级别限制IP地址,那么我们真的需要将public class Test { private static X509Certificate2 _certificate; private static HttpClient HttpClient { get; set; } ... public Test() { ... if (HttpClient == null) { LoadCertificate(); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3; var handler = new WebRequestHandler(); handler.ClientCertificates.Add(_certificate); HttpClient = new HttpClient(handler, false); } } private void LoadCertificate() { using (var store = new X509Store(StoreName.My, CertificateStoreLocation)) { store.Open(OpenFlags.ReadOnly); var certificates = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateFriendlyName, true); if (certificates.Count != 1) throw new ArgumentException( $"Cannot find a valid certificate with name {CertificateFriendlyName} in {CertificateStoreLocation}"); _certificate = certificates[0]; store.Close(); } ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; } } 设置为响应标头的一部分吗?

1 个答案:

答案 0 :(得分:4)

有助于理解CSRF攻击的目的。他们不是关于"偷窃"你的数据。顾名思义,它们是关于"在网站上制作伪造请求的#34;又名Cross Site Request Forgery又名CSRF。

目的是使用涉及银行帐户的规范示例更改服务器上的状态。通过CSRF攻击,我们会尝试以您的名义伪造请求(转移100美元)。

因此,简单的示例是攻击者将脚本或隐藏表单等注入到any site的页面中,例如www.cutekittens.com并让该脚本定位specific site,例如www.mybank.com因此术语Cross Site

这个想法是,你作为受害者会同时登录这两个网站,银行网站的安全性也很宽松。当您在www.cutekittens.com上查看可爱的小猫时,攻击者已将一个跨站点攻击脚本注入其中一个或多个页面。脚本的目的是代表您向银行www.mybank.com提出要求转移100美元。

再次注意,攻击者并没有窃取您的数据,而是试图以您的名义伪造请求来窃取您的钱/无论如何。这不是man in the middle攻击(MITM),而是请求伪造攻击。在CSRF中,攻击者无法查看或需要查看您的数据,他们只是找到了一种行为方式,就好像他们就是您一样。这样做的后续目的可能是获取您的数据,例如更改您的密码等,但攻击本身就是伪造请求,而不是拦截。

银行可以通过一种方式保护自己及其所有权。客户通过CORS标题明确说明哪些网站可能会向网站提出请求。

如果他们没有专门包含www.cutekittens.com,那么即使攻击者设法将他们的恶意脚本注入www.cutekittens.com网站的页面,即使您正好冲浪Cutekittens和你的银行网站都是相同的,即使执行了攻击脚本,对www.yourbank.com的请求也会被删除(在POST预检之后)因为银行没有向浏览器发送标题{ {1}}专门授权请求。

所以你是对的。通过使用动态ACCESS-CONTROL-ALLOW-ORIGIN : www.cutekittens.com替换此标头的静态*值,您所做的一切就是让Vega脱离你的背。如果您的网站编写得不好,您的网站仍然可能容易受到攻击,因为它会反映出www.cutekittens.com,这可能不是您想要的。

您要使用request.getHeader("Origin")代替request.getHeader("Origin")的一个原因是您要将凭据发送到服务器。您无法发送凭据,例如CORS AJAX请求上的cookie等,仅使用*的服务器,因此在这种情况下,您可以动态地将原点反射回客户端。

但是,通过这样做,您确实需要确保以其他方式降低风险。在这种情况下,您通常也会列出您的意愿,并且不会反映出来。例如portal.mybank.com可能在列表中,但www.cutekittens.com不会。如果您打算使用动态原点反射,那么这将是您可以实施的下一步。