文章目次
- 前言
- 一、服务器侧等保测评项目及加固
- 1、服务器未启用暗码长度以及口令复杂度、且未定期更新口令
- 2、服务器未限定非法登录次数,未设置登录毗连超时自动退出
- 3、服务器只采用暗码技能对用户的身份进行鉴别,未采用双因子认证;服务器未限定管理终端登录
- 4、Rc3.d文件权限过大755
- 5、未有第三方审计系统,未对审计记录进行定期备份
- 6、服务器未安装杀毒
- 二、MySql数据库等保加固
- 1、采用用户名+口令进行身份鉴别,未启用口令复杂度策略,未定期更换口令
- 2、未启用登录失败处置惩罚功能,未有登录毗连超时退出策略
- 3、采用用户名+口令验证码进行身份鉴别,未实现使用两种或两种以上组合鉴别技能进行身份鉴别,未实现双因子登录;未对接入方式或网络地址范围进行限定且网络不可控
- 4、未实现管理用户的最小权限分离
- 5、未有加密技能保证数据在传输过程中的完备性;
- 6、未定期进行数据备份规复测试功能
- 三、中间件版本过低产生的各种漏洞
- 四、Harbor 访问控制错误漏洞
- 五、Swagger API 未授权访问漏洞
- 六、服务器常见安全加固脚本分享
- 总结
前言
安全等级测评的目标是通过对目标系统在安全技能及管理方面的测评,对目标系统的安全技能状态及安全管理状态做出开端判断,给出目标系统在安全技能及安全管理方面与其相应安全等级保护要求之间的差距。测评结论作为委托方进一步完善系统安全策略及安全技能防护步伐依据
一、服务器侧等保测评项目及加固
1、服务器未启用暗码长度以及口令复杂度、且未定期更新口令
- 整改建议:
- 建议修改密码长度、口令复杂度以及定期90天更换口令。
-
- 整改方法:
- logindefs(){
- echo "---口令生存期---"
- cp -p /etc/login.defs /etc/login.defs_bak
- sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/g' /etc/login.defs
- sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 10/g' /etc/login.defs
- sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 7/g' /etc/login.defs
- }
- system_auth_crack(){
- echo "---口令复杂度及密码长度---"
- # 判断 system-auth 配置文件中是否包含 password requisite pam_cracklib.so 的配置
- if grep -q 'password requisite pam_cracklib.so' /etc/pam.d/system-auth; then
- # 如果有,则使用 sed 命令替换原有的行
- sed -i 's/^password.*requisite.*pam_cracklib.so$/& try_first_pass retry=3 dcredit=-1 lcredit=-1 ucredit=-1 ocredit=-1 minlen=8/g' /etc/pam.d/system-auth
- else
- # 如果没有,则添加新的一行
- echo "password requisite pam_cracklib.so try_first_pass retry=3 dcredit=-1 lcredit=-1 ucredit=-1 ocredit=-1 minlen=8" >> /etc/pam.d/system-auth
- fi
- }
复制代码 2、服务器未限定非法登录次数,未设置登录毗连超时自动退出
- 整改建议:
- 建议限制非法登录次数;设置登录连接超时自动退出,如:连续登录3次锁定10分钟,并无操作10分钟自动退出。
-
- 整改方法:
- login_timeout(){
- # 检查 /etc/profile 文件是否存在
- if [ ! -f /etc/profile ]; then
- echo "/etc/profile 文件不存在"
- exit 1
- fi
-
- # 使用 sed 命令检查文件末尾是否已经存在所需的两行内容,不存在则添加
- if ! grep -q '^TMOUT=' /etc/profile; then
- echo 'TMOUT=300' >> /etc/profile
- else
- sed -i 's/^TMOUT=.*/TMOUT=300/' /etc/profile
- fi
-
- if ! grep -q '^export TMOUT' /etc/profile; then
- echo 'export TMOUT' >> /etc/profile
- fi
- }
复制代码 3、服务器只采用暗码技能对用户的身份进行鉴别,未采用双因子认证;服务器未限定管理终端登录
- 整改建议:
- 服务器只采用密码技术对用户的身份进行鉴别,未采用双因子认证。
- 因为维护的项目都是通过vpn(短信验证)-->堡垒机(短信验证)-->登录服务器,最后沟通这项可以按如下修复。即服务器配置ssh白名单,只允许堡垒机登录
-
- 整改方法:
- vim /etc/hosts.deny #添加以下配置
- sshd:all:deny
- vim /etc/hosts.allow #添加以下配置
- sshd:堡垒机IP:allow
复制代码 4、Rc3.d文件权限过大755
- 整改建议:
- 建议修改rc3.d的读写权限为755以下
-
- 整改方法:
- chmod 644 -R /etc/rc.d/rc3.d
复制代码 5、未有第三方审计系统,未对审计记录进行定期备份
- 整改建议:
- 未有第三方审计系统,未对审计记录进行定期备份;
- 整改方法:
- 1、服务器开启audit服务
- 2、使用aidutctl -l命令查看审计策略
- 3、使用auditctl -w 路径/文件 -p 权限 命令对文件或目录配置审计策略
- 补充: 使用auditctl -W 路径/文件 -p 权限 命令是取消审计策略
- 4、使用ausearch -f 配置的路径/文件 查看对应的审计日志
- 5、使用AuditLogSync.py脚本+ip_address.txt文件实现将全部服务器的audit.log日志备份并同步到日志归档服务器。脚本如下所示
- 6、在日志归档服务器配置定时同步,即可
- [root@LogArchive]# crontab -e
- * */23 * * * /usr/bin/python3 -W ignore /path/AuditLogSync.py
复制代码- #!/usr/bin/env python3
- #Date: 202403212005
- import os
- import time
- import paramiko
- import logging
- from datetime import datetime
- import threading
- import inspect
-
-
- class AuditLogSync:
- def __init__(self, ip_file,audit_path,username,password,port):
- """
- 初始化AuditLogSync类
-
- Parameters:
- ip_file (str): 包含IP地址列表的文件路径
- audit_path (str): 审计日志路径
- username (str): 用户名
- password (str): 密码
- port (int): 端口
- """
- self.ip_file = ip_file
- self.audit_path=audit_path
- self.username = username
- self.password = password
- self.port = port
- #生成日期
- self.current_time = datetime.now().strftime("%Y%m%d")
- #生成审计日志归档目录
- self.export_dir = f"/export/AuditLogSync/{self.current_time}"
- #生成执行日志
- self.info_log_file = "/export/AuditLogSync/sync_info.log"
- self.error_log_file = "/export/AuditLogSync/sync_error.log"
- # 设置 info 日志记录器
- self.info_logger = logging.getLogger('info_logger')
- info_handler = logging.FileHandler(self.info_log_file)
- info_handler.setLevel(logging.INFO)
- info_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
- info_handler.setFormatter(info_formatter)
- self.info_logger.addHandler(info_handler)
- self.info_logger.setLevel(logging.INFO)
- # 设置 error 日志记录器
- self.error_logger = logging.getLogger('error_logger')
- error_handler = logging.FileHandler(self.error_log_file)
- error_handler.setLevel(logging.ERROR)
- error_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
- error_handler.setFormatter(error_formatter)
- self.error_logger.addHandler(error_handler)
- #判断审计日志归档目录是否存在
- if not os.path.exists(self.export_dir):
- os.makedirs(self.export_dir)
-
- def run_operations(self):
- """
- 运行一系列操作:连接到服务器,打包日志文件,执行rsync同步
- """
- # 从文件中读取IP地址列表
- with open(self.ip_file, 'r') as file:
- ip_addresses = file.readlines()
- threads= []
- # 拿到ip地址调用连接服务器方法
- for ip_address in ip_addresses:
- ip_address = ip_address.strip()
- # 创建线程并启动,不采用多线程容易卡死
- thread = threading.Thread(target=self.process_server, args=(ip_address,))
- threads.append(thread)
- thread.start()
- #ssh_client = self.connect_to_server(ip_address)
- #判断服务器连接是否成功,如果成功调用打包审计日志方法、执行rsync同步方法,最后关闭连接
- #if ssh_client is not None:
- # self.package_logs(ssh_client, ip_address)
- # self.execute_rsync(ssh_client, ip_address)
- # ssh_client.close()
- # 等待所有线程完成
- for thread in threads:
- thread.join()
- def process_server(self, ip_address):
- """
- 处理单个服务器的操作
- """
- ssh_client = self.connect_to_server(ip_address)
- #判断服务器连接是否成功,如果成功调用打包审计日志方法、执行rsync同步方法,最后关闭连接
- if ssh_client is not None:
- self.package_logs(ssh_client, ip_address)
- self.execute_rsync(ssh_client, ip_address)
- ssh_client.close()
- def connect_to_server(self, ip_address):
- """
- 建立SSH连接到远程服务器
-
- Parameters:
- ip_address (str): 目标服务器的IP地址
-
- Returns:
- paramiko.SSHClient: SSH客户端对象
- """
- ssh_client = paramiko.SSHClient()
- ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- try:
- ssh_client.connect(ip_address, username=self.username, password=self.password, port=self.port,timeout=20)
- self.info_logger.info(f"成功连接到服务器 {ip_address} - {inspect.currentframe().f_code.co_name}")
- except paramiko.ssh_exception.AuthenticationException:
- self.error_logger.error(f"连接服务器失败 {ip_address}. 请检查服务器信息是否正确 - {inspect.currentframe().f_code.co_name}")
- return None
-
- return ssh_client
-
- def package_logs(self, ssh_client, ip_address):
- """
- 打包远程服务器上的日志文件
-
- Parameters:
- ssh_client (paramiko.SSHClient): SSH客户端对象
- ip_address (str): 目标服务器的IP地址
- """
- check_dir_cmd = f"""
- if [ -d {self.audit_path} ]; then
- echo 'Directory exists'
- else
- echo 'Directory does not exist'
- fi
- """
- stdin, stdout, stderr = ssh_client.exec_command(check_dir_cmd)
- dir_check_output = stdout.read().decode('utf-8')
- if "Directory exists" in dir_check_output:
- self.info_logger.info(f"{ip_address}: 审计日志目录 {self.audit_path} 存在 - {inspect.currentframe().f_code.co_name}")
- tar_cmd = f"cd {self.audit_path} && tar -zcf /tmp/{ip_address}_{self.current_time}_audit.tar.gz ."
- stdin, stdout, stderr = ssh_client.exec_command(tar_cmd)
- exit_status = stdout.channel.recv_exit_status()
-
- # 判断打包是否成功
- if exit_status == 0:
- self.info_logger.info(f"{ip_address}: 审计日志打包成功 - {inspect.currentframe().f_code.co_name}")
- else:
- self.error_logger.error(f"{ip_address}: 审计日志打包失败 - {stderr.read().decode('utf-8')} - {inspect.currentframe().f_code.co_name}")
- else:
- self.error_logger.error(f"{ip_address}: 审计日志目录 {self.audit_path} 不存在 - {inspect.currentframe().f_code.co_name}")
- def execute_rsync(self, ssh_client, ip_address):
- """
- 执行rsync同步操作
-
- Parameters:
- ssh_client (paramiko.SSHClient): SSH客户端对象
- ip_address (str): 目标服务器的IP地址
- """
- rsync_check_cmd = "which rsync"
- stdin, stdout, stderr = ssh_client.exec_command(rsync_check_cmd)
- #调试
- #print(f"execute_rsync_stdout: {stdout.read().decode('utf-8')}")
- if "rsync" not in stdout.read().decode('utf-8'):
- install_rsync_cmd = "yum -y install rsync"
- ssh_client.exec_command(install_rsync_cmd)
- #安装rsync命令可能需要20s左右
- self.info_logger.info(f"{ip_address}: 安装rsync中,请等待... - {inspect.currentframe().f_code.co_name}")
- time.sleep(20)
- # 再次检查rsync命令是否安装成功
- stdin, stdout, stderr = ssh_client.exec_command(rsync_check_cmd)
- if "rsync" not in stdout.read().decode('utf-8'):
- self.error_logger.error(f"{ip_address} 安装rsync失败 - {inspect.currentframe().f_code.co_name}")
- return
- # 已经安装rsync,执行目标服务器的操作
- rsync_cmd = f"rsync -az -e 'ssh -p {self.port}' {self.username}@{ip_address}:/tmp/{ip_address}_{self.current_time}_audit.tar.gz {self.export_dir}"
- os.system(rsync_cmd)
- self.info_logger.info(f"{ip_address}: 审计日志压缩包同步成功 - {inspect.currentframe().f_code.co_name}")
- # 删除远程服务器上的tar包
- delete_tar_cmd = f"rm /tmp/{ip_address}_{self.current_time}_audit.tar.gz"
- ssh_client.exec_command(delete_tar_cmd)
- self.info_logger.info(f"{ip_address}: 成功删除远程服务器上的tar包 - {inspect.currentframe().f_code.co_name}")
-
- def delete_old_archive_logs(self, ssh_client):
- # 删除旧归档日志目录方法
- check_archive_cmd = f"find /export/AuditLogSync/ -mindepth 1 -maxdepth 1 -type d -mtime +7"
- stdin, stdout, stderr = ssh_client.exec_command(check_archive_cmd)
- old_archive_dirs = stdout.read().decode('utf-8').splitlines()
-
- for old_dir in old_archive_dirs:
- delete_cmd = f"rm -rf {old_dir}"
- _, stderr, _ = ssh_client.exec_command(delete_cmd)
- error = stderr.read().decode('utf-8')
- if error:
- self.error_logger.error(f"xx.xx.xx.xx 删除旧归档日志目录失败: {error} - {inspect.currentframe().f_code.co_name}")
- else:
- self.info_logger.info("xx.xx.xx.xx 没有7天前旧归档日志目录")
- # 使用AuditLogSync类来运行操作,程序执行入口
- if __name__ == '__main__':
- auditLogSync = AuditLogSync("/export/AuditLogSync/ip_addresses.txt","/var/log/audit",'root','Dcn763#+',822)
- auditLogSync.run_operations()
- ssh_client = auditLogSync.connect_to_server("xx.xx.xx.xx")
- if ssh_client is not None:
- auditLogSync.info_logger.info(f"成功连接服务器 xx.xx.xx.xx")
- auditLogSync.delete_old_archive_logs(ssh_client)
- ssh_client.close()
复制代码 6、服务器未安装杀毒
- 整改建议:
- 建议服务器安装杀毒程序,并提供最新病毒库版本
-
- 整改方法:
- 找服务器厂商协助安装杀毒软件(商业版),一般是深信服EDR防护
复制代码 二、MySql数据库等保加固
此处mysql版本是5.7.32,其余版本请DBA判断是否能用以下设置;并且设置后不要立即重启数据库,发起跟项目侧和客户约定业务低峰期进行重启操作,肯定要得到客户侧的同意再执行重启操作
1、采用用户名+口令进行身份鉴别,未启用口令复杂度策略,未定期更换口令
- 整改建议:
- 建议配置数据库口令复杂度策略,如口令长度至少8位以上且包含大写字母、小写字母、数字三种字符类型中至少两种组成
-
- 整改方法:
- 1、检查mysql是否已安装validate_password插件
- 登录mysql,执行以下命令:
- mysql> show plugins;
- 2、如果未安装该插件,执行以下命令进行安装:
- mysql>INSTALL PLUGIN validate_password SONAME 'validate_password.so';
- 3、my.cnf添加以下配置
- plugin-load-add=validate_password.so
- validate_password_check_user_name = ON
- validate_password_length = 8
- validate_password_mixed_case_count = 1
- validate_password_number_count = 1
- validate_password_policy = medium
- validate_password_special_char_count = 1
复制代码 2、未启用登录失败处置惩罚功能,未有登录毗连超时退出策略
- 整改建议:
- 建议配置登录失败处理及登录连接超时退出策略;(如登录失败5次锁定账户20分钟,登录连接超时30分钟自动退出)
-
- 整改方法:
- my.cnf添加以下配置
- #登录失败次数限制
- max_connect_errors = 5
- #登录连接超时退出策略
- interactive_timeout = 1800 # 将交互式客户端的超时时间设置为 1800 秒(30 分钟)
- wait_timeout = 1800 # 将非交互式客户端的超时时间设置为 1800 秒(30 分钟)
复制代码 3、采用用户名+口令验证码进行身份鉴别,未实现使用两种或两种以上组合鉴别技能进行身份鉴别,未实现双因子登录;未对接入方式或网络地址范围进行限定且网络不可控
- 整改建议:
- 服务器只采用密码技术对用户的身份进行鉴别,未采用双因子认证。
- 因为维护的项目都是通过vpn(短信验证)-->堡垒机(短信验证)-->登录服务器,最后沟通这项可以按如下修复。即服务器配置ssh白名单,只允许堡垒机登录
-
- 整改方法:
- vim /etc/hosts.deny #添加以下配置
- sshd:all:deny
- vim /etc/hosts.allow #添加以下配置
- sshd:堡垒机IP:allow
复制代码 4、未实现管理用户的最小权限分离
- 整改建议:
- 建议创建系统管理员、审计管理员、安全管理员并划分各管理员所需管理的最小权限,实现管理用户的三权分离
-
- 整改方法:
- 创建系统管理员(root) 审计管理员(audit) 安全管理员(secure)并分配对应权限
复制代码 5、未有加密技能保证数据在传输过程中的完备性;
- 整改建议:
- 建议采用加密技术或密码技术保证重要数据在传输过程中的完整性
-
- 整改方法:
- my.cnf添加以下配置
- require_secure_transport=ON
复制代码 6、未定期进行数据备份规复测试功能
- 整改建议:
- 建议重要数据进行本地数据备份与恢复功能
-
- 整改方法:
- 添加mysql_backup_3306.py全量备份脚本,定时备份,并进行恢复测试
- crontab -e
- * */23 * * * /usr/bin/python /path/mysql_backup_3306.py IP PORT
复制代码 三、中间件版本过低产生的各种漏洞
此处就不挨个展示中间件相干的漏洞了,就拿nginx的漏洞作为示例,其余中间件的修复方法都与此处同等
1、nginx漏洞示例及修复
- 漏洞示例:
- nginx 安全漏洞(CVE-2021-23017)
- nginx 缓冲区错误漏洞(CVE-2022-41741)
- nginx 越界写入漏洞(CVE-2022-41742)
- Nginx 信任管理问题漏洞(CVE-2021-3618)
- NGINX 环境问题漏洞(CVE-2019-20372)
-
- 漏洞修复方法:
- 采用iptables规则或firewalld规则进行修复。我比较熟练iptables规则,因此采用iptables
-
- 只允许指定的源IP地址、源网段地址、127.0.0.1访问nginx暴露出来的端口,拒绝其余网段/ip地址的访问
- iptables -A INPUT -s 10.x.xx.0/24 -p tcp -m multiport --dports 80,8999 -j ACCEPT
- iptables -A INPUT -s 172.xx.xx.0/24 -p tcp -m multiport --dports 80,8999 -j ACCEPT
- iptables -A INPUT -s 127.0.0.1 -p tcp -m multiport --dports 80,8999 -j ACCEPT
- iptables -A INPUT -p tcp -m multiport --dports 80,8999 -j DROP
-
- 注意事项:
- 1、为什么中间件漏洞通过IPtables规则进行修复?
- 因为随着项目再交付期的稳定运行,客户侧已开始学习使用系统,如果升级中间件版本,后端微服务代码可能也涉及到需要更改,更改后也并不一定能保证系统平稳运行,耗时巨大,成功率不敢保证100%。一般情况下客户侧也是不同意升级版本的。如果客户侧强烈要求升级版本,那只能自求多福写升级方案并演练,演练通过后再上生产。
- 2、其余中间件的修复方法亦是如此,只需要确定好哪些IP地址方法该中间件端口,然后添加规则就行。
复制代码 四、Harbor 访问控制错误漏洞
- 整改建议:
- 1、升级harbor版本(此方法已验证不适用,经过查询才知道这个是harbor的一个特性,每一个版本都会存在。因为最好的解决方法是方法2)
- 2、将harbor中公开的仓库全部设置为私有仓库,给pod的yaml文件中配置镜像拉取策略即可 #推荐方法2
复制代码
五、Swagger API 未授权访问漏洞
- 整改建议:
- 结合SpringSecurity/shiro进行认证授权,将Swagger-UI的URLs加入到各自的认证和授权过滤链中,当用户访问Swagger对应的资源时,只有通过认证授权的用户才能进行访问
-
- 整改方法:
- 拉通研发,进行处理即可
复制代码 六、服务器常见安全加固脚本分享
一个简单的shell脚本,包含了服务器暗码、毗连超时、文件权限、服务器汗青下令等方面的加固
总结
以上就是关于常见的等保测评项及加固方法,后期碰到新的测评项及加固方法会随时更新,盼望能对大家起到帮助作用,也盼望大家能给文章点点赞!!!
最后
从时代发展的角度看,网络安全的知识是学不完的,而且以后要学的会更多,同学们要摆正心态,既然选择入门网络安全,就不能仅仅只是入门水平而已,能力越强时机才越多。
因为入门学习阶段知识点比较杂,以是我讲得比较笼统,大家假如有不懂的地方可以找我咨询,我保证知无不言言无不尽,需要相干资料也可以找我要,我的网盘里一大堆资料都在吃灰呢。
干货主要有:
①1000+CTF历届题库(主流和经典的应该都有了)
②CTF技能文档(最全中文版)
③项目源码(四五十个有趣且经典的练手项目及源码)
④ CTF大赛、web安全、渗透测试方面的视频(适合小白学习)
⑤ 网络安全学习路线图(告别不入流的学习)
⑥ CTF/渗透测试工具镜像文件大全
⑦ 2023暗码学/隐身术/PWN技能手册大全
假如你对网络安全入门感兴趣,那么你需要的话可以点击这里 |