我们项目上线前都经过漏洞扫描,并针对漏扫报告修改存在的漏洞,每次扫描都有2个关于cookie方面的漏扫(漏洞级别属于低),漏洞名字分别是:Cookie No HttpOnly Flag 和 Cookie Without SameSite Attribute。每次上线前漏扫,测试同事都催着让改(由于属于低级别漏洞,都一直拖着),我看以前同事改过几次,但是都没起作用,漏洞还存在。所以就研究一下,自己做下总结。
关于这2个漏洞简单介绍
Cookie No HttpOnly Flag:没有安全标签的cookie,需要把httponly属性设置为true;这样就可以防止跨站脚本攻击XSS(Cross Site script)。
Cookie Without SameSite Attribute: 意思cookie的samesite属性设置了none,当samesite=none时,有可能存在跨站请求伪造CSRF(cross site request forgery)攻击的风险。samesite属性有三个值:Strict/Lax/None。具体意思大家自行百度吧。我们这里把samesite设置成Lax就可以了。
错误的解决方案
我也在网上查了很多资料,都是写个过滤器filter,然后在response里设置下,大概代码如下:
response.setHeader("SameSite","Lax");
response.setHeader("Set-Cookie","HttpOnly");
其实我们就是这么改的,但是不生效,这2个漏洞还存在。在浏览器F12下看相关信息截图如下:
在响应头里确实有了这个2个属性,由于前期对cookie的这2个属性不了解,以为这样就可以了,但是这是无法解决这2个漏洞的。
错误解决方案的代码如下
:
package com.lsl.mylsl.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CookieFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
//这里模拟下浏览器发送请求中包含三个cookie,
// 因为后端在request中无法添加cookie,咱们就先添加到response中,
//第一次请求把三个cookie带到客户端,再请求时浏览器就把这三个cookie带过来了
Cookie cookie1 = new Cookie("name","lsl");
httpResponse.addCookie(cookie1);
Cookie cookie2 = new Cookie("age","18");
httpResponse.addCookie(cookie2);
Cookie cookie3 = new Cookie("addr","beijing");
httpResponse.addCookie(cookie3);
httpResponse.setHeader("SameSite","Lax");
httpResponse.setHeader("Set-Cookie","HttpOnly");
filterChain.doFilter(httpRequest,httpResponse);
如果解决了这2个漏洞,正确的截图如下:
图2:下图红色框上面的也有三个set-cookie属性,分别有三个cookie,但是后面没有httponly和samesite属性。原因我在代码里模拟了客户端发送请求里放了三个cookie。这是第一次请求时添加的heeader属性,红色框里是第二次请求request才把三个cookie带过来,所以才有这2个属性。大家可以看后面附的正确解决方案的代码
正确方案的代码如下:
package com.lsl.mylsl.filter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CookieFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
//这里模拟下浏览器发送请求中包含三个cookie,
// 因为后端在request中无法添加cookie,咱们就先添加到response中,
//第一次请求把三个cookie带到客户端,再请求时浏览器就把这三个cookie带过来了
Cookie cookie1 = new Cookie("name","lsl");
httpResponse.addCookie(cookie1);
Cookie cookie2 = new Cookie("age","18");
httpResponse.addCookie(cookie2);
Cookie cookie3 = new Cookie("addr","beijing");
httpResponse.addCookie(cookie3);
String url = httpRequest.getRequestURL().toString();
Cookie[] cookies = httpRequest.getCookies();
if (cookies != null){
StringBuilder sb = new StringBuilder();
for (Cookie cookie : cookies){
String cookieName = cookie.getName();
String cookieValue = cookie.getValue();
System.out.println("url = " + url + ", cookieName = " + cookieName + ", cookieValue = " + cookieValue);
ResponseCookie lastCookie = ResponseCookie.from(cookieName, cookieValue).httpOnly(true).sameSite("Lax").build();
httpResponse.addHeader(HttpHeaders.SET_COOKIE,lastCookie.toString());
filterChain.doFilter(httpRequest,httpResponse);
发现没有,我正确的解决方案里除了遍历了cookie,添加属性时用的是response.addHeader("Set-cookie",String)方法,而错误的解决方案中用的是response.setHeader("Set-Cookie",String)方法。
httponly和samesite属性是属于cookie的,所以必须遍历所有cookie,并设置这些相关属性,当然cookie还有其他好多属性(domain,path,maxAge等)。错误方案里只是给响应头添加了属性,所以没法解决这2个漏洞问题。对应请求中有多个cookie,必须用addHeader方法,如果只有一个cookie可以使用setHeader方法。
response.addHeader()和response.setHeader的区别
这2个方法都是给response的header添加属性,但是略有区别,
response.setHeader():如果存在key就替换value
response.addHeader(): 如果key存在也不替换value,而是增加
这里我先说下Set-Cookie属性,其实是一个cookie对应一个Set-Cookie属性,我开始以为是Set-Cookie里放所有cookie,然后后面的httponly等属性一起修饰前面的cookie。其实不是的,当然如果你一个Set-Cookie属性了前面放了多个cookie,后面的httponly; SameSite=Lax 属性只对第一个cookie生效,这个我测试过了。代码和截图如下:
package com.lsl.mylsl.filter;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CookieFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
//这里模拟下浏览器发送请求中包含三个cookie,
// 因为后端在request中无法添加cookie,咱们就先添加到response中,
//第一次请求把三个cookie带到客户端,再请求时浏览器就把这三个cookie带过来了
Cookie cookie1 = new Cookie("name","lsl");
httpResponse.addCookie(cookie1);
Cookie cookie2 = new Cookie("age","18");
httpResponse.addCookie(cookie2);
Cookie cookie3 = new Cookie("addr","beijing");
httpResponse.addCookie(cookie3);
String url = httpRequest.getRequestURL().toString();
Cookie[] cookies = httpRequest.getCookies();
if (cookies != null){
StringBuilder sb = new StringBuilder();
for (Cookie cookie : cookies){
String cookieName = cookie.getName();
String cookieValue = cookie.getValue();
System.out.println("url = " + url + ", cookieName = " + cookieName + ", cookieValue = " + cookieValue);
// ResponseCookie lastCookie = ResponseCookie.from(cookieName, cookieValue).httpOnly(true).sameSite("Lax").build();
sb.append(cookieName).append("=").append(cookieValue).append(";");
sb.append("HttpOnly; SameSite=Lax");
httpResponse.addHeader(HttpHeaders.SET_COOKIE,sb.toString());
filterChain.doFilter(httpRequest,httpResponse);
我们再说下,response.addHeader("Set-cookie",String)和response.setHeader("Set-Cookie",String)的区别。根据上面的正确代码可以看出,如果采用response.setHeader("Set-Cookie",String),只是把最后一个cookie设置的httponly和sameSite属性生效了。这个2个方法我也都测试过了。
用setHeader方法,只有最后一个cookie生效了,相关的代码和截图如下:
package com.lsl.mylsl.filter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CookieFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
//这里模拟下浏览器发送请求中包含三个cookie,
// 因为后端在request中无法添加cookie,咱们就先添加到response中,
//第一次请求把三个cookie带到客户端,再请求时浏览器就把这三个cookie带过来了
Cookie cookie1 = new Cookie("name","lsl");
httpResponse.addCookie(cookie1);
Cookie cookie2 = new Cookie("age","18");
httpResponse.addCookie(cookie2);
Cookie cookie3 = new Cookie("addr","beijing");
httpResponse.addCookie(cookie3);
String url = httpRequest.getRequestURL().toString();
Cookie[] cookies = httpRequest.getCookies();
if (cookies != null){
StringBuilder sb = new StringBuilder();
for (Cookie cookie : cookies){
String cookieName = cookie.getName();
String cookieValue = cookie.getValue();
System.out.println("url = " + url + ", cookieName = " + cookieName + ", cookieValue = " + cookieValue);
ResponseCookie lastCookie = ResponseCookie.from(cookieName, cookieValue).httpOnly(true).sameSite("Lax").build();
httpResponse.setHeader(HttpHeaders.SET_COOKIE,lastCookie.toString());
filterChain.doFilter(httpRequest,httpResponse);
解决漏扫cookie漏洞:Cookie No HttpOnly Flag和Cookie Without SameSite Attribute。设置cookie的httponly和samesite属性。
一、属性说明:
1 secure属性
当设置为true时,表示创建的 Cookie 会被以安全的形式向服务器传输,也就是只能在 HTTPS 连接中被浏览器传递到服务器端进行会话验证,如果是 HTTP 连接则不会传递该信息,所以不会被窃取到Cookie 的具体内容。
2 HttpOnly属性
如果在Cookie中设置了"HttpOnly"属性,那么通过程序(JS脚本、Applet等)将无法读取到Cookie信息,这样能有效的防止XSS攻击。
对于以上两个属性,
首先,secure属性是防止信息在传递的过程中被监听捕获后信息泄漏,HttpOnly属性的目的是防止程序获取cookie后进行攻击。
其次,GlassFish2.x支持的是servlet2.5,而servlet2.5不支持Session Cookie的"HttpOnly"属性。不过使用Filter做一定的处理可以简单的实现HttpOnly属性。GlashFish3.0(支持servlet3.0)默认开启Session Cookie的HttpOnly属性。
也就是说两个属性,并不能解决cookie在本机出现的信息泄漏的问题(FireFox的插件FireBug能直接看到cookie的相关信息)。
项目架构环境:jsp+servlet+applet
一、HttpOnly的简介
HttpOnly是Cookie中一个属性,用于防止客户端脚本通过document.cookie属性访问Cookie,有助于保护Cookie不被跨站脚本攻击窃取或篡改。但是,HttpOnly的应用仍存在局限性,一些浏览器可以阻止客户端脚本对Cookie的读操作,但允许写操作;此外大多数浏览器仍允许通过XMLHTTP对象读取HTTP响应中的Set-Cookie头。
二、使用方式
Set-Cookie: <cookie-name>=<cookie-value
漏洞说明
在用webinspect工具对web项目进行扫描,会报一下两种错误:1.Cookie中缺少HttpOnly属性;2.Cookie中缺少Secure属性。
HttpOnly属性
浏览器通过document对象获取Cookie。HttpOnly作为保护Cookie安全的一个属性,一旦被设置,document对象便看不到Cookie了,同时,浏览器在访问网页时不受任何影响,因为Cookie...
目录1、概述2、分析2.1、Samesite属性是个啥?2.2、Strict2.3、Lax2.4、None
最近,用APPSCAN对网站进行扫描,结果报了一个“具有不安全、不正确或缺少SameSite属性的Cookie”的漏洞。
2.1、Samesite属性是个啥?
为了从源头上解决CSRF(跨站请求伪造)攻击,Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cooki
SameSite 属性相对项目的 javax.servlet-api:3.1.0还是太新了,而项目是 Spring 的,并且 Cookie 并没有 SameSite 这个属性,那么对于新的浏览器(chrome 80 之后等)多了 SameSite 属性,比如说单点登录这种,导致没有带上 token 而用户一直登录不了,现在就得给cookie带上 SameSite。
SameSite:
防止第三方恶意 CSRF 攻击,所以用于控制第三方 Cookie,有 ...
在Web开发中,可以通过设置Cookie的HttpOnly属性来增强其安全性。HttpOnly是一种安全标志,用于限制Cookie的访问权限。当设置了HttpOnly属性后,浏览器将禁止通过JavaScript访问和修改Cookie,从而有效地防止一些常见的攻击,如跨站脚本攻击(XSS)。\[1\]
通过在Cookie中设置HttpOnly属性为true,兼容的浏览器接收到HttpOnly Cookie后,客户端通过程序(如JavaScript脚本、Applet等)将无法读取到Cookie信息。这有助于缓解跨站点脚本威胁,提高网站的安全性。\[2\]
需要注意的是,HttpOnly是微软对Cookie做的扩展,该属性的值指定了Cookie是否可通过客户端脚本访问。Microsoft Internet Explorer版本6 Service Pack 1及更高版本支持Cookie属性HttpOnly。\[3\]
#### 引用[.reference_title]
- *1* [什么是 cookie 的 httponly 属性](https://blog.csdn.net/i042416/article/details/131263746)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item]
- *2* *3* [HttpOnly的设置](https://blog.csdn.net/willie_chen/article/details/81363234)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item]
[ .reference_list ]