web常见漏洞修复方法
内容锚点一、cookie问题1、httpOnly2、Cookies with missing, inconsistent or contradictory properties二、 Clickjacking 问题三、TLS/SSL LOGJAM attack四、HSTS问题一、cookie问题1、httpOnlyJava 解决方案let JSESSIONID = document.cookie.m
内容锚点
- 负、检测工具
- 零、测试加密套件方法 (nmap)
- 一、cookie问题
- 二、 Clickjacking 问题
- 三、TLS/SSL
- 四、HSTS问题
- 五、TLS 1.0 enabled
- 六、iframe问题
- 七、apache Log4j 远程漏洞执行问题
- 八、CSRF 处理 (Broken Access Control)
- 九、请求头相关问题
- 1、Missing or insecure "X-Content-Type-Options" header
- 2、Security Misconfiguration (Access-Control-Allow-Origin issue)
- 3、Content-Security-Policy header (CSP) was not configured properly (CSP Scanner: unsafe-inline/unsafe-eval)
- 4、Secure Pages Include Mixed Content
- 5、Strict-Transport-Security Multiple Header Entries
- 6、Cookie Without Secure Flag/Cookie without SameSite Attribute or with SameSite Attribute None
- 7、Re-examine Cache-control Directives
- 十、dom元素相关问题
负、检测工具
1、加密套件、协议兼容性、浏览器兼容性
1、https://www.ssllabs.com/ssltest/index.html
2、https://myssl.com/
通过域名检测
2、重大漏洞检测
http://0day.websaas.com.cn/
零、测试加密套件方法 (nmap)
安装方式:yum -y install nmap
可以告知你当前密码套件强度
nmap -sV --script ssl-enum-ciphers -p 443 www.example.com
[root@iZj6c2t7x4azg1onsgpzljZ nginxtest]# nmap -sV --script ssl-enum-ciphers -p 443 chatbot.hkpc.org
Starting Nmap 6.40 ( http://nmap.org ) at 2021-07-08 17:13 CST
Nmap scan report for www.example.com (xx.xxx.xx.xxx)
Host is up (0.0012s latency).
PORT STATE SERVICE VERSION
443/tcp open ssl/http Jetty
| ssl-enum-ciphers:
| SSLv3: No supported ciphers found
| TLSv1.2:
| ciphers:
| TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
| TLS_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_RSA_WITH_AES_128_CBC_SHA256 - strong
| TLS_RSA_WITH_AES_128_GCM_SHA256 - strong
| TLS_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_AES_256_CBC_SHA256 - strong
| TLS_RSA_WITH_AES_256_GCM_SHA384 - strong
| compressors:
| NULL
|_ least strength: strong
一、cookie问题
1、httpOnly / Secure
Java 解决方案
let JSESSIONID = document.cookie.match("JSESSIONID");
if(JSESSIONID){
console.log(JSESSIONID)
let exp = new Date();
exp.setTime(exp.getTime() + 7*24*60*60*1000);
document.cookie = JSESSIONID[0]+"="+JSESSIONID['input']+";Secure;Path=/;expires="+exp.toGMTString()+";"
}
jetty解决方案
//配置文件 etc/webdefault.xml
// 可以根据注释:<-- Default session configuration -->下来定位
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<secure>true</secure>
<http-only>true</http-only>
</cookie-config>
</session-config>
nginx 解决方案
//1、会直接设置当前的slb之类的cookies
proxy_cookie_path / "/; httponly; secure; SameSite=Lax";
//2、自定义设置cookie
//add_header Set-Cookie <cookie-name>=<cookie-value>; Path=/; HttpOnly; Secure;SameSite=strict;
//例如针对jetty 的JSESSIONID,我们需要用到aws的slb
// $cookie_{keyname} 可以直接获取值
//$http_cookie 是获取整个cookie
add_header Set-Cookie "JSESSIONID=$cookie_AWSALB ; Path=/; HttpOnly; Secure; SameSite=strict;";
2、Cookies with missing, inconsistent or contradictory properties
java解决方案
通常建议在拦截器增加
public class HttpLeakInterceptor implements HandlerInterceptor {
...
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null) {
Cookie cookie = cookies[0];
if (cookie != null) {
// serlvet 2.5 不支持在 Cookie 上直接设置 HttpOnly 属性.
String value = cookie.getValue();
StringBuilder builder = new StringBuilder();
builder.append("JSESSIONID=" + value + "; ");
builder.append("Secure; ");
builder.append("SameSite=strict; "); //主要是这段
builder.append("HttpOnly; ");
builder.append("path=/; ");
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR, 1);
Date date = calendar.getTime();
Locale locale = Locale.CHINA;
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss", locale);
builder.append("Expires=" + sdf.format(date));
httpServletResponse.setHeader("Set-Cookie", builder.toString());
}
}
}
...
}
jetty 解决方案(9.4.22+版本)
严格模式:__SAME_SITE_STRICT__
不使用:__SAME_SITE_NONE__
lax模式:__SAME_SITE_LAX__
//配置文件 etc/webdefault.xml
// 可以根据注释:<-- Default session configuration -->下来定位
<session-config>
<cookie-config>
<comment>__SAME_SITE_NONE__</comment>
</cookie-config>
</session-config>
二、 Clickjacking 问题
参考网站:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy
1、X-Frame-Options header
1、DENY
表示该页面不允许在frame中展示,即便是在相同域名的页面中嵌套也不允许。
2、SAMEORIGIN
表示该页面可以在相同域名页面的frame中展示。
3、ALLOW-FROM uri
表示该页面可以在指定来源的frame中展示。
java 解决方案
//基于过滤器处理
//例如:我需要允许的网站:http://www.coffeeandice.cn
...
package cn.coffeeandice.filters
...
@Component
public class LeakFilter implements Filter {
...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("X-Frame-Options", "ALLOW-FROM http://www.coffeeandice.cn");
chain.doFilter(request, resp);
}
...
}
若非springboot项目,还需要搭配web.xml配置过滤器
<!-- clickJacking -->
<filter>
<filter-name>LeakFilter</filter-name>
<filter-class>cn.coffeeandice.filters.LeakFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LeakFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
ngingx解决方案
//设:所需允许的网站为 https://www.coffeeandice.cn
add_header X-Frame-Options "ALLOW-FROM https://www.coffeeandice.cn";
2、CSP frame-ancestors missing
nginx解决方案
通常我们可以通过配置
Content-Security-Policy
处理可以多个数据源,中间只需要空格分隔即可
Content-Security-Policy: frame-ancestors <source> <source>;
通常两个策略:
self
: 设置一相信的域名,可以利用通配符*
單個域名: add_header Content-Security-Policy "frame-ancestors 'self' https://www.coffeeandice.cn"; 多個域名: 利用空格分隔 add_header Content-Security-Policy "frame-ancestors 'self' https://www.coffeeandice.cn https://www.coffeeandice.cn";
none
: 当该指令设置为none
时,其作用类似于X-Frame-Options: DENY
add_header Content-Security-Policy "frame-ancestors 'none'";
三、TLS/SSL
1、LOGJAM attack
参考网站:
https://weakdh.org/
总体建议是需要提升DHKey的长度,建议提升为2048
(Part A)jdk参数设置
jdk参数 -Djdk.tls.ephemeralDHKeySize = 2048
方式一: 直接设置jdk参数
方式二:设置jetty的启动参数
(Part B)jetty-ssl.xml文件配置
通常目录结构为
{Jetty_Home}/etc/
下
前提条件:在start.ini
中开启了这个模块配置 /etc/jetty.xml
TIps: 9.4.x之后迁移至jetty-ssl-context.xml
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
...
<Set name="ExcludeCipherSuites">
<Array type="String">
...
<!-- Disable cipher suites with Diffie-Hellman key exchange to prevent Logjam attack and avoid the ssl_error_weak_server_ephemeral_dh_key error in recent browsers -->
<Item>SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA</Item>
<Item>SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA</Item>
<Item>TLS_DHE_RSA_WITH_AES_256_CBC_SHA256</Item>
<Item>TLS_DHE_DSS_WITH_AES_256_CBC_SHA256</Item>
<Item>TLS_DHE_RSA_WITH_AES_256_CBC_SHA</Item>
<Item>TLS_DHE_DSS_WITH_AES_256_CBC_SHA</Item>
<Item>TLS_DHE_RSA_WITH_AES_128_CBC_SHA256</Item>
<Item>TLS_DHE_DSS_WITH_AES_128_CBC_SHA256</Item>
<Item>TLS_DHE_RSA_WITH_AES_128_CBC_SHA</Item>
<Item>TLS_DHE_DSS_WITH_AES_128_CBC_SHA</Item>
...
</Array>
</Set>
...
9.4.40后开启ssl启动时检查通用jks建议加上的排除套件如下
<Item>TLS_RSA_WITH_AES_256_GCM_SHA384</Item>
<Item>TLS_RSA_WITH_AES_128_GCM_SHA256</Item>
<Item>TLS_RSA_WITH_AES_256_CBC_SHA256</Item>
<Item>TLS_RSA_WITH_AES_128_CBC_SHA256</Item>
<Item>TLS_RSA_WITH_AES_256_CBC_SHA</Item>
<Item>TLS_RSA_WITH_AES_128_CBC_SHA</Item>
2023.4.10 更新记录
通过定期检测,发现需要额外增加以下内容使得通过安全检测
<Item>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384</Item>
<Item>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</Item>
<Item>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</Item>
<Item>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</Item>
2、Sweet32 attack / Weak Cipher Suites
其实两个问题都是围绕
TLS_RSA_WITH_3DES_EDE_CBC_SHA
这个加密套件处理
Sweet32 attack :主要是围绕 64位加密不安全的情况出现
Weak Cipher Suites:主要是这个加密套件强度不够,建议关闭
阿里雲SLB解決方案
负载均衡 SLB/配置监听 大于图示选项即可
jetty解决方案
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
...
<Set name="ExcludeCipherSuites">
<Array type="String">
...
<!-- Disable cipher suites with Diffie-Hellman key exchange to prevent Logjam attack and avoid the ssl_error_weak_server_ephemeral_dh_key error in recent browsers -->
<Item>TLS_RSA_WITH_3DES_EDE_CBC_SHA</Item>
...
<Array type="String">
</Set>
...
nginx 解决方案
nginx编译时需要考虑到openSSl版本问题
参考网站: https://www.openssl.org/news/secadv/20160922.txt
OpenSSL 1.0.2 users should upgrade to 1.0.2i
OpenSSL 1.0.1 users should upgrade to 1.0.1u
理论上nginx默认是: ssl_ciphers HIGH:!aNULL:!MD5;
只需要在后加上一个!3DES 即可
ssl_ciphers AES128+EECDH:AES128+EDH:!aNULL:!3DES;
四、HSTS问题
具体而言就是 HTTP Strict Transport Security (HSTS) not implemented
jetty解决方案
方式一:变更jetty-rewrite.xml( 这个模式内,不需要证书挂载再jetty下)
//在start.ini修改以下两个参数为rewrite
//#Module: rewrite
//--module=rewrite
//
//直接放置<configure></configure> 节点内
在jetty-rewrite.xml添加
<Ref refid="Rewrite">
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
<Set name="pattern">*</Set>
<Set name="name">Strict-Transport-Security</Set>
<Set name="value">max-age=31536000;includeSubDomains</Set>
</New>
</Arg>
</Call>
</Ref>
方式二: 变更 jetty-ssl.xml
通常为9.4+ version
初始默认值:
<New id="sslHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
<Arg><Ref refid="httpConfig"/></Arg>
<Call name="addCustomizer">
<Arg>
<New class="org.eclipse.jetty.server.SecureRequestCustomizer">
<Arg name="sniRequired" type="boolean"><Property name="jetty.ssl.sniRequired" default="false"/></Arg>
<Arg name="sniHostCheck" type="boolean"><Property name="jetty.ssl.sniHostCheck" default="true"/></Arg>
<Arg name="stsMaxAgeSeconds" type="int"><Property name="jetty.ssl.stsMaxAgeSeconds" default="-1"/></Arg>
<Arg name="stsIncludeSubdomains" type="boolean"><Property name="jetty.ssl.stsIncludeSubdomains" default="false"/></Arg>
</New>
</Arg>
</Call>
</New>
适配解决HSTS值:
主要是:
stsMaxAgeSeconds
及stsIncludeSubdomains
属性
<New id="sslHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
<Arg><Ref refid="httpConfig"/></Arg>
<Call name="addCustomizer">
<Arg>
<New class="org.eclipse.jetty.server.SecureRequestCustomizer">
<Arg name="sniRequired" type="boolean"><Property name="jetty.ssl.sniRequired" default="false"/></Arg>
<Arg name="sniHostCheck" type="boolean"><Property name="jetty.ssl.sniHostCheck" default="true"/></Arg>
<Arg name="stsMaxAgeSeconds" type="int"><Property name="jetty.ssl.stsMaxAgeSeconds" default="31536000"/></Arg>
<Arg name="stsIncludeSubdomains" type="boolean"><Property name="jetty.ssl.stsIncludeSubdomains" default="true"/></Arg>
</New>
</Arg>
</Call>
</New>
nginx解决方案
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
五、TLS 1.0 enabled
阿里雲SLB解決方案
负载均衡 SLB/配置监听 大于图示选项即可
java解决方案
理论上需要TLS1.1也需要禁用,内部通常有内容,往上添加即可
路径: {JAVA_HOME}/jre/lib/security/java.security
jdk.tls.disabledAlgorithms=TLSv1, TLSv1.1
nginx 解决方案
ssl_protocols TLSv1.2;
六、iframe问题
1、Insecure Inline Frame
主要是因为缺少sandbox属性,引入了外部资源
参数名称 | 参数说明 |
---|---|
allow-forms | 允许进行提交表单 |
allow-scripts | 运行执行脚本 |
allow-modals | 允许提示框,即允许执行window.alert()等会产生弹出提示框方法 |
allow-same-origin | 允许同域请求,比如ajax,storage |
allow-top-navigation | 允许iframe能够主导window.top进行页面跳转 |
allow-popups | 允许iframe中弹出新窗口,比如,window.open,target=“_blank” |
allow-popups-to-escape-sandbox | 允许弹出窗口不受沙箱的限制 ,针对谷歌和Edge拦截附件弹出网站奇效 |
allow-pointer-lock | 在iframe中可以锁定鼠标,主要和鼠标锁定有关 |
allow-downloads | 允许点击后下载文件 (83版本后新增) |
allow-top-navigation | 允许嵌入的网页对顶级窗口进行导航 |
allow-top-navigation-by-user-activation | 允许嵌入的网页对顶级窗口进行导航,但必须由用户激活。 |
allow-downloads-without-user-activation | 允许在没有征求用户同意的情况下下载文件 |
allow-storage-access-by-user-activation | 允许在用户激动的情况下,嵌入的网页通过 Storage Access API 访问父窗口的储存 |
建议例子:
sandbox=‘allow-forms allow-popups allow-same-origin allow-scripts allow-downloads’
七、apache Log4j 远程漏洞执行问题
实际上是属于v2版本的漏洞问题:
受影响版本为v2系列,Apache Log4j 2.x <= 2.15.0-rc2
参考漏洞链接:
国家漏洞共享平台:https://www.cnvd.org.cn/webinfo/show/7116
LunaSec:https://www.lunasec.io/docs/blog/log4j-zero-day
建议临时处置方式:
1)添加jvm启动参数-Dlog4j2.formatMsgNoLookups=true;
2)在应用classpath下添加log4j2.component.properties配置文件,文件内容为log4j2.formatMsgNoLookups=true;
3)JDK使用11.0.1、8u191、7u201、6u211及以上的高版本;
4)部署使用第三方防火墙产品进行安全防护。
八、CSRF 处理 (Broken Access Control)
这里通常是存在多种防御措施,
验证Referer
是这里的处理方式。
其他建议方式(基于网络搜寻)
1、尽量Post request
这里是可以针对性侦测,处理风险。
2、验证码处理 & 针对性 csrf token
采用二次验证的方式处理,当然这里多少会影响负载能力
这里也可以采用lua脚本的方式校验
3、验证Referer
主要采用校验Referer 与 Host 的方式处理
1、单域名处理
server {
listen 80;
server_name yourdomain.com;
location / {
# 检查请求的 Referer 头,这里已经正则匹配
if ($http_referer !~* "^https://yourdomain\.com/") {
return 403;
}
# 允许合法的请求继续到后端
proxy_pass http://backend_server;
}
}
2、多域名处理
可以采用
map模块
去匹配
./configure --add-module=src/http/modules/ngx_http_map_module
http {
map $http_referer $is_valid_referer {
default 0; # 默认情况下,禁止请求
"~^https://(www\.)?domain1\.com" 1;
"~^https://(www\.)?domain2\.com" 1;
"~^https://(www\.)?domain3\.com" 1;
# 添加其他受信任的域名
}
server {
listen 80;
server_name yourdomain.com;
location / {
if ($is_valid_referer = 0) {
return 403; # 拒绝无效 Referer 头的请求
}
# 处理请求
}
}
}
九、请求头相关问题
Tips:
如果下属内容需要页面嵌入到iframe中,需要将CSP & XFO 提前至顶部,避免内容被浏览器提前拦截
eg:add_header Content-Security-Policy "frame-ancestors 'self' https://www.coffeeandice.cn"; add_header X-Frame-Options "ALLOW-FROM https://www.coffeeandice.cn"; if ($http_referer !~ "https://[a-zA-Z0-9.-]+\.coffeeandice\.*$") { return 403; }
1、Missing or insecure “X-Content-Type-Options” header
建议
nginx
增加请求头X-Content-Type-Options
以避免对 MIME 类型 进行修改为可执行的内容
X-Content-Type-Options: nosniff
2、Security Misconfiguration (Access-Control-Allow-Origin issue)
主要是CORS问题,
nginx
增加域名限制使得浏览器可以正常执行拦截
2.1、配置内容
#1 、$http_origin 这里根据环境替换内容域名(server级别支持)
add_header "Access-Control-Allow-Origin" $http_origin;
#2、补充隐藏应用的头部,避免应用滥用 Access-Control-Allow-Origin: * “
proxy_hide_header 'Access-Control-Allow-Origin';
2.2、校验方法
1、检查响应头是否与设置的源一致。
2、通过http客户端,自行设置Referer header
看是否存在 * 滥用的情况,一般保持不变或不增加新行即可。
3、Content-Security-Policy header (CSP) was not configured properly (CSP Scanner: unsafe-inline/unsafe-eval)
unsafe-inline
:通常如果JavaScript没有设置nonce值的准备就开启这个。
object-src
: 禁止加载任何对象,通常是玄学插件 flash
add_header Content-Security-Policy "script-src 'self' 'unsafe-inline'; object-src 'none'";
这里建议正确遇到
Content-Security-Policy header (CSP) was not configured properly (CSP Scanner: unsafe-inline/unsafe-eval)
可以参照下属示例即可。
1、default-src 'self';
如果没有加载其他网站的需求,这里同源策略即可
2、script-src 'strict-dynamic';
这里主要是严格控制加载来源,默认全世界禁止,所以引出下一个配置
3、script-src-elem 'self';
用于控制script
的元素来源,是针对2的白名单
4、style-src 'self';
用于控制样式表的加载来源
5、frame-ancestors 'self' https://www.demo.com;
这里用于控制只能被什么网站来源以iframe
的格式加载,这里增加了一个例外https://www.demo.com
default-src 'self'; script-src 'strict-dynamic';script-src-elem 'self'; style-src 'self'; frame-ancestors 'self' https://www.demo.com
4、Secure Pages Include Mixed Content
指令会告诉浏览器将所有HTTP资源自动升级为HTTPS。
add_header Content-Security-Policy "upgrade-insecure-requests";
5、Strict-Transport-Security Multiple Header Entries
通常是属于存在多个HSTS的配置,我们需要考虑多个地方的配置是否存在折叠配置
1、F5、nginx上查看是否存在配置
2、服务的中间件是否存在配置,例如tomcat 和 jetty
这里以jetty为例子,校验start.ini
,检查--module=rewrite
,里面可以重写HSTS
3、程序中是否增加了内容配置。
校验方法
检查网络资源中的
strict-transport-security
是否仍存在多个内容,期望是一个内容
6、Cookie Without Secure Flag/Cookie without SameSite Attribute or with SameSite Attribute None
主要问题是静态内容设置了cookie 但是没有安全标识,这种通常出现在
前后端不分离
的项目。
思路:
1、源头上处理,cookies标签哪里发布,就从哪里设置,比如若是 不分离的项目,就要在程序中赋予配置。
2、容器相关只能是查漏补缺
7、Re-examine Cache-control Directives
主要是针对
页面缓存
相关处理,主要分为两种
1、完全放弃缓存(不缓存,不存储,必须重新验证)add_header Cache-Control "no-cache, no-store, must-revalidate";
2、开启缓存配置(公开的,最大时间N,不可更改)
expires 6h; # 设置缓存时间为6小时,这个不一定要配置,主要是提高兼容策略的效果 add_header Cache-Control "public, max-age=21600, immutable";
十、dom元素相关问题
1、Unsafe third-party link (target=“_blank”)
建议为每个a 标签中包含
target
的元素,添加 rel=“noopener noreferrer”
属性 | 描述 |
---|---|
noopener | 防止新打开的窗口能够通过 window.opener 访问到原始文档,从而提高安全性 |
noreferrer | 阻止浏览器发送原始文档的 Referer 头信息 |
<a href="https://example.com" target="_blank" rel="noopener noreferrer">打开新窗口</a>
更多推荐
所有评论(0)