使用 oAuth 的 GAE 端点上的 CSRF
CSRF on GAE Endpoints with oAuth
我希望在我的 API 中实施针对 CSRF 攻击的保护,这是我使用 GAE 端点开发的,所有方法都需要 oAuth2。
在实施任何特定保护之前,我试图真正破坏我的应用程序(CSRF 乍一看看起来很简单)。但是就是不能让它工作。
当我在另一个页面中引用我的端点时,浏览器会添加 cookie 信息,但不会添加带有不记名访问令牌的授权 header。这似乎还不够,因为我的端点自动 return 401 with a www-authenticate:Bearer realm="https://accounts.google.com/"
header.
正如我所说,我没有针对 CSRF 的具体保护措施。但是,在 HTTPS 下使用 Google Cloud Endpoints 和 oAuth2 是否可以保护我免受此类攻击 "for free"?
--编辑 以解决评论
我尝试了一个简单的 CSRF 攻击。我得到一个 <img src="https://bla-bla-bla-appspot.com/_ah/api/myapi/v1/resource.getMethod">
的页面。然后我在另一个选项卡中打开我的应用程序时访问了这个页面,所以我的浏览器会发送我的身份验证信息。它确实会发送 cookie,但不会发送我的 oAuth 令牌)。
我什至没有尝试过 POST,如果我 "hack" GET 就已经很棒了。
OAUth 2.0 explicitly protects against CSRF 通过使用由客户端生成并由服务器验证的 non-guessable 状态参数。即使攻击者能够诱使客户端访问 URL 以授权恶意令牌,状态参数也不会与客户端的参数匹配,请求将被拒绝。
Google Cloud Endpoints 库会为您处理 OAuth 规范的这一点,所以您没有问题。
Oauth2 要求所有请求都将承载访问令牌作为 HTTP header(使用来自 javascript 的 XMLhttpRequest 来设置 header 并发出请求)或作为 URL 查询参数 (access_token)。攻击者不会知道这个秘密值,因此无法创建可以通过验证的 URL。
这是(我希望)对我的 Kuoll remote debugger Web 应用有用的 java 片段。
package com.kuoll.server.filters;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CrossOriginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
resp.setHeader("Access-Control-Allow-Headers", "origin, content-type, accept");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
将 resp.addHeader("Access-Control-Allow-Origin", "*");
中的 *
替换为您的来源(如果需要)。
web.xml
<filter-mapping>
<filter-name>CrossOriginFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
我希望在我的 API 中实施针对 CSRF 攻击的保护,这是我使用 GAE 端点开发的,所有方法都需要 oAuth2。
在实施任何特定保护之前,我试图真正破坏我的应用程序(CSRF 乍一看看起来很简单)。但是就是不能让它工作。
当我在另一个页面中引用我的端点时,浏览器会添加 cookie 信息,但不会添加带有不记名访问令牌的授权 header。这似乎还不够,因为我的端点自动 return 401 with a www-authenticate:Bearer realm="https://accounts.google.com/"
header.
正如我所说,我没有针对 CSRF 的具体保护措施。但是,在 HTTPS 下使用 Google Cloud Endpoints 和 oAuth2 是否可以保护我免受此类攻击 "for free"?
--编辑 以解决评论
我尝试了一个简单的 CSRF 攻击。我得到一个 <img src="https://bla-bla-bla-appspot.com/_ah/api/myapi/v1/resource.getMethod">
的页面。然后我在另一个选项卡中打开我的应用程序时访问了这个页面,所以我的浏览器会发送我的身份验证信息。它确实会发送 cookie,但不会发送我的 oAuth 令牌)。
我什至没有尝试过 POST,如果我 "hack" GET 就已经很棒了。
OAUth 2.0 explicitly protects against CSRF 通过使用由客户端生成并由服务器验证的 non-guessable 状态参数。即使攻击者能够诱使客户端访问 URL 以授权恶意令牌,状态参数也不会与客户端的参数匹配,请求将被拒绝。
Google Cloud Endpoints 库会为您处理 OAuth 规范的这一点,所以您没有问题。
Oauth2 要求所有请求都将承载访问令牌作为 HTTP header(使用来自 javascript 的 XMLhttpRequest 来设置 header 并发出请求)或作为 URL 查询参数 (access_token)。攻击者不会知道这个秘密值,因此无法创建可以通过验证的 URL。
这是(我希望)对我的 Kuoll remote debugger Web 应用有用的 java 片段。
package com.kuoll.server.filters;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CrossOriginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
resp.setHeader("Access-Control-Allow-Headers", "origin, content-type, accept");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
将 resp.addHeader("Access-Control-Allow-Origin", "*");
中的 *
替换为您的来源(如果需要)。
web.xml
<filter-mapping>
<filter-name>CrossOriginFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>