Browse Source

安全扫描处理

dev-v1.0.2
庄锐波 3 months ago
parent
commit
41138b502b
  1. 80
      doc/部署说明/安全扫描.md
  2. 8
      doc/部署说明/部署过程描述.md
  3. 1
      ng/14/nginx.conf
  4. 158
      ng/14/源码安装nginx-1.26.3.md
  5. 23
      ng/3/nginx.conf
  6. 4
      zdxt-common/zdxt-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java
  7. 68
      zdxt-common/zdxt-common-satoken/src/main/java/org/dromara/common/satoken/core/jwt/PlusSaJwtTemplate.java
  8. 5
      zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java
  9. 5
      zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java
  10. 5
      zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java
  11. 5
      zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java
  12. 5
      zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java

80
doc/部署说明/安全扫描.md

@ -1,20 +1,60 @@
执法/企业端: # 安全扫描问题清单
1: 支持较老的 TLS 版本- 中 (已改)
2: 未实施加密- 中 (一期的https问题. 不好改变当前生产环境) ## 执法/企业端
3: 检测到 SHA-1 密码套件- 中 (已改)
| 序号 | 问题描述 | 风险等级 | 状态 |
监督端: |------|----------|----------|------|
1: JWT中的弱签名(3个) - 高 (已改) | 1 | 支持较老的 TLS 版本 | 中 | 已改 |
2: JWT过期(3个) - 高 (已改) | 2 | 未实施加密 | 中 | 未改(一期的 HTTPS 问题,不好改变当前生产环境) |
3: 易受攻击的组件(2个) - 高 | 3 | 检测到 SHA-1 密码套件 | 中 | 已改 |
4: 查询中的密码参数 - 高
5: SRI (Subresource Integrity) 的检查 - 中 ## 监督端
主机: | 序号 | 问题描述 | 风险等级 | 状态 |
.25: waf 我们动不了 |------|----------|----------|----|
- SSLV2和SSLV3 协议检测【原理扫描】 - 高 | 1 | JWT 中的弱签名(3个) | 高 | 已改 |
- 目标使用过期的TLS1.0 版协议【原理扫描】 - 中 | 2 | JWT 过期(3个) | 高 | 已改 |
.19: 目标主机showmount -e信息泄露(CVE-1999-0554) - 高 (同步服务器) | 3 | 易受攻击的组件(2个) | 高 | 已改 |
.3: 目标使用过期的TLS1.0 版协议【原理扫描】 - 中 (已改) | 4 | 查询中的密码参数 | 高 | 已改 |
.6: SSH 服务支持弱加密算法【原理扫描】 - 中 (已改) | 5 | SRI (Subresource Integrity) 的检查 | 中 | 已改 |
.5: SSH 服务支持弱加密算法【原理扫描】 - 中 (已改)
## 主机
| 主机 | 问题描述 | 风险等级 | 状态 |
|------|----------|----------|-----------|
| .25 | SSLV2 和 SSLV3 协议检测【原理扫描】 | 高 | WAF 我们动不了 |
| .25 | 目标使用过期的 TLS1.0 版协议【原理扫描】 | 中 | WAF 我们动不了 |
| .19 | 目标主机 showmount -e 信息泄露(CVE-1999-0554) | 高 | 已改 |
| .3 | 目标使用过期的 TLS1.0 版协议【原理扫描】 | 中 | 已改 |
| .6 | SSH 服务支持弱加密算法【原理扫描】 | 中 | 已改 |
| .5 | SSH 服务支持弱加密算法【原理扫描】 | 中 | 已改 |
## 等保测评项
### 监督端
| 编号 | 测试项 | 风险等级 |
|------|--------|----------|
| 4.2.1.1 | 验证码测试 | 低风险 |
| 4.2.1.2 | 认证错误提示 | 低风险 |
| 4.1.2 | 服务器指纹信息 | 低风险 |
| 4.2.3.3 | 业务数据机密性保护 | 高风险 |
| 4.2.3.4 | 个人信息机密性保护 | 高风险 |
| 4.2.2.4 | 基于用户身份的纵向越权操作测试 | 高风险 |
| 4.2.2.1 | 服务器敏感目录遍历 | 中风险 |
### 企业端
| 测试项 | 风险等级 |
|--------|----------|
| 验证码测试 | 低风险 |
| 认证错误提示 | 低风险 |
| 基于用户身份的横向越权测试 | 中风险 |
### 执法端
| 测试项 | 风险等级 |
|--------|----------|
| 验证码测试 | 低风险 |
| 认证错误提示 | 低风险 |
| 基于用户身份的横向越权测试 | 中风险 |

8
doc/部署说明/部署过程描述.md

@ -321,7 +321,15 @@ ng配置文件路径
--- ---
## 10.76.108.19 文件存储主服务器 ## 10.76.108.19 文件存储主服务器
1. 配置允许访问的 IP(仅允许业务服务器查询)
cat >> /etc/hosts.allow << 'EOF'
mountd: 10.76.108.1, 10.76.108.7, 10.76.108.8, 10.76.108.9, 10.76.108.10, 10.76.108.16
EOF
# 2. 拒绝所有其他主机
cat >> /etc/hosts.deny << 'EOF'
mountd: ALL
EOF
### NFS 挂载设置 ### NFS 挂载设置
``` ```

1
ng/14/nginx.conf

@ -80,7 +80,6 @@ http {
} }
} }
# zdxt-efcode-enforcement-app 执法端应用
server { server {
listen 12003; listen 12003;
listen [::]:12003; listen [::]:12003;

158
ng/14/源码安装nginx-1.26.3.md

@ -0,0 +1,158 @@
# 10.76.108.14 源码安装 nginx-1.26.3(麒麟V10 ARM64)
## 一、卸载旧版 yum 安装的 Nginx(如存在)
```bash
systemctl stop nginx
yum remove nginx nginx-mod-stream -y
```
## 二、安装编译依赖
```bash
yum install -y gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel
```
## 三、下载并解压源码
```bash
cd /usr/local/src
wget https://nginx.org/download/nginx-1.26.3.tar.gz
tar -zxvf nginx-1.26.3.tar.gz
cd nginx-1.26.3
```
> 如服务器无法访问外网,可先在本地下载后通过 scp 上传到 `/usr/local/src/` 目录。
## 四、配置编译参数
```bash
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib64/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-stream \
--with-stream_ssl_module \
--with-pcre
```
## 五、编译并安装
```bash
make -j$(nproc)
make install
```
## 六、创建 nginx 用户(如不存在)
```bash
id nginx 2>/dev/null || (groupadd nginx && useradd -r -g nginx -s /sbin/nologin nginx)
```
## 七、验证安装
```bash
/usr/sbin/nginx -v
# 应输出: nginx version: nginx/1.26.3
/usr/sbin/nginx -V 2>&1 | grep stream
# 应看到: --with-stream
```
## 八、配置 systemd 服务
```bash
cat > /usr/lib/systemd/system/nginx.service << 'EOF'
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
```
## 九、部署业务配置文件
将业务 nginx.conf 覆盖到配置路径:
```bash
# 备份默认配置
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
# 上传或编辑业务配置(注意:必须移除 include /usr/share/nginx/modules/*.conf; 这行)
vi /etc/nginx/nginx.conf
```
> **重要**:源码编译安装后,模块(stream、ssl等)已静态链接到二进制文件中,无需动态加载。
> 必须移除或注释掉配置文件中的 `include /usr/share/nginx/modules/*.conf;` 否则启动报错。
## 十、启动并设置开机自启
```bash
systemctl daemon-reload
systemctl start nginx
systemctl enable nginx
systemctl status nginx
```
## 十一、防火墙设置
```bash
firewall-cmd --state
firewall-cmd --list-all
firewall-cmd --add-port={80,85,445,81,12001,12002,12003,12004,12005}/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-all
```
## 十二、常用命令
| 操作 | 命令 |
|------|------|
| 测试配置并重载 | `/usr/sbin/nginx -t && systemctl reload nginx` |
| 查看状态 | `systemctl status nginx` |
| 启动 | `systemctl start nginx` |
| 停止 | `systemctl stop nginx` |
| 查看版本 | `/usr/sbin/nginx -v` |
| 查看错误日志 | `tail -f /var/log/nginx/error.log` |
## 路径说明
| 项目 | 路径 |
|------|------|
| 二进制文件 | /usr/sbin/nginx |
| 配置文件 | /etc/nginx/nginx.conf |
| 日志目录 | /var/log/nginx/ |
| PID 文件 | /run/nginx.pid |
## 注意事项
- 系统平台:银河麒麟 V10 ARM64 (aarch64)
- nginx 1.26.3 已修复 CVE-2022-41742 安全漏洞
- 配置文件中需添加 `server_tokens off;` 隐藏版本号进行安全加固
- 使用绝对路径 `/usr/sbin/nginx` 调用,因 sudo 的 secure_path 默认不包含 /usr/sbin

23
ng/3/nginx.conf

@ -107,12 +107,12 @@ http {
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
} }
# location /efcode20-sup-web/ { location /efcode20-sup-web/ {
# proxy_pass http://10.76.108.15:12004/; proxy_pass http://10.76.108.15:12004/;
# proxy_set_header Host $http_host; proxy_set_header Host $http_host;
# proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# } }
#location ~* /(uploads|images)/.*\.(php|php2|php3|php4|php5|phpm|phpml|phtml|phtm|phps|pht|asp|aspx|asa|cer|cdx|ashx|exe|sh|bash|jsp|jspx|jspa|html|web.config|cfm|cgi|war|ashx|htaccess|py|pl)$ { #location ~* /(uploads|images)/.*\.(php|php2|php3|php4|php5|phpm|phpml|phtml|phtm|phps|pht|asp|aspx|asa|cer|cdx|ashx|exe|sh|bash|jsp|jspx|jspa|html|web.config|cfm|cgi|war|ashx|htaccess|py|pl)$ {
#deny all; # 拦截.html和.htm文件,并返回403禁止访问 #deny all; # 拦截.html和.htm文件,并返回403禁止访问
#return 403; #return 403;
@ -316,7 +316,6 @@ http {
# } # }
#} #}
# HTTPS server # HTTPS server
# #
server { server {
@ -326,14 +325,14 @@ http {
ssl_certificate /usr/local/nginx/ssl/szssfj.cn.pem; ssl_certificate /usr/local/nginx/ssl/szssfj.cn.pem;
ssl_certificate_key /usr/local/nginx/ssl/szssfj.cn.key; ssl_certificate_key /usr/local/nginx/ssl/szssfj.cn.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_ciphers HIGH:!aNULL:!MD5:!3DES:!RC4:!DES:!EXPORT;
ssl_prefer_server_ciphers on; ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
root /usr/local/nginx/html; root /usr/local/nginx/html;
location /enterprisetest { location /enterprisetest {

4
zdxt-common/zdxt-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java

@ -1,12 +1,14 @@
package org.dromara.common.satoken.config; package org.dromara.common.satoken.config;
import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.jwt.SaJwtUtil;
import cn.dev33.satoken.jwt.StpLogicJwtForMixin; import cn.dev33.satoken.jwt.StpLogicJwtForMixin;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple; import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.StpInterface; import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.stp.StpLogic;
import org.dromara.common.core.factory.YmlPropertySourceFactory; import org.dromara.common.core.factory.YmlPropertySourceFactory;
import org.dromara.common.satoken.core.dao.PlusSaTokenDao; import org.dromara.common.satoken.core.dao.PlusSaTokenDao;
import org.dromara.common.satoken.core.jwt.PlusSaJwtTemplate;
import org.dromara.common.satoken.core.service.SaPermissionImpl; import org.dromara.common.satoken.core.service.SaPermissionImpl;
import org.dromara.common.satoken.handler.SaTokenExceptionHandler; import org.dromara.common.satoken.handler.SaTokenExceptionHandler;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
@ -26,6 +28,8 @@ public class SaTokenConfig {
public StpLogic getStpLogicJwt() { public StpLogic getStpLogicJwt() {
// Sa-Token 整合 jwt (简单模式) // Sa-Token 整合 jwt (简单模式)
//return new StpLogicJwtForSimple(); //return new StpLogicJwtForSimple();
// 注册自定义 SaJwtTemplate,补充标准 RFC 7519 exp 声明
SaJwtUtil.setSaJwtTemplate(new PlusSaJwtTemplate());
return new StpLogicJwtForMixin(); return new StpLogicJwtForMixin();
} }

68
zdxt-common/zdxt-common-satoken/src/main/java/org/dromara/common/satoken/core/jwt/PlusSaJwtTemplate.java

@ -0,0 +1,68 @@
package org.dromara.common.satoken.core.jwt;
import cn.dev33.satoken.jwt.SaJwtTemplate;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.hutool.jwt.JWT;
import java.util.Map;
/**
* 自定义 SaJwtTemplate在生成 JWT 时追加标准 RFC 7519 exp过期时间声明
* <p>
* Sa-Token 默认使用私有 eff 字段毫秒级不包含标准 exp秒级声明
* 某些安全扫描工具会标记缺少 exp 为合规风险因此在此扩展中补充 exp 字段
* </p>
*
* @author zdxt
*/
public class PlusSaJwtTemplate extends SaJwtTemplate {
/**
* RFC 7519 标准过期时间声明 key
*/
public static final String EXP = "exp";
/**
* 创建 jwt全参数方式 追加标准 exp 声明
*
* @param loginType 账号类型
* @param loginId 账号id
* @param deviceType 设备类型
* @param timeout token有效期 (单位 )
* @param extraData 扩展数据
* @param keyt 秘钥
* @return jwt-token
*/
@Override
public String createToken(String loginType, Object loginId, String deviceType,
long timeout, Map<String, Object> extraData, String keyt) {
// 计算 eff 有效期(Sa-Token 私有字段,毫秒级)
long effTime = timeout;
if (timeout != NEVER_EXPIRE) {
effTime = timeout * 1000 + System.currentTimeMillis();
}
// 计算标准 exp(RFC 7519,秒级 Unix 时间戳)
long expTime;
if (timeout == NEVER_EXPIRE) {
// 永不过期时,exp 设为一个极大值(100年后)
expTime = System.currentTimeMillis() / 1000 + 100L * 365 * 24 * 3600;
} else {
expTime = System.currentTimeMillis() / 1000 + timeout;
}
// 创建 JWT 并追加 exp 声明
JWT jwt = JWT.create()
.setPayload(LOGIN_TYPE, loginType)
.setPayload(LOGIN_ID, loginId)
.setPayload(DEVICE_TYPE, deviceType)
.setPayload(EFF, effTime)
.setPayload(EXP, expTime)
// 塞入一个随机字符串,防止同账号同一毫秒下每次生成的 token 都一样的
.setPayload(RN_STR, SaFoxUtil.getRandomString(32))
.addPayloads(extraData);
// 返回签名后的 token
return generateToken(jwt, keyt);
}
}

5
zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java

@ -60,10 +60,7 @@ public class EmailAuthStrategy implements IAuthStrategy {
loginUser.setDeviceType(client.getDeviceType()); loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter(); SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType()); model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 // 不从数据库读取超时配置,统一使用全局 yml 默认配置(timeout: 86400, active-timeout: 1800)
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);

5
zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java

@ -76,10 +76,7 @@ public class PasswordAuthStrategy implements IAuthStrategy {
loginUser.setDeviceType(client.getDeviceType()); loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter(); SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType()); model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 // 不从数据库读取超时配置,统一使用全局 yml 默认配置(timeout: 86400, active-timeout: 1800)
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);

5
zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java

@ -60,10 +60,7 @@ public class SmsAuthStrategy implements IAuthStrategy {
loginUser.setDeviceType(client.getDeviceType()); loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter(); SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType()); model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 // 不从数据库读取超时配置,统一使用全局 yml 默认配置(timeout: 86400, active-timeout: 1800)
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);

5
zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java

@ -90,10 +90,7 @@ public class SocialAuthStrategy implements IAuthStrategy {
loginUser.setDeviceType(client.getDeviceType()); loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter(); SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType()); model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 // 不从数据库读取超时配置,统一使用全局 yml 默认配置(timeout: 86400, active-timeout: 1800)
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);

5
zdxt-web-server/zdxt-admin-web-server/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java

@ -78,10 +78,7 @@ public class XcxAuthStrategy implements IAuthStrategy {
SaLoginParameter model = new SaLoginParameter(); SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType()); model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 // 不从数据库读取超时配置,统一使用全局 yml 默认配置(timeout: 86400, active-timeout: 1800)
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 生成token // 生成token
LoginHelper.login(loginUser, model); LoginHelper.login(loginUser, model);

Loading…
Cancel
Save