request.getHeader("Origin") 如何防止跨站请求伪造攻击?
How request.getHeader("Origin") prevents from Cross Site Request Forgery attacks?
我正在开发 Web 应用程序,并要求在发布前 运行 VAPT
反对它。
然后我下载了Vega并快速扫描了我的webapp,发现了一个VAPT问题,如下:
Vega has detected that the resource has set an insecure Cross-Origin
Resource Sharing (CORS) access control. CORS provides mechanisms that
allow a server to restrict resource access for cross-site requests to
certain trusted domains. The server in question has allowed resource
from any origin by setting the value of the
"Access-Control-Allow-Origin" response header to a wildcard value.
This presents a security risk because any site can issue requests to
access resources, regardless of origin.
然后我开始寻找修复它的解决方案并遇到 post 并按照答案中的建议实施 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 post, I am thinking over how request.getHeader("Origin")
prevents from Cross Site Request Forgery attacks
, as whatever the origin is either https://webapp.com or https://evil.com 后,请求对应用程序始终有效,因为我从请求 header 本身中选择 "Access-Control-Allow-Origin"
。
任何人都可以帮助我理解这个概念,如何设置 request.getHeader("Origin")
从 CSRF attacks
保存?
谢谢。
阅读@rism 回答和 Patrick Grimard 后的理解 post :
当客户端应用程序发出 AJAX 请求时,浏览器最初会向服务器发送预检 OPTIONS
请求以确定允许客户端执行的操作,对于 [=22= 以外的请求] 这就是我们应该将 Access-Control-Allow-Origin
设置为来源或特定域作为响应的一部分的原因 header.
以POST
为例,当客户端发送请求时,浏览器首先向服务器发出预检OPTIONS
请求,服务器对OPTIONS
请求的响应包含header 指示允许所有 origin
请求的浏览器。除了添加 response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
站点仍然存在漏洞,因此我们需要在 Apache 中显式 whitelist
IP(对于部署在集群中的应用程序),如 here or in Tomcat as described here.
我仍然有一个疑问,如果我们在服务器级别本身限制 IP 地址,那么我们真的需要将 "Access-Control-Allow-Origin"
设置为响应的一部分 header?
有助于理解 CSRF 攻击的目的。它们与 "stealing" 您的数据无关。顾名思义,它们是关于 "making forged requests across sites" aka Cross Site Request Forgery aka 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
headers.
明确说明哪些网站可以和不可以向它发出请求。
而且如果他们没有特别包含 www.cutekittens.com,那么即使攻击者设法将他们的恶意脚本注入到 www.cutekittens.com 站点的页面中,即使您恰好在网上冲浪cutekittens 和你的银行网站同时存在,即使执行了攻击脚本,对 www.yourbank.com 的请求也会被丢弃(在 POST 的预检之后),因为银行没有发送 header 到浏览器 ACCESS-CONTROL-ALLOW-ORIGIN : www.cutekittens.com
以专门授权请求。
所以你是对的。通过用动态 request.getHeader("Origin")
替换此 header 的静态 *
值,您所做的一切就是让 Vega 脱离您的支持。如果您的网站写得不好,它仍然可能容易受到这种攻击,因为它会反射回来www.cutekittens.com,这可能不是您想要的。
您使用 request.getHeader("Origin")
而不是 *
的一个原因是您希望将凭据发送到服务器。您不能发送凭据,例如CORS AJAX 请求上的 cookie 等,到仅使用 *
的服务器,因此在这种情况下,您将动态地将来源反射回客户端。
但是通过这样做,您确实需要确保以其他方式降低风险。在这种情况下,您通常还会将您将要反映和不会反映的内容列入白名单。例如portal.mybank.com 可能在列表中,但 www.cutekittens.com 不会。因此,如果您要使用动态原点反射,那将是您可以实施的下一步。
我正在开发 Web 应用程序,并要求在发布前 运行 VAPT
反对它。
然后我下载了Vega并快速扫描了我的webapp,发现了一个VAPT问题,如下:
Vega has detected that the resource has set an insecure Cross-Origin Resource Sharing (CORS) access control. CORS provides mechanisms that allow a server to restrict resource access for cross-site requests to certain trusted domains. The server in question has allowed resource from any origin by setting the value of the "Access-Control-Allow-Origin" response header to a wildcard value. This presents a security risk because any site can issue requests to access resources, regardless of origin.
然后我开始寻找修复它的解决方案并遇到 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 post, I am thinking over how request.getHeader("Origin")
prevents from Cross Site Request Forgery attacks
, as whatever the origin is either https://webapp.com or https://evil.com 后,请求对应用程序始终有效,因为我从请求 header 本身中选择 "Access-Control-Allow-Origin"
。
任何人都可以帮助我理解这个概念,如何设置 request.getHeader("Origin")
从 CSRF attacks
保存?
谢谢。
阅读@rism 回答和 Patrick Grimard 后的理解 post :
当客户端应用程序发出 AJAX 请求时,浏览器最初会向服务器发送预检 OPTIONS
请求以确定允许客户端执行的操作,对于 [=22= 以外的请求] 这就是我们应该将 Access-Control-Allow-Origin
设置为来源或特定域作为响应的一部分的原因 header.
以POST
为例,当客户端发送请求时,浏览器首先向服务器发出预检OPTIONS
请求,服务器对OPTIONS
请求的响应包含header 指示允许所有 origin
请求的浏览器。除了添加 response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
站点仍然存在漏洞,因此我们需要在 Apache 中显式 whitelist
IP(对于部署在集群中的应用程序),如 here or in Tomcat as described here.
我仍然有一个疑问,如果我们在服务器级别本身限制 IP 地址,那么我们真的需要将 "Access-Control-Allow-Origin"
设置为响应的一部分 header?
有助于理解 CSRF 攻击的目的。它们与 "stealing" 您的数据无关。顾名思义,它们是关于 "making forged requests across sites" aka Cross Site Request Forgery aka 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
headers.
而且如果他们没有特别包含 www.cutekittens.com,那么即使攻击者设法将他们的恶意脚本注入到 www.cutekittens.com 站点的页面中,即使您恰好在网上冲浪cutekittens 和你的银行网站同时存在,即使执行了攻击脚本,对 www.yourbank.com 的请求也会被丢弃(在 POST 的预检之后),因为银行没有发送 header 到浏览器 ACCESS-CONTROL-ALLOW-ORIGIN : www.cutekittens.com
以专门授权请求。
所以你是对的。通过用动态 request.getHeader("Origin")
替换此 header 的静态 *
值,您所做的一切就是让 Vega 脱离您的支持。如果您的网站写得不好,它仍然可能容易受到这种攻击,因为它会反射回来www.cutekittens.com,这可能不是您想要的。
您使用 request.getHeader("Origin")
而不是 *
的一个原因是您希望将凭据发送到服务器。您不能发送凭据,例如CORS AJAX 请求上的 cookie 等,到仅使用 *
的服务器,因此在这种情况下,您将动态地将来源反射回客户端。
但是通过这样做,您确实需要确保以其他方式降低风险。在这种情况下,您通常还会将您将要反映和不会反映的内容列入白名单。例如portal.mybank.com 可能在列表中,但 www.cutekittens.com 不会。因此,如果您要使用动态原点反射,那将是您可以实施的下一步。