负、检测工具

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值:

主要是:
stsMaxAgeSecondsstsIncludeSubdomains属性

  <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
LunaSechttps://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>

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐