## 前言
某些情况,大家的系统会被扫描出低危漏洞,描述如下:
```
1.未设置Content-Security-Policy或X-Content-Security-Policy响应头.
2.未设置Strict-Transport-Security响应头.
3.Set-Cookie未设置Secure标识.
4.Set-Cookie未设置HttpOnly标识.
```
处理方式也很简单,有Nginx和Java两种方式,我们更推荐从Nginx进行配置。
<br>
## 一、Nginx配置(推荐,性能更高,可灵活变动,不影响系统运行)
### 1. 在 Nginx 中添加安全 HTTP 响应头
可以通过 `add_header` 指令在 Nginx 配置中全局添加所需的 HTTP 响应头。
#### 示例 Nginx 配置:
```nginx
server {
listen 443 ssl;
server_name yourdomain.com;
# SSL 证书配置
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
# 确保客户端只能通过 HTTPS 访问
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 添加 Content-Security-Policy 头,限制资源加载来源
add_header Content-Security-Policy "default-src 'self';" always;
# 添加 X-Content-Type-Options 头,防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;
# 添加 X-Frame-Options 头,防止点击劫持,使用 SAMEORIGIN 来允许同源访问
add_header X-Frame-Options "SAMEORIGIN" always;
# 添加 X-XSS-Protection 头,防止 XSS 攻击
add_header X-XSS-Protection "1; mode=block" always;
# 添加 X-Permitted-Cross-Domain-Policies 头,阻止跨域策略文件被加载
add_header X-Permitted-Cross-Domain-Policies "none" always;
# 添加 X-Download-Options 头,防止文件被下载时自动打开
add_header X-Download-Options "noopen" always;
# 添加 Referrer-Policy 头,限制引荐来源的披露
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 处理反向代理请求
location / {
proxy_pass http://your_backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### 2. 全局设置 `Set-Cookie` 的 `Secure` 和 `HttpOnly` 标识
对于 `Set-Cookie` 头,你可以使用 `proxy_cookie_path` 和 `proxy_cookie_flags` 指令来修改 `Set-Cookie` 头,添加 `Secure` 和 `HttpOnly` 标识。
#### 示例 Nginx 配置:
```nginx
server {
listen 443 ssl;
server_name yourdomain.com;
# SSL 证书配置
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
# 确保客户端只能通过 HTTPS 访问
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 添加 Content-Security-Policy 头,限制资源加载来源
add_header Content-Security-Policy "default-src 'self';" always;
# 添加 X-Content-Type-Options 头,防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;
# 添加 X-Frame-Options 头,防止点击劫持,使用 SAMEORIGIN 来允许同源访问
add_header X-Frame-Options "SAMEORIGIN" always;
# 添加 X-XSS-Protection 头,防止 XSS 攻击
add_header X-XSS-Protection "1; mode=block" always;
# 添加 X-Permitted-Cross-Domain-Policies 头,阻止跨域策略文件被加载
add_header X-Permitted-Cross-Domain-Policies "none" always;
# 添加 X-Download-Options 头,防止文件被下载时自动打开
add_header X-Download-Options "noopen" always;
# 添加 Referrer-Policy 头,限制引荐来源的披露
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 为所有 Set-Cookie 头添加 Secure 标识(需要 HTTPS)
proxy_cookie_flags ~ Secure;
# 为所有 Set-Cookie 头添加 HttpOnly 标识
proxy_cookie_flags ~ HttpOnly;
# 处理反向代理请求
location / {
proxy_pass http://your_backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### 3. 配置说明
- **`add_header`**:用于在 HTTP 响应中添加自定义头。`always` 参数确保即使返回 4xx 或 5xx 错误代码时也会添加这些头。
- `Strict-Transport-Security`: 强制浏览器通过 HTTPS 访问,避免中间人攻击。
- `Content-Security-Policy`: 限制资源加载的来源,防止 XSS 攻击。
- `X-Content-Type-Options`: 防止 MIME 类型嗅探,避免浏览器解析错误的文件类型。
- `X-Frame-Options`: 防止点击劫持攻击。
- `X-XSS-Protection`: 启用浏览器的 XSS 过滤器,防止 XSS 攻击。
- **`proxy_cookie_flags`**:用于修改 `Set-Cookie` 头的标识。`~` 匹配所有 Cookie。
- `Secure`: 仅在 HTTPS 连接下发送 Cookie,避免 Cookie 在明文 HTTP 传输中被窃取。
- `HttpOnly`: 防止 JavaScript 访问 Cookie,减少 XSS 攻击的风险。
### 4. 其他安全头
你还可以根据需要添加其他安全头,例如:
- **Referrer-Policy**: 控制浏览器在发送 HTTP 请求时如何处理 `Referer` 头。
```nginx
add_header Referrer-Policy "no-referrer" always;
```
- **Permissions-Policy**: 控制浏览器的某些特性(如摄像头、麦克风等)的使用权限。
```nginx
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
```
### 5. 总结
通过在 Nginx 中配置这些安全头和 `Set-Cookie` 标识,你可以确保所有的请求和响应都符合安全要求,而不需要修改应用程序的代码。这样可以集中管理安全策略,并且对所有后端服务生效。
#### 要点:
- 使用 `add_header` 指令为响应添加安全头。
- 使用 `proxy_cookie_flags` 指令为所有 `Set-Cookie` 头添加 `Secure` 和 `HttpOnly` 标识。
- 确保 Nginx 配置文件正确无误后,重新加载 Nginx 配置。
通过这种方式,可以在 Nginx 层面上解决安全问题。
<br>
## 二、Java配置(不推荐,影响系统性能,不可灵活配置)
1. java可以用一个filter解决所有请求头、响应头的安全问题,具体范例如下:
```java
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;
@Component
public class SecurityHeadersFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化方法,可选
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// 设置Content-Security-Policy响应头
httpServletResponse.setHeader("Content-Security-Policy", "default-src 'self'");
// 设置Strict-Transport-Security响应头
httpServletResponse.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
// 继续处理请求
chain.doFilter(request, response);
// 拦截响应中的Set-Cookie头,添加Secure和HttpOnly标识
Collection<String> setCookieHeaders = httpServletResponse.getHeaders("Set-Cookie");
if (setCookieHeaders != null) {
// 将现有的Set-Cookie头处理并重新设置
Collection<String> modifiedCookies = setCookieHeaders.stream()
.map(cookie -> {
if (!cookie.toLowerCase().contains("secure")) {
cookie += "; Secure";
}
if (!cookie.toLowerCase().contains("httponly")) {
cookie += "; HttpOnly";
}
return cookie;
})
.collect(Collectors.toList());
// 先移除原有的Set-Cookie头
httpServletResponse.setHeader("Set-Cookie", null);
// 重新添加修改后的Set-Cookie头
for (String modifiedCookie : modifiedCookies) {
httpServletResponse.addHeader("Set-Cookie", modifiedCookie);
}
}
}
@Override
public void destroy() {
// 销毁方法,可选
}
}
```
2. 在 Spring Boot 中,过滤器会自动注册,但也可以通过 `@Bean` 显式注册过滤器。
```java
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<SecurityHeadersFilter> securityHeadersFilter() {
FilterRegistrationBean<SecurityHeadersFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new SecurityHeadersFilter());
registrationBean.addUrlPatterns("/*"); // 对所有请求生效
return registrationBean;
}
}
```
3. **`doFilter` 方法中的逻辑**:
* 首先,设置需要的安全响应头(如`Content-Security-Policy`和`Strict-Transport-Security`)。
* 然后,调用`chain.doFilter(request, response)`继续处理请求,这样后续的逻辑可以正常执行,并生成响应。
* 当响应生成后,我们获取所有的`Set-Cookie`头。
* 对每个`Set-Cookie`头进行处理,检查是否已经包含`Secure`和`HttpOnly`标识。如果没有,则自动添加这些标识。
* 最后,重新设置修改后的`Set-Cookie`头。
4. **处理流程**:
* 过滤器会在每个请求的响应阶段执行,确保所有的`Set-Cookie`头都被检查和修改(如果需要)。
* 这样,你就不需要在每次设置`Cookie`时手动处理`Secure`和`HttpOnly`标识了。
5. **注意事项**
* **HTTPS**:`Secure`标识仅在 HTTPS 连接下有效。如果你在本地开发时使用的是 HTTP,则`Secure`标识不会生效,只有在 HTTPS 环境下才会生效。
* **HttpOnly**:这个标识会阻止 JavaScript 访问`Cookie`,因此确保你不需要通过 JavaScript 访问这些`Cookie`。