Var*_*run 5 java csrf-protection
我试图阻止我的 Web 应用程序遭受 CSRF(跨站点请求伪造)我点击了此链接Link for CSRF
这是我尝试过的。为了在 Java 中实现这一机制,我选择使用两个过滤器,一个为每个请求创建盐,另一个用于验证它。由于用户请求和后续应验证的 POST 或 GET 不一定按顺序执行,因此我决定使用基于时间的缓存来存储有效盐字符串的列表。
第一个过滤器用于为请求生成新的盐并将其存储在缓存中,代码如下:
public class LoadSalt implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Assume its HTTP
HttpServletRequest httpReq = (HttpServletRequest)request;
// Check the user session for the salt cache, if none is present we create one
@SuppressWarnings("unchecked")
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>)
httpReq.getSession().getAttribute("csrfPreventionSaltCache");
System.out.println("Checking cahce befor creating it from Request :csrfPreventionSaltCache: "+csrfPreventionSaltCache);
if(csrfPreventionSaltCache == null)
{
System.out.println("csrfPreventionSaltCache is null have to create new one");
String csrfPreventionfromrequest = (String) httpReq.getSession().getAttribute("csrfPreventionSaltCache");
System.out.println("csrfPreventionfromrequest :"+csrfPreventionfromrequest);
// creating a new cache
csrfPreventionSaltCache = CacheBuilder.newBuilder().maximumSize(5000)
.expireAfterAccess(20, TimeUnit.MINUTES).build();
// Setting to gttpReq
httpReq.getSession().setAttribute("csrfPreventionSaltCache", csrfPreventionSaltCache);
System.out.println("After setting the csrfPreventionSaltCache to HttpReq");
System.out.println("--------csrfPreventionSaltCache------ :"+httpReq.getSession().getAttribute("csrfPreventionSaltCache"));
}
// Generate the salt and store it in the users cache
String salt = RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());
System.out.println("Salt: "+salt);
csrfPreventionSaltCache.put(salt, Boolean.TRUE);
// Add the salt to the current request so it can be used
// by the page rendered in this request
httpReq.setAttribute("csrfPreventionSalt", salt);
System.out.println("Before going to validate salt checking for salt in request");
System.out.println(" httpReq.getAttribute(csrfPreventionSalt) ----:"+httpReq.getAttribute("csrfPreventionSalt"));
// System.out.println(" httpReq.getSession().getAttribute(csrfPreventionSalt) :----"+httpReq.getSession().getAttribute("csrfPreventionSalt"));
chain.doFilter(request, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
}
Run Code Online (Sandbox Code Playgroud)
web.xml 中的映射
<filter>
<filter-name>loadSalt</filter-name>
<filter-class>com.globalss.dnb.monitor.security.LoadSalt</filter-class>
</filter>
<filter-mapping>
<filter-name>loadSalt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Run Code Online (Sandbox Code Playgroud)
为了在执行安全事务之前验证盐,我编写了另一个过滤器:
public class ValidateSalt implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Assume its HTTP
HttpServletRequest httpReq = (HttpServletRequest) request;
//String salt = (String) httpReq.getSession().getAttribute("csrfPreventionSalt");
String salt =(String) httpReq.getAttribute("csrfPreventionSalt");
System.out.println("I am in ValidateSalt : salt: "+salt);
// Validate that the salt is in the cache
@SuppressWarnings("unchecked")
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>)
httpReq.getSession().getAttribute("csrfPreventionSaltCache");
if(csrfPreventionSaltCache !=null && salt !=null && csrfPreventionSaltCache.getIfPresent(salt)!=null)
{
// If the salt is in the cache, we move on
chain.doFilter(request, response);
}
else
{
// Otherwise we throw an exception aborting the request flow
throw new ServletException("Potential CSRF detected!! Inform a scary sysadmin ASAP.");
}
}
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
}
Run Code Online (Sandbox Code Playgroud)
web.xml 中第二个 Filetr 的映射
<filter>
<filter-name>validateSalt</filter-name>
<filter-class>com.globalss.dnb.monitor.security.ValidateSalt</filter-class>
</filter>
<filter-mapping>
<filter-name>validateSalt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Run Code Online (Sandbox Code Playgroud)
配置完两个 servlet 后,所有安全请求都失败了:)。为了解决这个问题,我必须向以安全 URL 结尾的每个链接和表单帖子添加 csrfPreventionSalt 参数,其中包含具有相同名称的请求参数的值。例如,在 JSP 页面内的 HTML 表单中:
<form action="/transferMoneyServlet" method="get">
<input type="hidden" name="csrfPreventionSalt" value="<c:out value='${csrfPreventionSalt}'/>"/>
...
</form>
Run Code Online (Sandbox Code Playgroud)
完成所有这些之后,我尝试尝试 CSRF,这就是我所做的
public class LoadSalt implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Assume its HTTP
HttpServletRequest httpReq = (HttpServletRequest)request;
// Check the user session for the salt cache, if none is present we create one
@SuppressWarnings("unchecked")
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>)
httpReq.getSession().getAttribute("csrfPreventionSaltCache");
System.out.println("Checking cahce befor creating it from Request :csrfPreventionSaltCache: "+csrfPreventionSaltCache);
if(csrfPreventionSaltCache == null)
{
System.out.println("csrfPreventionSaltCache is null have to create new one");
String csrfPreventionfromrequest = (String) httpReq.getSession().getAttribute("csrfPreventionSaltCache");
System.out.println("csrfPreventionfromrequest :"+csrfPreventionfromrequest);
// creating a new cache
csrfPreventionSaltCache = CacheBuilder.newBuilder().maximumSize(5000)
.expireAfterAccess(20, TimeUnit.MINUTES).build();
// Setting to gttpReq
httpReq.getSession().setAttribute("csrfPreventionSaltCache", csrfPreventionSaltCache);
System.out.println("After setting the csrfPreventionSaltCache to HttpReq");
System.out.println("--------csrfPreventionSaltCache------ :"+httpReq.getSession().getAttribute("csrfPreventionSaltCache"));
}
// Generate the salt and store it in the users cache
String salt = RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());
System.out.println("Salt: "+salt);
csrfPreventionSaltCache.put(salt, Boolean.TRUE);
// Add the salt to the current request so it can be used
// by the page rendered in this request
httpReq.setAttribute("csrfPreventionSalt", salt);
System.out.println("Before going to validate salt checking for salt in request");
System.out.println(" httpReq.getAttribute(csrfPreventionSalt) ----:"+httpReq.getAttribute("csrfPreventionSalt"));
// System.out.println(" httpReq.getSession().getAttribute(csrfPreventionSalt) :----"+httpReq.getSession().getAttribute("csrfPreventionSalt"));
chain.doFilter(request, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
}
Run Code Online (Sandbox Code Playgroud)
当我点击提交请求按钮时,我收到了成功响应,并且 CSRUser 已添加到我的数据库中。
我错过了什么吗?如何防止 CSRF 攻击?
您可以使用Spring Security进行用户身份验证和授权。从 Spring 3.2.0 版本开始,默认支持跨站请求伪造(CSRF) 。
您还可以使用 RequestMatcher 轻松排除不想保护的 URL:
public class CsrfSecurityRequestMatcher implements RequestMatcher {
private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("/unprotected", null);
@Override
public boolean matches(HttpServletRequest request) {
if(allowedMethods.matcher(request.getMethod()).matches()){
return false;
}
return !unprotectedMatcher.matches(request);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
36527 次 |
| 最近记录: |