博主将收集整理的一些安全资料分享给大家,共同推进安全建设工作
安全建设:通用安全加固手册
作者:KEYONE
时间:2021/01
版本:1.0
系统加固
SSH安全配置
仅使用SSHv2 协议
SSHv1是已知的对于SSH协议的不安全实现,为了确保系统的完整性,应当将SSH服务配置为仅接受SSHv2连接。
- 修改/etc/ssh/sshd_config文件
vi /etc/ssh/sshd_config
- 修改以下内容:
Protocol 2
说明:RedHat和CentOS在7.4版本之后使用SSHv2作为默认配置,但仍可将该行写入配置文件
- 重启SSH服务
systemctl restart sshd.service
限制身份验证最大尝试次数
限制用户失败认证的最大次数可以缓解账户被暴力破解攻击。将MaxAuthTries
设置为比较小的数字(x),将会在用户x次失败尝试后强制断开会话。
- 修改/etc/ssh/sshd_config文件
vi /etc/ssh/sshd_config
- 修改以下内容:
MaxAuthTries 3
- 重启SSH服务
systemctl restart sshd.service
限制账户登录
只允许指定用户进行登录(黑、白名单):
- 修改/etc/ssh/sshd_config文件
vi /etc/ssh/sshd_config
- 修改内容如下:
AllowUsers aliyun test@192.168.1.1
# 允许 aliyun 和从 192.168.1.1 登录的 test 帐户通过 SSH 登录系统
DenyUsers zhangsan aliyun
# 拒绝 zhangsan、aliyun 帐户通过 SSH 登录系统
- 重启SSH服务
systemctl restart sshd.service
启用密钥登录
- 制作密钥对
ssh-keygen
- 复制公钥至服务器
cat id_rsa.pub >> authorized_keys
chmod 600 authorized_keys # 设置文件权限
chmod 700 ~/.ssh
- 修改/etc/ssh/sshd_config文件
vi /etc/ssh/sshd_config
- 修改内容如下:
RSAAuthentication yes # 启用 RSA 认证
PubkeyAuthentication yes # 启用公钥认证
PermitRootLogin yes #确定 root 用户能否通过 SSH 登录
PasswordAuthentication no #禁止使用密码登录
- 重启SSH服务
systemctl restart sshd.service
检查特殊账号
检查是否存在空口令和root权限的账号。
- 查看空口令和root权限账号,确认是否存在异常账号:
- 使用命令
awk -F: '($2=="")' /etc/shadow
查看空口令账号。 - 使用命令
awk -F: '($3==0)' /etc/passwd
查看UID为零的账号。
- 使用命令
- 加固空口令账号:
- 使用命令
passwd <用户名>
为空口令账号设定密码。 - 确认UID为零的账号只有root账号。
- 使用命令
限制用户su
限制能su到root的用户。
使用命令 vi /etc/pam.d/su
修改配置文件,在配置文件中添加行。
例如,只允许test组用户su到root,则添加 auth required pam_wheel.so group=test
。
添加口令策略
加强口令的复杂度等,降低被猜解的可能性。
-
使用命令
vi /etc/login.defs
修改配置文件。
PASS_MAX_DAYS 90 #新建用户的密码最长使用天数
PASS_MIN_DAYS 0 #新建用户的密码最短使用天数
PASS_WARN_AGE 7 #新建用户的密码到期提前提醒天数
-
使用chage命令修改用户设置。
例如,chage -m 0 -M 60 -E 2020-10-01 -W 7 <用户名>
表示将此用户的密码最长使用天数设为60,最短使用天数设为0,密码2020年10月1日过期,过期前七天警告用户。 -
设置连续输错三次密码,账号锁定五分钟。
使用命令
vi /etc/pam.d/common-auth
修改配置文件,在配置文件中添加auth required pam_tally.so onerr=fail deny=3 unlock_time=300
。
设置umask值
设置默认的umask值,增强安全性。
使用命令 vi /etc/profile
修改配置文件,添加行 umask 027
, 即新创建的文件属主拥有读写执行权限,同组用户拥有读写权限,其他用户无权限。
或者 umask 022
, 即新创建的文件属主拥有读写执行权限,同组用户拥有读写权限,其他用户拥有读写权限。
Web服务加固
Nginx安全配置
部署运行要求
非特权用户运行
在nginx主配置文件nginx.conf使用命令user来指定nginx执行用户。
user nginx;
隐藏或伪装版本信息
在nginx新版本发布后,公布旧版本的漏洞,攻击者极容易获得这些信息,并针对更新不及时或者补丁未打的nginx进行攻击。
通过修改配置文件nginx.conf,提供nginx安全。
打开nginx.conf,在http服务器中配置指令server_tokens为off。如下所示:
http {
…
server_tokens off;
…
}
基础安全加固
禁用不必要的http方法
nginx的反向代理功能,有一部分请求转发到后端服务器上,并从后端服务器上读取响应,发回客户端。后端可能有Tomcat或者Apache服务器,默认http方法包括GET、HEAD、POST、PUT、DELETE、OPTIONS等方法。在这些方法中,虽然PUT、DELETE方法很少被使用到,但可能被利用来进行攻击。对于web服务来讲标准的请求只使用GET,POST和HEAD,其它方法不使用的需要禁止掉。例外:如果确实是业务需要使用,则不强制要求。
方法一:在nginx.conf配置所允许的http。
语法:
limit_except method
... {...}
配置块:location
例如:
http {
…
Server {
…
location / {
#http请求方法在全目录“/”下,除了GET POST HEAD,均禁止
limit_except GET POST HEAD
{
deny all;
}
}
}
}
方法二:在nginx.conf针对某一个http方法禁止,根据业务需求。
if ($request_method = PUT ) {
return 403;
}
if ($request_method = DELETE ) {
return 403;
}
定制nginx出错信息
nginx发生服务器端出错时(例如:nginx在找不到网页时,会报404错误),错误页面上经常会附带当前服务器版本号,还可能泄露其他服务器端信息。黑客可以通过版本号,查询当前nginx服务器的默认配置信息,以及该版本的安全漏洞。如果出错页面带有版本号等敏感信息,则必须对出错信息进行定制。
在配置文件nginx.conf配置出错信息,配置模块主在server,如下所示:
对5xx和4xx的错误统一配置。
server {
…
error_page 500 501 /50x.html;
location = /50x.html {
#html是nginx自创建的目录,50x.html是自配置的出错提示信息
root html
}
#关于4xx类型的错误,同上
error_page 400 401 402 403 404 405 406 407 413 414 /4xx.html;
location = /4xx.html{
root html;
}
}
说明:出错提示信息的网页大小必须大于512个字节,否则IE会自动调用自己的友好提示界面。特别提醒,禁止给响应码302配置错误页面,否则所有重定向都将指向该错误页面。的配置值是自定义错误页面相对于当前Web应用的根目录的路径,需要根据自定义错误页面的实际路径配置。
禁用目录列表功能
如果访问nginx下的一个web应用,如果输入是一个目录名,而且该目录下没有一个默认访问文件,那么nginx会将该目录下的所有文件列出来,这种敏感信息泄露是严格禁止的。nginx默认的是关闭目录列表,但是为了程序调试方便,部分程序员也有可能开启这一功能。因此,要确认该项配置是否正确。
在配置文件nginx.conf中,修改autoindex参数的值为off。或者该参数没有出现(默认情况下是关闭目录列表功能):
在location server段或者http段,
http {
...
autoindex off;
...
}
禁止nginx重定向至监听端口
可以从nginx的核心模块中得知,如果请求发生重定向,nginx默认的情况下,是会在重定向的URL后自动添加nginx当前站点监听的端口。这样明显会对服务器造成很大的威胁,后端的端口暴露出来,就可能会被人直接对这个端口进行诸如CC类攻击。
在配置文件nginx.conf中的http段、或server段或location段增加禁止指令,建议在http段添加,如下所示:
http {
...
#nginx will not add the port in the url when the request is redirected
port_in_redirect off;
...
Server {
...
}
...
}
绑定特定IP地址
nginx安装好后需要绑定在主机特定的接口IP地址上,以限制外部的访问通道,禁止绑定在0.0.0.0。需要按照下面方法进行配置,不配置或默认的配置都是绑定到0.0.0.0。
操作如下所示:
server{
listen 10.248.216.102:30443;
....
}
说明:上述命令中的IP地址及端口为示例,请根据实际nginx服务器IP地址和端口修改。
限制允许访问的IP
nginx允许限制某些IP地址的客户端访问,例如限制Nginx服务器仅允许负载均衡、CDN访问等等,可以避免直接遭受DDOS攻击。
具体配置以用户实际需求为准,举例如下所示:
location/ {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
说明:规则按照顺序依次检测,直到匹配到第一条规则。在这个例子里,IPv4的网络中只有10.1.1.0/16和192.168.1.0/24允许访问,但192.168.1.1除外,对于IPv6的网络,只有2001:0db8::/32允许访问。
限制http请求的消息主体和消息头的大小
此指令给了服务器管理员更大的可控性,以控制客户端不正常的请求行为,自定义缓存以限制缓冲区溢出攻击。
在配置文件nginx.conf调整请求头和请求体的缓冲区大小:
http{
... ...
server{
... ...
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
client_body_buffer_size 16k;
client_max_body_size 50g;
... ...
}
}
说明:以上所定义的缓冲区大小是建议值。在报文请求过程中,报“Request URL too large”(414)或者“Bad-request”(400)错误,则须增加缓冲区大小。产品如果有特殊需要可以根据自身的需求,进行相应调整。
配置网络超时时间
配置nginx的超时时间,提高服务器的性能,降低客户端的等待时间。同时,在受到DOS攻击时,可以起到缓解作用。特殊情况下,请根据具体性能需求进行调优。
在配置文件nginx.conf中的http段配置超时,单位秒(s):
http {
... ...
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 5 30;
send_timeout 1000;
... ...
}
隐藏X-Powered-By HTTP头
X-Powered-By表示网站是用什么技术开发的,它会泄漏开发语言、版本号和框架等信息,有安全隐患,需要隐藏掉。可采用以下措施:
在nginx.conf使用指令proxy_hide_header指令隐藏它
http {
... ...
proxy_hide_header X-Powered-By;
... ...
}
HTTP响应头加固
启用XSS保护
X-XSS-Protection这个响应头是用来防范XSS的。现在主流浏览器都支持,并且默认都开启了XSS保护,用这个header可以关闭它。它有几种配置:
0:禁用XSS保护;
1:启用XSS保护;
1; mode=block:启用XSS保护,并在检查到XSS攻击时,停止渲染页面(例如IE8中,检查到攻击时,整个页面会被一个#替换);
浏览器提供的XSS保护机制并不完美,但是开启后仍然可以提升攻击难度,总之没有特别的理由,不要关闭它。
推荐配置:
add_header X-XSS-Protection "1; mode=block";
减少点击劫持
X-Frame-Options这个功能主要为了减少了点击劫持(Clickjacking)的发生。X-Frame-Options,已经转正为Frame-Options,但现阶段使用最好还是带上X-。
这个响应头支持三种配置:
DENY:不允许被任何页面嵌入;
SAMEORIGIN:不允许被本域以外的页面嵌入;
ALLOW-FROM uri:不允许被指定的域名以外的页面嵌入(Chrome现阶段不支持);
如果某页面被不被允许的页面以或的形式嵌入,IE会显示类似于“此内容无法在框架中显示”的提示信息,Chrome和Firefox都会在控制台打印信息。由于嵌入的页面不会加载,这就减少了点击劫持(Clickjacking)的发生。
推荐配置:
add_header X-frame-options SAMEORIGIN;
禁用浏览器的类型猜测
互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:"text/html"代表html文档,"image/png"是PNG图片,"text/css"是CSS样式文档。然而,有些资源的Content-Type是错的或者未定义。这时,某些浏览器会启用MIME-sniffing来猜测该资源的类型,解析内容并执行。
例如,即使给一个html文档指定Content-Type为"text/plain",在IE8-中这个文档依然会被当做html来解析。利用浏览器的这个特性,攻击者甚至可以让应该解析为图片的请求被解析为JavaScript。通过X-Content-Type-Options这个响应头可以禁用浏览器的类型猜测行为:
这个响应头的值只能是nosniff,可用于IE8+和Chrome。另外,它还被Chrome用于扩展下载。
推荐配置:
add_header X-Content-Type-Options nosniff;
目录权限控制
nginx根目录只能由nginx运行用户修改,nginx根目录的所有父级目录的修改权限不能赋予除nginx运行用户的其他普通用户
不仅文件本身,nginx根目录必须只能由属主来改写,nginx根目录的所有父级目录的修改权限不能赋予除nginx运行用户的其他普通用户。如果nginx根目录的某一父级目录的修改权限可以被其它普通用户拥有,那这个用户就可以删除这个父级目录下面原来的目录或文件然后新建同名的目录或文件,达到对目录下所有文件进行篡改控制的目的。
如果要配置nginx根目录为/opt/nginx,首先要确认/opt/nginx目录只能由nginx运行用户修改,其他用户不能具备这些目录的修改权限。
nginx配置文件属主必须是nginx启动用户,且只能允许nginx启动用户修改
其它用户有可能会覆盖配置文件,从而获取更高的权限或者更多的信息。
执行如下命令配置:
chown -R nginx:nginx /opt/nginx
chmod -R 600 /opt/nginx/conf/*
日志文件属主只能是nginx运行用户,且只允许属主可读写
nginx日志文件包括错误日志和访问日志。两类日志必须都只允许其属主(nginx运行用户)可读写,如果日志文件本身对非属主用户是可写的,别人就可能伪造日志。
如果nginx运行用户为nginx,执行下列命令:
chown nginx:nginx /var/log/nginx/error.log
chmod 640 /var/log/nginx/error.log
chown nginx:nginx /var/log/nginx/access.log
chmod 640 /var/log/nginx/access.log
说明:日志文件的上级目录也只能允许nginx运行用户可写。
日志审计策略
开启nginx日志功能
正常的访问日志和错误请求日志这些日志可以提供异常访问的线索。nginx可以记录所有的访问请求,同样,异常的请求也会记录。日志文件可以记录系统发生的重要事件,可以帮助找到安全事件的原因,因此,日志文件要尽可能的包含访问的关键信息,例如访问时间、内容、结果、请求用户的ip、访问的网址等。
在配置文件nginx.conf中,在的标签里添加如下内容,在http段声明日志文件:
http {
…
#在目录/opt/nginx/logs/下配置一个访问日志文件,日志格式按照main来打印,压缩后写入。
access.log /var/log/nginx/access.log main gzip;
…
}
在上文配置信息中的main格式名,是用来配置日志基本格式的。
一般情况下,定义日志格式:
http {
…
#main是格式名,日志打印格式可按照此定义,具体可根据实际情况确定。
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer" '
' "$http_user_agent" "$http_x_forwarded_for" ';
…
}
参数值的具体含义如下:
$remote_addr | 客户端的IP地址(如果中间有代理服务器那么这里显示的ip就为代理服务器的ip地址) |
---|---|
$remote_user | 用于记录远程客户端的用户名称(一般为“-”) |
$request | 用于记录请求的url以及请求方法,这里注意需要进行检查,如果URL中可能包含敏感信息,就不要将其记录到日志里 |
$status | 响应状态码 |
$body_bytes_sent | 给客户端发送的文件主体内容大小 |
$http_referer | 可以记录用户是从哪个链接访问过来的 |
$http_user_agent | 用户所使用的代理(一般为浏览器) |
$http_x_forwarded_for | 可以记录客户端IP地址,通过代理服务器来记录客户端的ip地址 |
SSL安全策略
启用SSL功能
启用SSL功能操作如下:
server {
…
ssl on;
ssl_certificate /opt/nginx/security/nginx_cert/server.pem;
ssl_certificate_key /opt/nginx/security/nginx_cert/server.key;
…
}
启用SSL功能后需要配置证书和私钥,私钥强制要求设置密码保护,且对私钥文件进行严格的访问控制。必须做到以下两点:
- 私钥设置严格的访问权限,只允许进程运行用户可以读;
- 如果要对私钥进行备份或转移,必须设置密码保护。
设置合适的超时时间
设置ssl timeout的原因是避免攻击者建立大量无效链接,或者慢速攻击。
推荐配置如下:
server {
…
ssl_session_timeout 5m;#超时时间5分钟
…
}
使用安全的TLS协议
如果不配置ssl_protocols,nginx默认使用SSLv3 TLSv1 TLSv1.1 TLSv1.2。根据密码算法应用规范的要求,应该使用更安全的TLS协议。nginx需要openssl版本>=1.0.1来支持TLSv1.2协议。
server {
…
ssl_protocols TLSv1.1 TLSv1.2;
…
}
使用安全的加密套件
ssl_ciphers定义了网站使用那些加密套件,nginx的默认设置是HIGH:!aNULL:!MD5;这个值已经是比较安全的。最主要的是ssl_prefer_server_ciphers的设置,开启这个设置可以优先使用服务器定义的加密算法以防止Beast Attacks。
server {
…
ssl_ciphers
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES256-SHA:HIGH:!MEDIUM:!LOW:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:@STRENGTH";
ssl_prefer_server_ciphers on;
…
}
Tomcat安全配置
部署运行要求
非特权用户运行
缺省情况下,Java运行时根据运行它的用户授予安全权限。当Tomcat以系统管理员身份或作为系统服务运行时取得了系统用户或系统管理员所具有的全部权限。这样一来,Java运行时就取得了所有文件夹中所有文件的全部权限。并且Servlets(JSP在运行过程中要转换成Servlets)取得了同样的权限。所以Java代码可以调用Java SDK中的文件API列出文件夹中的全部文件,删除任何文件,最大的危险在于以系统权限运行一个程序。
-
专门为Tomcat建立一个单独的用户和用户组。
groupadd tomcat useradd -g tomcat -d /home/tomcat -m tomcat
tomcat组名和用户名,用户可根据需要自行修改。/home/tomcat为用户登录时默认路径(家目录),可根据需要自行修改。
-
设置权限:
更改Tomcat安装目录属主为tomcat用户; 为tomcat用户添加应用程序(例如webapps,或者被单独放置在tomcat安装目录之外的应用目录)目录的只读权限; 如果某些应用程序需要写权限,请单独为其配置tomcat的写权限。
删除Tomcat默认管理控制台或管理员帐户
默认情况下,Tomcat存在管理控制台,其地址一般为http://[IP]:[Port]/admin。管理台的应用文件,在 t o m c a t / w e b a p p s 下 , 有 h o s t − m a n a g e r 和 m a n a g e r 两 个 应 用 。 其 用 户 密 码 , 在 tomcat/webapps下,有host-manager和manager两个应用。其用户密码,在 tomcat/webapps下,有host−manager和manager两个应用。其用户密码,在tomcat/conf/tomcat-users.xml中定义。默认情况下,tomcat管理台启用,易造成严重安全问题。
删除$tomcat/webapps下host-manager和manager两个应用。
删除$tomcat/conf/tomcat-users.xml中的用户和密码。
禁用自动部署功能
默认情况下,tomcat启动时,会自动部署 a p p B a s e 下 面 的 所 有 应 用 。 例 如 , 当 appBase下面的所有应用。例如,当 appBase下面的所有应用。例如,当appBase的值为webapps时,那么任意一个应用,只要被放进webapps目录下,在tomcat启动时,都会被发布。这有可能导致恶意或者未经测试的应用程序被自动部署在服务器上。因此,这里必须禁用掉Tomcat的自动部署功能。
修改配置文件$tomcat/conf/server.xml如下:
autoDeploy="false" //自动部署 deployOnStartup="false"
说明:
- 如果server.xml文件中不存在deployOnStartup参数,则必须手工添加,因为该参数的默认值是true。格式位置如下:
<Host …. deployOnStartup="false"/>
- 关闭自动部署功能后,Tomcat不会自动发布$appBase目录下的web应用。对需要发布的Web应用,需要手工部署。手工部署的推荐方法,是在server.xml文件的Host标签内新建一个context,格式如下:
<Context path="/myapp" reloadable="false" docBase="myapp" workDir="webapps/myapp/WEB-INF/work"/>
其中:
path:指定访问该Web应用的URL入口。
docBase:指定Web应用的文件路径,可以给定绝对路径,也可以给定相对于的appBase属性的相对路径。
workDir:是指Tomcat解析Jsp转换为Java文件,并编译为class存放的文件夹,设置在项目文件夹里面,可以避免移植到其他地方首次读取jsp文件需要重新解析。可以给定绝对路径,也可以给定相对于tomcat根目录的相对路径。禁止将workDir设置为Web内容目录(通过Web可以直接浏览、访问的目录),否则容易被攻击者直接下载获取。也可以不配置workDir属性,使用默认配置。
reloadable:设置为false,只在启动时加载该Web应用WEB-INF的lib和classes。
以安全管理模式运行Tomcat
通过使用安全管理器运行Tomcat,应用程序将在沙箱中运行,可以防止不受信任的代码访问文件系统上的文件或者执行敏感的操作。
Tomcat以安全管理模式运行时,安全管理器自动加载默认的安全策略文件$CATALINA_HOME /conf/catalina.policy。
默认的安全配置catalina.policy文件包含了一组默认的安全策略,对Tomcat中的web应用程序对系统环境变量读取和敏感操作等进行授权。产品可以根据代码需要增加授权(可以使用JDK的policytool工具进行策略编辑,添加自己的策略授权)。
在安全管理模式下,应用程序中代码若进行了非授权的操作,程序则会抛出异常。产品可以根据这些异常信息,对安全策略进行补充。
安全策略文件可以定制如下的权限管理(概要):
java.security.AllPermission 所有权限的集合
java.util.PropertyPermission 系统/环境属性权限
java.lang.RuntimePermission 运行时权限
java.net.SocketPermission Socket权限
java.io.FilePermission 文件权限,包括读写,删除,执行
java.lang.reflect.ReflectPermission 反射权限
java.net.NetPermission 网络权限
java.security.SecurityPermission 安全控制方面的权限
启动Tomcat时,使用-security
参数:
$CATALINA_HOME/bin/catalina.sh start -security
基础安全加固
禁用不必要的http方法
Tomcat服务器提供默认http方法包括GET、HEAD、POST、PUT、DELETE、OPTIONS。在这些方法中,PUT、DELETE方法很少被使用到,并且极易被利用来进行攻击。
-
禁用DELETE的方法:
在$tomcat/conf/web.xml检查readonly参数的值是否为true:
<init-param> <param-name>readonly</param-name> <param-value>true</param-value> </init-param>
说明: 如果不存在readonly参数,则不用配置,因为该参数的默认值为true。
-
禁用Trace的方法:
在$tomcat/conf/server.xml禁用trace方法,即配置allowTrace为false:
<Connector port="80" maxThreads="150" connectionTimeout="20000" redirectPort="8443" allowTrace="false"/>
说明: 如果不存在allowTrace参数,则不用配置,因为该参数的默认值为false;如果配置了该参数,需要确保参数值为false。
-
在$tomcat/conf/web.xml文件的节中增加以下内容:
<security-constraint> <web-resource-collection> <url-pattern>/*</url-pattern> <http-method>OPTIONS</http-method> <http-method>HEAD</http-method> <http-method>DELETE</http-method> <http-method>TRACE</http-method> </web-resource-collection> <auth-constraint> </auth-constraint> </security-constraint>
说明:
- 这里的/*和策略可以根据实际业务来进行配置。
- 这里的配置不会影响到RESTFUL中PUT、DELETE方法的使用,因为RESTFUL的PUT、DELETE方法只是构造请求,并不会实际在服务器上创建或删除文件。如果产品由于使用RESTFUL接口需要PUT、DELETE方法,应该把PUT和DELETE方法从上面配置的黑名单中删除。
定制Tomcat出错信息
Tomcat发生服务器端出错时(例如:Tomcat在找不到网页时,会报404错误),错误页面上会附带当前服务器版本号,还可能泄露其他服务器端信息。黑客可以通过版本号,查询当前Tomcat服务器的默认配置信息,以及该版本的安全漏洞。
在配置文件$tomcat/conf/web.xml的倒数第二行(即之前的那一行)添加如下内容:
<error-page>
<error-code>400</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>401</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>402</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>405</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>406</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>407</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>413</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>414</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<error-code>501</error-code>
<location>/error.htm</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.htm</location>
</error-page>
关闭目录列表功能
缺省情况下,访问tomcat下的一个web应用,如果输入是一个目录名,而且该目录下没有一个可用的welcome文件,那么tomcat会将该目录下的所有文件列出来,这种敏感信息泄露是严格禁止的。Tomcat5.0以后的版本出于安全考虑,默认的是关闭目录列表,但是为了程序调试方便,部分程序员也有可能开启这一功能。因此,要确认该项配置是否正确。
在配置文件$tomcat/conf/web.xml中修改listings参数的值为false:
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
更改Tomcat服务器默认shutdown端口号和命令
Tomcat服务器提供默认shutdown端口(8005)和命令(shutdown),很容易被黑客捕获利用关闭服务器,进而威胁到服务器和应用等。
-
使用shutdown.sh关闭tomcat。
-
修改$home/conf/server.xml文件,更改默认端口和shutdown命令为其他大于8位的任意字符串,例如:
<Server port="2324" shutdown="Rea!!yC0mplexW0rd">
这里shutdown命令建议12个字符,包含大小写字母、数字和特殊字符
-
使用startup.sh启动tomcat。
说明: 默认的8005端口为Tomcat的shutdown端口,在linux下如果删掉或者改成-1(表示不使用shutdown端口),会导致Tomcat无法shutdown,故不建议禁用shutdown端口。必须在关闭tomcat的情况下修改该参数,否则会导致tomcat无法正常关闭。
限制http请求的消息主体和消息头的大小
此指令给了服务器管理员更大的可控性,以控制客户端不正常的请求行为。
在配置文件$tomcat/conf/server.xml中的每个***Connector***的“maxPostSize”属性为10240,“maxHttpHeaderSize”属性为8192:
<Connector port="18081" protocol="HTTP/1.1"
connectionTimeout="20000" maxPostSize="53687091200" maxHttpHeaderSize="8192"
redirectPort="18443" />
禁止配置Tomcat的网络连接超时时间为0或-1
connectionTimeout为网络连接超时时间毫秒数,当配置为0或-1时,表示永不超时,在受到DOS攻击时,很快就会导致最大连接数被完全占用,进而导致Tomcat服务器无法访问。因此这里禁止配置connectionTimeout为0和-1,通常推荐的超时时间为20s和30s。
在配置文件$tomcat/conf/server.xml中的每个***Connector***的“connectionTimeout”属性为20000:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000" maxPostSize="10240"
redirectPort="8443"/>
关闭会话facade回收重利用功能
RECYCLE_FACADES(会话facade回收重利用)指定是否为每个请求都建立一个新的facade,如果设置为false,则新请求可能不会创建新的facade而是使用旧的facade,该功能有可能导致请求信息泄露。
在启动脚本tomcat/bin/setenv.sh中添加如下命令:
-Dorg.apache.catalina.connector.RECYCLE_FACADES=true
启用context.xml文件的useHttpOnly参数,防止会话cookie被客户端脚本访问
设置cookie为HttpOnly,可以阻止客户端脚本访问(包括读取和修改)cookie,当支持HttpOnly的客户端浏览器(当前主流的浏览器都支持)检测到Cookie包括了HttpOnly标志时,浏览器返回空字符串给企图读取该cookie的脚本,这样cookie中的任何信息暴露给黑客或者恶意网站的几率将会大大降低。
在$tomcat/conf/context.xml中设置context的参数useHttpOnly的值为true,例如
<Context useHttpOnly="true">
不使用的Connector(Protocol)必须删除
对于不使用的Connector应该删除,否则会带来安全隐患。Tomcat默认情况下提供AJP 1.3 Connector,负责和其他的HTTP服务器建立连接(例如:Apache和Tomcat组合使用,客户请求通过Apache过滤转发到tomcat服务器,对于一些静态页面的请求,包括请求的Html文件,静态页面或者动态页面中的图片都直接由Apache处理,采用另外一种说法就是,对于用户发出的对动态页面的请求,如jsp、servlet,由Apache转发给Tomcat处理,可以有效提高服务器性能),如果确认不使用AJP 1.3 Connector,则必须删除。
-
删除**$tomcat/conf/server.xml**中不用的AJP 1.3 Connector:
-
注释或删除$tomcat/conf/server.xml文件中的如下内容:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
说明:
- 如果使用AJP Connector,应该修改默认的8009端口为其他端口,如3039。
- 其他不使用的Connector(Protocol)也需要删除。
禁用X-Powered-By HTTP头并重命名所有Connector的Server值
xpoweredBy设置决定了Tomcat是否在X-Powered-By HTTP Header中提供其版本等信息,设置为false可以使攻击者更难获知服务器的安全缺陷。
Tomcat默认配置中,Connector标签中无Server属性,在HTTP响应消息中,将默认携带服务器的实现及版本信息,如Server: Apache-Coyote/1.1,攻击者可以使用所公开的信息来获取所标识的版本的特定安全漏洞,对服务器做进一步的攻击。
-
在$tomcat/conf/server.xml文件中每一个Connector中加上xpoweredBy属性并设置为false,或者保证Connector中没有xpoweredBy:
<Connector ... xpoweredBy="false" />
-
在$tomcat/conf/server.xml文件中每一个HTTP Connector中加上server属性并设置为非空值(建议设置为模糊信息,可自行修改)。
用额外的路径分隔符
允许额外路径分隔符会导致黑客访问不可见的应用或区域。
在启动脚本$tomcat/bin/setenv.sh中添加如下命令:
-Dorg.apache.setenv.connector.CoyoteAdapter.ALLOW_BACKSLASH=false
-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=false
说明:
这两个参数默认值为false。如果在启动脚本中未发现这两个参数,则不用添加。
禁用自定义头状态信息
允许将用户提供的数据放入头中可能导致XSS攻击。
在启动脚本$tomcat/bin/catalina.sh中添加如下命令:
-Dorg.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER=false
说明: 该参数默认值为false。如果在启动脚本中未发现该参数,则不用添加。
禁止以特权方式运行应用
以特权方式运行应用会允许应用加载管理库。
在所有的context.xml中设置:
-<Context ... privileged= "false" />
说明: 该参数默认值为false,如果未发现该参数,则不用设置。
不解析日志阀上的主机
如果将日志阀里面的resolveHosts设置为true,那么在记录信息之前会先进行DNS查询,增加额外资源消耗。
在所有包含Valve节的context.xml和server.xml中设置:
<Valve ... resolveHosts= "false" />
说明: 该参数默认值为false,如果Valve节中未发现该参数,则不用设置。
Tomcat配置SSL时,需要使用安全的协议TLSV1.2、TLSV1.1
当Tomcat启用SSL时,需注意防范POODLE漏洞,在配置HTTPS connector时设置sslEnabledProtocols=“TLSv1.1,TLSv1.2”,请参考如下实施操作:
修改https参数:
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
sslEnabledProtocols="TLSv1.1,TLSv1.2"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA"
keystoreFile="/opt/security/server_cert/tomcat1/keystore.jks"
keystorePass="YPMlhVQGqO7ho3UbIwesyuzgcHEpvBhRk/Xayz36gL8="
为Tomcat配置JRE memory leak listener
Tomcat为JRE的一些已知的内存泄露问题提供了解决方案:使用JRE Memory Leak Prevention Listener可以预防此类问题。
检查$tomcat/conf/server.xml中是否存在JRE Memory Leak Prevention Listener配置,若未配置,请添加(或者解除注释):
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
为Tomcat配置Security Lifecycle Listener
当Tomcat启动时,Security Lifecycle Listener会执行一些安全检查,若检查失败,该Listener会阻止Tomcat启动。
Security Lifecycle Listener检查内容包含:
- 检查Tomcat启动时所使用的账号是否在指定的黑名单中(若未配置黑名单,黑名单中默认值为root)。
- 检查Tomcat启动时umask是否符合配置的最小限制(若未指定,则使用默认值0007)。
-
在$tomcat/conf/server.xml中增加(或者解除注释)Security Lifecycle Listener配置:
<Listener className="org.apache.catalina.security.SecurityListener" checkedOsUsers="root" minimumUmask="0007" />
-
在tomcat/bin/setenv.sh文件中,解除如下注释(该配置仅与umask检查相关):
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.security.SecurityListener.UMASK=`umask`"
目录权限控制
Tomcat根目录只能由Tomcat属主用户修改(755),Tomcat根目录的所有父级目录的修改权限不能赋予除超级管理员用户和Tomcat属主的其他普通用户
不仅文件本身,tomcat根目录( C A T A L I N A H O M E ) 必 须 只 能 由 属 主 来 改 写 , T o m c a t 根 目 录 的 所 有 父 级 目 录 的 修 改 权 限 不 能 赋 予 除 超 级 管 理 员 用 户 和 T o m c a t 属 主 的 其 他 普 通 用 户 。 采 用 多 实 例 运 行 的 T o m c a t , 也 要 对 CATALINA_HOME)必须只能由属主来改写,Tomcat根目录的所有父级目录的修改权限不能赋予除超级管理员用户和Tomcat属主的其他普通用户。采用多实例运行的Tomcat,也要对 CATALINAHOME)必须只能由属主来改写,Tomcat根目录的所有父级目录的修改权限不能赋予除超级管理员用户和Tomcat属主的其他普通用户。采用多实例运行的Tomcat,也要对CATALINA_BASE目录进行同样的权限限制。
如果要配置Tomcat根目录为/home/tomcat,首先要确认/、/home目录只能由root修改,/home/tomcat目录只有root和Tomcat属主用户才有修改权限,其他用户不能具备这些目录的修改权限,其次要使用Tomcat属主用户执行下列命令:
chmod -R 700 /opt/tomcat_${num}/
chmod 600 /opt/tomcat_${num}/bin/*
chmod 700 /opt/tomcat_${num}/bin/*.sh
chmod 600 /opt/tomcat_${num}/conf/*
说明:num表示当前VM安装的tomcat序号。若配置$CATALINA_BASE,该目录也需要进行同样的权限限制。
日志访问控制
开启Tomcat的日志功能:正常的访问日志和错误请求日志。日志文件的记录中包含访问时间、内容、结果及请求用户的ip等关键信息
这些日志可以提供异常访问的线索。Tomcat可以记录所有的访问请求,同样,异常的请求也会记录。日志文件可以记录系统发生的重要事件,可以帮助找到安全事件的原因,因此,日志文件必须包含访问的关键信息,例如请求用户的ip、访问的网址等。
在配置文件$tomcat/conf/server.xml中,在的标签里添加如下内容:
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="localhost_access_log." suffix=".log"
pattern="%h %l %u %t "%r" %s %b %{Referer}i %{User-Agent}i %D" resolveHosts="false"/>
在上文配置信息中的pattern参数,是用来配置日志基本格式的。
一般情况下,pattern可以直接设置成两种方式:common和combined,真实值如下:
common :%h %l %u %t %r %s %b
combined:%h %l %u %t %r %s %b %{Referer}i %{User-Agent}i
参数值的具体含义如下:
%a | 记录访问者的IP地址 |
---|---|
%A | 记录本地服务器的IP地址 |
%b | 发送信息的字节数,不包括http头,如果字节数为0的话,显示为“-” |
%B | 发送信息的字节数,不包括http头 |
%h | 设置resolveHosts为false时,这里就是IP地址,否则就是服务器名称 |
%H | 访问者使用的协议,例如HTTP/1.1 |
%l | 登录标识中的逻辑用户名,通常返回值为“-” |
%m | 请求的HTTP方法(GET,POST等) |
%p | 访问的端口 |
%q | 查询字符串(即请求中?后面的部分) |
%r | 请求头,即请求的第一行(例如POST/HTTP/1.1) |
%s | 响应请求的HTTP状态代码(例如200,404等) |
%S | 用户的会话ID |
%t | 日期和时间 |
%u | 得到了验证的访问者,否则就是"-" |
%U | 请求的URL地址 |
%v | 服务器名称 |
%D | 请求响应时间,单位是毫秒 |
%T | 请求响应时间,单位是秒 |
%I | 当前请求的线程名称(可以在后期用来堆栈比较) |
Tomcat日志路径要限制其访问权限,只能由Tomcat属主、属组用户访问
对Tomcat的日志存放目录进行权限限制,可以增强应用程序运行时完整性和机密性,减少信息泄露。日志存放目录只允许Tomcat属主和属组用户访问。
在配置文件(Server.xml或Context.xml)中检查配置中Valve组件的directory属性指向的目录:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="$CATALINA_HOME/logs/" prefix="access_log" fileDateFormat="yyyy-MM-dd.HH" suffix=".log" pattern="%t %H cookie:%{SESSIONID}c request:%{SESSIONID}r %m %U %s %q %r" />
设定该目录的owner为tomcat属主及属组,取消其他用户的权限:
chown -R tomcat:robogrp /opt/tomcat_${num}/
chmod 700 /opt/tomcat_${num}/logs
说明: num表示当前VM安装的tomcat序号。
数据库加固
MySQL安全配置
部署运行要求
非特权用户运行
数据库以专用的非操作系统超级用户启动,可以减少MySQL引入漏洞的影响,而且受限的账号不能访问与MySQL无关的资源。
-
执行如下命令检查是否以OS超级管理员用户身份启动和运行:
ps -C mysqld -o user
-
若结果为OS超级管理员用户身份启动和运行,则在/etc/my.cnf配置文件中(后续简称my.conf)修改[mysqld] user=,并执行如下命令启动MySQL:
systemctl start mysqld
基础安全加固
**监听地址不允许包含 ,0.0.0.0,::
-
执行如下SQL语句:
show variables like 'bind_address';
-
若返回值包含*,0.0.0.0,::等信息,则在/etc/my.cnf配置文件中修改[mysqld] bind-address=<‘ServerIP’>。
-
重启数据库。
用户主机名不使用通配符 %
通配符标识用户接受来自任何IP的连接,因此创建用户、复制用户时hostname不允许指定为%,执行如下SQL语句检查是否使用通配符%:
select user,host from mysql.user where host ='%';
SELECT user, host FROM mysql.user WHERE user='repl' AND host = '%';
上述语句中repl为举例用户名,请根据实际情况修改。
超级管理员只能本地登录
-
执行如下SQL语句:
select count(*) from mysql.user where Super_priv = 'Y' and host not in ('localhost','127.0.0.1','::1');
-
若返回值不为0,则执行如下语句:
Delete from mysql.user where Super_priv = 'Y' and host not in ('localhost','127.0.0.1','::1');
禁止重用数据库用户名
禁止重用数据库账户用户名,数据库账户用户名不能用于多个应用,或用于多个用户。在应用程序中使用单独的数据库帐户,当出现安全威胁时,将减少受损MySQL帐户的影响。
-
执行如下SQL语句检查是否存在数据库用户名重名(使用mysql库,后续无特殊声明均在此库):
use mysql select user,count(*) from user group by user having count(*) > 1;
-
若返回结果不为空,则删除重用数据库用户。
修改超级用户的密码
MySQL安装后默认有root超级帐户,要重置root用户密码。执行如下命令修改超级用户的密码:
set password for <user>@<hostname> = password('<yourpassword>');
新设置的密码必须满足配置密码复杂度中密码复杂度要求。
禁止数据库用户密码为空
-
执行如下执行SQL语句检查密码是否为空:
SELECT User,host FROM mysql.user WHERE LENGTH(authentication_string) = 0;
-
若返回结果不为空,则执行如下命令设置数据库用户密码,且密码必须满足配置密码复杂度中密码复杂度要求:
配置密码复杂度
数据库密码配置需要满足一定的复杂度,防止暴力破解,密码长度最小14位,至少一个数字,一个大写字符,一个小写字符,一个特殊字符,并且不能和用户名重复。
-
在/etc/my.cnf配置文件中添加如下配置:
[mysqld] validate-password=FORCE_PLUS_PERMANENT validate_password_length=14 或大于14 validate_password_policy= MEDIUM 或STRONG validate_password_mixed_case_count=1 或大于1 validate_password_number_count=1 或大于1 validate_password_special_char_count=1 或大于1
配置文件中还应包含:
plugin-load="validate_password.so" validate-password=FORCE_PLUS_PERMANENT
-
重启数据库。
禁止在/etc/my.cnf中配置密码
/etc/my.cnf配置文件中[client]块允许配置密码方便数据库连接,会导致任何OS登录人员都能够操作数据库,因此须禁止。
-
执行如下shell命令:
cat /etc/my.cnf 2>/dev/null | grep -i '^[^a-zA-Z0-9#]*password'
-
若返回结果不为空,则在/etc/my.cnf配置文件中清除[client]中的password信息。
-
重启数据库。
启用记录错误日志
错误日志记录功能需启用,确保系统能记录相应的攻击行为,且错误日志不要存放于系统分区。
-
执行SQL语句:
show variables like 'log_error';
-
执行命令:
df -h
-
若错误日志路径不是存放于系统分区内,则在/etc/my.cnf配置文件中添加配置[mysqld] log-error=<your_path>。
-
重启数据库。
用户权限控制
mysql.user表只有管理员用户才能操作
mysql.user表记录了MySQL数据库的用户信息(包括密码密文等),要限制只有管理员才能访问。
创建业务数据库用户时不要指定任何权限,根据业务需要创建业务数据库,并将业务数据库赋权给业务用户,执行如下SQL语句检查mysql.user表的操作权限:
select user,host from mysql.user where (Select_priv ='Y' ) or (Insert_priv ='Y' ) or (Update_priv ='Y' ) or (Delete_priv ='Y' ) or (Create_priv ='Y' ) or (Drop_priv ='Y' )or(Alter_priv ='Y' ) and user not in (admin);
select user,host from mysql.db where db ='mysql'and ( (Select_priv ='Y' ) or (Insert_priv ='Y' ) or (Update_priv ='Y' ) or (Delete_priv ='Y' ) or (Create_priv ='Y' ) or (Drop_priv ='Y' ) or(Alter_priv ='Y' ))and user not in (admin);
上述语句中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写。
避免以管理员用户创建存储过程和函数
存储过程和函数默认以创建者的身份运行,如果管理员用户创建的存储过程和函数存在提权或其他风险操作,那么普通用户会以管理员的身份运行,从而完成提权或其他风险操作,因此须避免使用管理员用户创建存储过程和函数,执行如下SQL语句检查创建存储过程和函数用户权限:
select body,definer from mysql.proc where definer not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写。
只有授权用户才能执行show databases命令
show databases命令会暴露数据库内部信息,因此必须限制该命令的执行权限。
-
执行如下SQL语句:
show variables like 'skip_show_database';
-
若返回值不为ON,则在/etc/my.cnf配置文件中添加[mysqld] skip_show_database=1。
-
重启数据库。
File_priv只能赋予超级用户
File_priv权限允许数据库用户通过load data和select into outfile命令操作后台服务器文件,需要配置为只允许超级用户有此权限。
-
执行如下SQL语句:
select user from mysql.user where File_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写。
-
若返回值不为空,则执行如下语句:
REVOKE FILE ON <host>.<databasename> FROM <your_account>
Process_priv只能赋予超级用户
Process_priv权限允许数据库用户kill连接,需要配置为只允许超级用户有此权限。
-
执行如下SQL语句:
select user from mysql.user where Process_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写。
-
若返回值不为空,则执行如下语句:
REVOKE PROCESS ON <host>.<databasename> FROM <your_account>
Super_priv只能赋予超级用户
-
执行如下SQL语句:
select user from mysql.user where Super_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写。
-
若返回值不为空,则执行如下语句:
REVOKE SUPER ON <host>.<databasename> FROM <your_account>
Shutdown_priv只能赋予超级用户
-
执行SQL语句:
select user from mysql.user where Shutdown_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写。
-
若返回值不为空,则执行如下语句:
REVOKE SHUTDOWN ON <host>.<databasename> FROM <your_account>
Create_user_priv只能赋予超级用户
-
执行SQL语句:
select user from mysql.user where Create_user_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写
-
若返回值不为空,则执行如下语句:
REVOKE CREATE USER ON <host>.<databasename> FROM <your_account>
Grant_priv只能赋予超级用户
-
执行SQL语句:
select user from mysql.user where Grant_priv = 'Y' and user not in (admin); select user from mysql.db where Grant_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写
-
若返回值不为空,则执行如下语句:
REVOKE GRANT OPTION USER ON <host>.<databasename> FROM <your_account>
Reload_priv只能赋予超级用户
-
执行SQL语句:
select user from mysql.user where Reload_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写。
-
若返回值不为空,则执行如下语句:
REVOKE RELOAC OPTION USER ON <host>.<databasename> FROM <your_account>
Repl_slave_priv只能赋予超级用户和数据复制用户
-
执行如下SQL语句:
select user from mysql.user where Repl_slave_priv = 'Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写
-
若返回值不为空,则执行如下语句:
REVOKE REPLICATION SLAVE ON <host>.<databasename> FROM <your_account>
更改MySQL默认超级用户root的名字
-
执行如下SQL语句:
select user from mysql.user where user = 'root';
-
若返回值不为空,则执行如下命令:
update mysql.user set user='<your_account>' where user='root'; flush privileges;
数据库备份用户权限要求
-
执行如下SQL语句:
select user from mysql.user where Reload_priv='Y' and Process_priv='Y' and Lock_tables_priv='Y' and Repl_client_priv='Y' and user not in (admin);
其中admin为数据库的所有管理员用户,以格式’root’,'dbuser’填写
-
若返回值不为空,则执行如下语句:
GRANT RELOAD ON <host>.<databasename> TO <your_account>; GRANT PROCESS ON <host>.<databasename> TO <your_account>; GRANT LOCK TABLES ON <host>.<databasename> TO <your_account>; GRANT REPLICATION CLIENTON <host>.<databasename> TO <your_account>;
目录权限控制
限制安装文件属主和权限
MySQL初始安装后,安装目录和文件属主要求为MySQL运行用户,目录权限要求为700,二进制文件为500,库文件为500,启动文件(一般位于/etc/init.d目录下)为500。
执行如下命令配置文件属主和权限:
chmod 500 /usr/bin/mysql*
chown mysql:dbgrp /usr/bin/mysql*
chown mysql:dbgrp /opt/mysql/data
chmod 700 /opt/mysql/data/
chown mysql:dbgrp /opt/mysql/data/*
chmod 700 /opt/mysql/data/*
chmod 700 /opt/mysql/log
chown mysql:dbgrp /opt/mysql/log
chmod 600 /opt/mysql/log/*
chown mysql:dbgrp /opt/mysql/log/*
chmod 500 /usr/lib64/mysql/plugin/
chown mysql:dbgrp /usr/lib64/mysql/plugin/
chmod 400 /usr/lib64/mysql/plugin/*
chown mysql:dbgrp /usr/lib64/mysql/plugin/*
chmod 400 /opt/mysql/data/*.pem
chmod 600 /usr/lib/systemd/system/mysqld@.service
chmod 600 /usr/lib/systemd/system/mysqld.service
限制数据库数据文件属主和权限
数据文件存储MySQL数据库的数据,如果权限控制不当,可能导致数据泄露。需要配置数据目录和文件属主为MySQL运行用户,数据目录为700,数据文件为600。
-
执行如下命令配置数据目录权限为700,配置属主为数据库运行用户:
#chmod 700 <data_dir Value> #chown mysql:dbgrp <data_dir Value>
-
执行如下命令配置数据目录下的文件权限为600,配置属主为数据库运行用户:
#chmod 600 <data_dir Value>/* #chown mysql:dbgrp <data_dir Value>/*
限制日志文件(含binlog)属主和权限
数据库日志文件属主和权限需要进行设置,防止恶意用户破坏日志。配置日志文件属主为数据库运行用户,权限为600。
查看数据库日志文件权限,默认为600,如果不满足需要配置umask,通过chmod命令修改为600。
执行如下命令配置数据目录权限为600,配置属主为数据库运行用户。
#chmod 600 < log_error Value > < slow_query_log_file Value > < general_log_file Value > < log_bin_basename Value >* < relay_log_basename Value >*
#chown mysql:dbgrp < log_error Value > < slow_query_log_file Value > < general_log_fileValue > < log_bin_basename Value >* < relay_log_basename Value >*
限制/etc/my.cnf文件属主和权限
/etc/my.cnf存储数据库配置信息,如果被篡改,会导致启动参数变化,需要对此文件属主和权限进行设置。
执行如下命令配置/etc/my.cnf文件属主为数据库运行用户,权限为600。
#chmod 600 /etc/my.cnf
#chown mysql:dbgrp /etc/my.cnf
限制Plugin目录及其文件权限
Plugin目录用于存放插件库,UDF特性的库也需要放在此目录才能生效,为了防止用户向后台注入udf库,需要对此目录的属主和权限进行设置。
-
执行如下命令配置Plugin目录权限为500,配置属主为数据库运行用户。
#chmod 500 <plugin_dir Value> #chown mysql:dbgrp <plugin_dir Value>
-
执行如下命令配置Plugin目录下的文件权限为400,配置属主为数据库运行用户。
#chmod 400 <plugin_dir Value>/* #chown mysql:dbgrp <plugin_dir Value>/*
限制SSLfile文件权限
SSl文件为客户端与服务端进行加密通信的证书相关文件,为避免恶意人员篡改,需要对属主和权限进行限制。
执行如下领命配置ssl证书相关文件属主为数据库运行用户,权限为400:
#chmod 400 <ssl_ca> < ssl_cert > < ssl_crl > <ssl_key>
#chown mysql:dbgrp <ssl_ca> < ssl_cert > < ssl_crl > <ssl_key>
Reids安全配置
部署运行要求
禁止监听地址包含0.0.0.0
0.0.0.0表示监听所有可用的IP地址,会直接将Redis服务暴露到公网上,容易受到攻击者攻击,因此须禁止。
-
执行如下命令:
netstat -plunt | grep -i redis
-
若返回结果中包含0.0.0.0,则修改配置文件redis.conf(该配置文件默认路径为/opt/redis/conf/,下同),设置bind ,重启数据库。
禁止OS超级管理员用户身份启动和运行
使用root组用户运行Redis服务有安全风险。因此禁止使用OS超级管理员用户(root)运行Redis服务,建议以低权限帐户运行Redis服务,并且配置禁止操作系统帐户登录。
执行如下命令检查运行帐户权限:
ps -ef | grep redis
专门为MongoDB建立一个单独的用户和用户组:
# groupadd redis
# useradd -g redis –s /sbin/nologin -m redis
使用密码认证
开源社区版Redis默认连接不使用认证,很容易被攻击者入侵。当主数据库连接需要密码验证时,在配置文件中设置requirepass,主备认证中使用masterauth,指定密码。
-
修改配置文件redis.conf。
- 找到“# requirepass mypassword(fobared)”,并删除#号。
- 修改mypassword为复杂度高的值,不要自己填写密码。建议使用密码生成工具生成密码。
由于该密码不需要管理员记忆,所以密码复杂度可以高于正常密码(口令)复杂度的各项要求,建议密码长度大于32个字符,随机产生,并要防止密码泄露。
-
执行如下命令,查看相应密码:
cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep requirepass
基础安全加固
禁止不使用的高危命令
-
执行如下命令查询高危命令是否禁用:
cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep rename-command | grep FLUSHALL cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep rename-command | grep FLUSHDB cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep rename-command | grep EVAL cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep rename-command | grep SHUTDOWN cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep rename-command | grep SAVE cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep rename-command | grep DEBUG
-
根据返回结果,修改服务器配置文件redis.conf,在SECURITY一项中新增命令,禁用以下命令:
rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command EVAL "" rename-command SHUTDOWN "" rename-command SAVE "" rename-command DEBUG ""
使用非默认端口
Redis Server监听的端口默认为6379,容易被扫描攻击,因此建议修改为其他自定义端口。
- 执行如下命令进行查询:
cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep port
-
在redis.conf配置文件中修改port 。
-
重启数据库。
限制数据库最大内存使用
为避免系统内存被耗尽,需要进行内存使用限制。通过设置阈值参数,限制资源耗尽和拒绝服务的可能性。
-
执行如下命令检查配置文件中maxmemory参数:
cat /opt/redis/conf/redis.conf | grep -v "^\s*#" | grep maxmemory
-
若返回值为空,则修改配置文件redis.conf,设置maxmemory,建议设置为1gb。
文件权限控制
限制配置文件属主和权限
redis.conf保存敏感信息,应该限制文件仅能够被创建者读写,文件权限应控制为600,最小化访问权限能够减少敏感信息的泄露风险。
执行如下命令限制配置文件属主和权限:
chown redis:redis /opt/redis/conf/redis.conf
chmod 700 /opt/redis/*
chmod 600 /opt/redis/conf/redis.conf
限制二进制文件属主和权限
Redis二进制文件(如redis-cli/redis-server),属主和文件权限需要进行设置,防止恶意用户破坏,要求权限设置为700。
-
执行如下命令:
#ls -l /opt/redis/bin/*
预期结果如下:
-rwx------. 1 redis redis 25088 Jul 23 16:26 /opt/redis/bin/redis-check-aof -rwx------. 1 redis redis 5180856 Jul 23 16:26 /opt/redis/bin/redis-check-rdb lrwxrwxrwx. 1 redis redis 12 Jul 23 16:26 /opt/redis/bin/redis-sentinel -> redis-server -rwx------. 1 redis redis 5180856 Jul 23 16:26 /opt/redis/bin/redis-server
-
若返回值不为预期结果,则执行如下命令:
#chmod 700 /opt/redis/bin/*
MongoDB安全配置
部署运行要求
使用非特权专用服务帐户运行
MongoDB服务不应该使用特权帐户运行,例如root权限,因为这会不必要地使操作系统面临高风险。
加固方法:创建一个用于执行MongoDB数据库活动的专用用户,并使用该用户启动MongoDB。
专门为MongoDB建立一个单独的用户和用户组:
# groupadd mongodb
# useradd -g mongodb –s /sbin/nologin -m mongodb
基础安全加固
仅在授权接口上监听网络
确保MongoDB在受信任的网络环境中运行包括限制网络接口上MongoDB实例监听传入的连接。 任何不受信任的网络连接都应该被MongoDB删除。
加固方法:mongod.conf文件中是否设置bindIP,并且bindIP不为0.0.0.0。
启用登录认证
在所有人访问MongoDB服务器之前应该完成配置验证机制。此设置确保所有客户端,用户和服务器在被授予访问MongoDB数据库权限之前都需要进行身份验证。
加固方法:
- 在mongod.conf文件中应设置
security:
authorization: enabled
或配置:
auth=true
- 设置启动参数
--auth
禁止服务端脚本
MongoDB支持一些服务器端操作执行JavaScript代码:mapReduce,group和$ where。 如果不使用这些操作,应禁用服务器端脚本。
加固方法:
- mongod.conf文件中应设置为
security:
javascriptEnabled: false
或配置:
noscripting = false
- 设置启动参数:
--noscripting
禁止通过HTTP接口进行JSONP访问
net.http.JSONPEnabled参数用于通过HTTP接口启用或禁用JSONP访问。 即使启用HTTP接口的参数设置为禁用,启用此参数也会启用HTTP接口。
加固方法:mongod.conf文件中应配置
net:
http:
JSONPEnabled: false
或配置:
jsonp=false
禁用REST接口
net.http.RESTInterfaceEnabled参数用于启用或禁用REST API。 即使启用HTTP接口的参数设置为禁用,启用此参数也会启用HTTP接口。
加固方法:mongod.conf文件中应配置
net:
http:
RESTInterfaceEnabled: false
或配置:
rest=false
禁用HTTP接口
net.http.enabled参数用于启用或禁用HTTP接口,应禁用改接口。
加固方法:mongod.conf文件中应配置
net:
http:
enabled: false
或配置:
httpinterface=false
文件权限控制
MongoDB数据库文件需要设置文件权限进行保护。
建议mongodb配置文件的权限为640,建议存放数据的目录的权限为600,建议mongodb日志文件的权限为640。
Memcached安全配置
基础安全加固
非特权用户运行
用于运行Memcached的用户必须是一个没有特权的用户:
专门为Memcached建立一个单独的用户和用户组:
# groupadd memcached
# useradd -g memcached –s /sbin/nologin -m memcached
限制监听地址
如果Memcached没有在公网开放的必要,可在Memcached启动时指定绑定的IP地址为 127.0.0.1。
memcached -d -m 1024 -u memcached -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pid
其他组件加固
Zookeeper安全配置
部署运行要求
非特权用户运行
用于运行zookeeper的用户必须是一个没有特权的用户:既无权访问非必须的文件,又不能执行非必须的程序。
缺省情况下,Java运行时根据运行它的用户授予安全权限。当zookeeper以系统管理员身份或作为系统服务运行时,Java运行时取得了系统用户或系统管理员所具有的全部权限,因此需要对用户权限进行限制。
当安装帐户为超级管理员时,具体操作如下:
专门为zookeeper建立一个单独的用户和用户组:
# groupadd zookeeper
# useradd -g zookeeper –s /sbin/nologin -m zookeeper
限制监听地址
监听地址不允许包含*,减少对外暴露的风险,监听地址设置命令如下:
clientPortAddress=192.168.1.100
目录权限控制
根目录权限修改
zookeeper根目录只能由zookeeper属主用户修改(700),zookeeper根目录的所有父级目录的修改权限不能赋予除超级管理员用户和zookeeper属主的其他普通用户。
如果要配置zookeeper根目录为“/home/zookeeper”,首先要确认“/”、“/home”目录只能由root修改,“/home/zookeeper”目录只有root和zookeeper属主用户才有修改权限,其他用户不能具备这些目录的修改权限,其次使用zookeeper属主用户执行下列命令:
#chmod –R 755 zookeeper-3.4.10
#chow –R zookeeper:robogrp zookeeper-3.4.10
可执行文件修改
可执行文件只能由zookeeper属主用户修改(700)。
设置可执行文件的权限,例如bin目录下的执行文件,使用zookeeper属主用户执行下列命令:
#cd $zookeeper/bin
#chmod 600 *
#chmod 700 *.sh
配置目录和文件修改
配置目录和文件只能由zookeeper属主用户修改(600)。
执行如下命令进行修改:
# cd $zookeeper/conf
# chmod 600 *
日志路径限制
zookeeper日志路径要限制其访问权限,只能zookeeper属主访问。
使用zookeeper属主用户执行下列命令:
# cd $zookeeper
# chmod 700 $zookeeper/logs
# chmod 600 $zookeeper/logs/*
Elasticsearch安全配置
基础安全加固
- 非特权用户运行
用于运行Elasticsearch的用户必须是一个没有特权的用户:
专门为Elasticsearch建立一个单独的用户和用户组:
# groupadd elasticsearch
# useradd -g elasticsearch –s /sbin/nologin -m elasticsearch
- 限制监听地址
如果要映射开放端口,要限定好指定 IP 访问
进入 config
目录,修改 elasticsearch.yml
配置文件中以下参数:
network.bind_host: 192.168.0.1# 设置绑定的 IP 地址,可以是 IPv4 或 IPv6 地址,默认为 0.0.0.0。
network.publish_host: 192.168.0.1# 设置其它节点和该节点交互的 IP 地址,如果不设置它会自动判断,值必须是个真实的 IP 地址。
network.host: 192.168.0.1# 同时设置上述两个参数:bind_host 和 publish_host。
- 修改默认端口
进入 config
目录,修改 elasticsearch.yml
配置文件中以下参数:
ransport.tcp.port: 9300# 设置节点间交互的 TCP 端口,默认是 9300。
transport.tcp.compress: true# 设置是否压缩 TCP 传输时的数据,默认为 false,即不压缩。
http.port: 9200# 设置对外服务的 HTTP 端口,默认为 9200。
- 关闭 HTTP 访问
进入 config
目录,修改 elasticsearch.yml
配置文件中以下参数:
http.enabled: false# 是否使用 HTTP 协议对外提供服务,默认为 true,即开启。
- 升级高版本 Elasticsearch,使用 X-pack 基础安全功能
Elasticsearch 7.1&6.8 版本之后,X-pack 基础安全功能免费。这意味着:
Space、角色、用户基础功能免费,Elasticsearch、Kibana 访问都可以设置上复杂的用户名和密码。
集群之间 TLS 加密通信免费。
互联网访问可以由 HTTP 升级为 HTTPS。
或者利用 Nginx 设置 HTTP Basic 认证来实现 Elasticsearch 的登录认证。
- 禁用批量删除索引
Elasticsearch 支持使用全部(_all
)和通配符(*
)来批量删除索引。在生产环境,该操作存在一定风险,可以通过设置 action.destructive_requires_name: true
参数来禁用它。
er”,首先要确认“/”、“/home”目录只能由root修改,“/home/zookeeper”目录只有root和zookeeper属主用户才有修改权限,其他用户不能具备这些目录的修改权限,其次使用zookeeper属主用户执行下列命令:
#chmod –R 755 zookeeper-3.4.10
#chow –R zookeeper:robogrp zookeeper-3.4.10
可执行文件修改
可执行文件只能由zookeeper属主用户修改(700)。
设置可执行文件的权限,例如bin目录下的执行文件,使用zookeeper属主用户执行下列命令:
#cd $zookeeper/bin
#chmod 600 *
#chmod 700 *.sh
配置目录和文件修改
配置目录和文件只能由zookeeper属主用户修改(600)。
执行如下命令进行修改:
# cd $zookeeper/conf
# chmod 600 *
日志路径限制
zookeeper日志路径要限制其访问权限,只能zookeeper属主访问。
使用zookeeper属主用户执行下列命令:
# cd $zookeeper
# chmod 700 $zookeeper/logs
# chmod 600 $zookeeper/logs/*
Elasticsearch安全配置
基础安全加固
- 非特权用户运行
用于运行Elasticsearch的用户必须是一个没有特权的用户:
专门为Elasticsearch建立一个单独的用户和用户组:
# groupadd elasticsearch
# useradd -g elasticsearch –s /sbin/nologin -m elasticsearch
- 限制监听地址
如果要映射开放端口,要限定好指定 IP 访问
进入 config
目录,修改 elasticsearch.yml
配置文件中以下参数:
network.bind_host: 192.168.0.1# 设置绑定的 IP 地址,可以是 IPv4 或 IPv6 地址,默认为 0.0.0.0。
network.publish_host: 192.168.0.1# 设置其它节点和该节点交互的 IP 地址,如果不设置它会自动判断,值必须是个真实的 IP 地址。
network.host: 192.168.0.1# 同时设置上述两个参数:bind_host 和 publish_host。
- 修改默认端口
进入 config
目录,修改 elasticsearch.yml
配置文件中以下参数:
ransport.tcp.port: 9300# 设置节点间交互的 TCP 端口,默认是 9300。
transport.tcp.compress: true# 设置是否压缩 TCP 传输时的数据,默认为 false,即不压缩。
http.port: 9200# 设置对外服务的 HTTP 端口,默认为 9200。
- 关闭 HTTP 访问
进入 config
目录,修改 elasticsearch.yml
配置文件中以下参数:
http.enabled: false# 是否使用 HTTP 协议对外提供服务,默认为 true,即开启。
- 升级高版本 Elasticsearch,使用 X-pack 基础安全功能
Elasticsearch 7.1&6.8 版本之后,X-pack 基础安全功能免费。这意味着:
Space、角色、用户基础功能免费,Elasticsearch、Kibana 访问都可以设置上复杂的用户名和密码。
集群之间 TLS 加密通信免费。
互联网访问可以由 HTTP 升级为 HTTPS。
或者利用 Nginx 设置 HTTP Basic 认证来实现 Elasticsearch 的登录认证。
- 禁用批量删除索引
Elasticsearch 支持使用全部(_all
)和通配符(*
)来批量删除索引。在生产环境,该操作存在一定风险,可以通过设置 action.destructive_requires_name: true
参数来禁用它。
- 根据需要继续更新
声明:手册内容来自各方面资料整理,并非完全原创