docker部署nginx+php+mysql开发环境
# 信安之路-第一关
静中藏了一个争字,稳中藏了一个急字,忙中藏了一个亡字,忍中藏了一个刀字,越想争心越要静。越急心越要稳。越忙越要照顾好自己。越忍越要看清事态
本次目的:熟悉Linux+Nginx+PHP-fpm-Mysql开发环境的搭建。从基本开始,一步一步来。搭建完成后,进行加固,熟悉基础加固的思路。
linux
linxu采用centos虚拟机安装 最小化安装。安装完成后换源.
换源
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup #备份
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里云的源
yum makecache #生成缓存
加固
从互联网收集的加固手册,按着流程来一遍。先来一个自己总结的思维导图
账号管理
账号
用户口令设置
- 由于虚拟机搭建使用简单口令,root/root,对口令进行加强
- 执行:more /etc/login,检查PASS_MAX_DAYS/PASS_MIN_LEN/PASS_MIN_DAYS/PASS_WARN_AGE参数
- awk -F: '($2 == "") { print $1 }' /etc/shadow 检查是否存在空口令账号
思考:弱口令 空口令 密码复杂度
检查是否存在除root之外UID为0的用户
awk -F: '($3 == 0) { print $1 }' /etc/passwd #
只允许root一个uid为0
root用户环境变量的安全性
echo $PATH | egrep '(^|:)(\.|:|$)' #检查是否包含父目录
find `echo $PATH | tr ':' ' '` -type d \( -perm -002 -o -perm -020 \) -ls 检查是否包含组目录权限为777的目录
思考:确保root用户的系统路径中不包含父目录,在非必要的情况下,不应包含组权限为777的目录
认证
远程连接的安全性配置
执行:find / -name .netrc,检查系统中是否有.netrc文件
执行:find / -name .rhosts ,检查系统中是否有.rhosts文件
有文件则低于要求
用户的umask安全配置
执行: more /etc/csh.login more /etc/csh.cshrc more /etc/bashrc检查是否包含umask值 默认的低于要求
重要目录和文件的权限设置
ls –l /etc/
ls –l /etc/rc.d/init.d/
ls –l /tmp
ls –l /etc/inetd.conf
ls –l /etc/passwd
ls –l /etc/shadow
ls –l /etc/group
ls –l /etc/security
ls –l /etc/services
ls -l /etc/rc*.d # 权限过低,则低于安全要求
重要目录需要 chmod -R 750 file 只有root可以读、写和执行这个目录下的脚本
查找未授权的SUID/SGID文件
for PART in `grep -v ^# /etc/fstab | awk '($6 != "0") {print $2 }'`; do
find / \( -perm -04000 -o -perm -02000 \) -type f -xdev -print
Done #非空低于要求
检查任何人都有写权限的目录
for PART in `awk '($3 == "ext2" || $3 == "ext3") \
{ print $2 }' /etc/fstab`; do
find / -xdev -type d \( -perm -0002 -a ! -perm -1000 \) -print
Done #非空低于要求
查找任何人都有写权限的文件
for PART in `grep -v ^# /etc/fstab | awk '($6 != "0") {print $2 }'`; do
find $PART -xdev -type f \( -perm -0002 -a ! -perm -1000 \) -print
Done #非空低于要求
查找没有属主的文件
for PART in `grep -v ^# /etc/fstab | awk '($6 != "0") {print $2 }'`; do
find $PART -nouser -o -nogroup -print
done #非空低于要求
检查异常隐含文件
find / -name ".. *" -print –xdev
find / -name "…*" -print -xdev | cat -v #非空低于要求
日志审计
日志
more /etc/syslog.conf 查看参数authpriv值 对所有登录事件都记录
审计
more /etc/syslog.conf
#需设置
kern.warning;*.err;authpriv.none\t@loghost
*.info;mail.none;authpriv.none;cron.none\t@loghost
*.emerg\t@loghost
local7.*\t@loghost
系统文件
系统core dump状态
more /etc/security/limits.con
#需要包含一下项
* soft core 0
* hard core 0
其他思考
1. 指定IP可以远程登录,设置远程登录超时
2. 禁止直接登录root账户,需要从普通账户su到root;结合前边的禁止su到root,就只能本地root账户登录了
3. 开启防火墙
4. 对web业务开启防ddos攻击防护
5. 更改主机解析地址顺序,防止IP欺骗。
6. 补丁更新,防止被提权
7. 一些系统的指纹信息屏蔽 比如ftp ssh等等
nginx+php+mysql-docker部署
docker pull nginx
docker pull php:7.1-fpm
docker pull mysql:5.7
创建文件夹
# 网站目录
mkdir -p /data/www
# nginx 配置
mkdir -p /data/nginx/conf.d
# mysql数据
mkdir -p /data/mysql/data
# mysql配置
mkdir -p /data/mysql/conf.d
创建 Nginx 容器
docker run --rm nginx cat /etc/nginx/nginx.conf > /data/nginx/nginx.conf
#将nginx配置文件nginx.conf复制到主机/data/nginx目录中
docker run --name nginx \
-v /data/www:/usr/local/html \
-v /data/nginx/conf.d:/etc/nginx/conf.d \
-v /data/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
--net=host \
-d nginx
#创建nginx
docker run --name php-fpm \
-v /data/www:/var/www/html \
-d php:7.1-fpm
#创建php
#查看php ip
docker inspect php-fpm --format='{{.NetworkSettings.IPAddress}}'
# 返回 IP
172.17.0.2
vim /data/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.php index.html index.htm;
}
location ~ \.php(.*)$ {
root /var/www/html; # php 容器的目录,进 php 容器查看
fastcgi_pass 172.17.0.2:9000; # php 容器的IP
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}# 创建 Nginx 配置文件
docker restart nginx #重启nginx容器
docker ps
测试
echo "<?php phpinfo(); ?>" > /data/www/info.php
curl http://127.0.0.1/info.php
创建 MySQL 容器
docker run --name mysql \
-p 3306:3306 \
-v /data/mysql/conf.d:/etc/mysql/conf.d \
-v /data/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
安装php扩展
# 进入容器
docker exec -it php-fpm /bin/bash
# 安装 pdo_mysql mysqli
docker-php-ext-install pdo_mysql mysqli
# CTRL + D 退出容器
docker restart php-fpm
连接 MySQL测试
docker inspect mysql --format='{{.NetworkSettings.IPAddress}}'
查看mysql的ip
# 返回 IP
172.17.0.3
编辑连接测试文件
vim /data/www/conn.php
<?php
$serve = '172.17.0.3:3306';
$username = 'root';
$password = '123456';
$dbname = 'mysql';
$mysqli = new Mysqli($serve,$username,$password,$dbname);
if ($mysqli->connect_error) {
die('connect error:'.$mysqli->connect_errno);
}
$mysqli->set_charset('UTF-8');
$result = $mysqli->query('select * from user');
$data = $result->fetch_all();
print_r($data);
?>
curl http://127.0.0.1/conn.php #测试
nginx加固
nginx作为优秀的正反向代理web服务器,多线程,高并发等特点。顺便记下正反向代理,代理客户端就是正向,反之代理服务端就是反向代理。另外正向代理可以作为上网行为管理;反向代理除了负载均衡,暴露的是代理服务器在公网的IP,隐藏了内网web服务器
限制目录访问
vi /etc/nginx/nginx.conf 在HTTP模块增加 autoindex off; 因为nginx会自动下载web目录下的文件,增加威胁暴露面。
隐藏版本信息
vi /etc/nginx/nginx.conf 在HTTP模块增加server_tokens off 隐藏版本信息,如HTTP响应里就看不到了。这里得重启,重新载入配置不管用。
限制HTTP请求方法
vi /etc/nginx/conf.d/default.conf 在server模块增加
if ($request_method !~* GET|POST|HEAD) {
return 403;
} //拒绝除了get|post|head外的请求方式
nginx权
vi /etc/nginx/nginx.conf 增加 user nobody; 这样就算web服务权限失陷,也不会是root权限。这还涉及运维知识,nobody是Linux用来执行服务主进程之外进程的用户,为了达到失少不失全效果,若一开始用root部署的nginx,做好了负载均衡,后边重启服务每次都要root,麻烦;而且想换了,还会导致缓存访问权限不足进而进程缓慢,服务瘫痪等后患。
限制IP访问
编辑nginx.conf配置文件(vi /etc/nginx/nginx.conf ),在server标签内添加如下内容:
location / {
deny ip;
allow ip;
}
防盗链
编辑nginx.conf配置文件(vi /etc/nginx/nginx.conf ),在server标签内添加如下内容:
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ {
valid_referers none blocked server_names *.nsfocus.com http://localhost baidu.com;
if ($invalid_referer) {
rewrite ^/ [img]http://www.XXX.com/images/default/logo.gif[/img];
#return 403;
}
}
补丁更新
nginx -v #查看版本信息
nginx -t #查看配置文件
然后选择补丁
php加固
php-fpm降权
修改/etc/php-fpm.d/www.conf,将 user = apache group = apache,改为 user = nobody group = nobody
安全模式
5.3以后没有了
禁用不安全的PHP函数
vi /etc/php.ini
disable_functions = passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,phpinfo
#这样之前测试php nginx连通用的phpinfo函数就失效了。
关闭错误日志
vi /etc/php.ini
display_errors = Off
#避免报错暴露物理路径造成的文件上传或者sql报错注入、getshell。之前i春秋的ctf初级训练营里有一个就是利用PHP报错查看到数据库版本吧好像。
启用HTTPOnly
vi /etc/php.ini
session.cookie_httponly = 1
通过document盗用cookie预防XSS,但是可以在socket层抓包程序进阶攻击。
关闭PHP信息
vi /etc/php.ini
expose_php = Off
这样设置在http请求里就看不到x-powered-by:php/5.4.16了
限制目录访问
vi /etc/php.ini
open_basedir = ./:/tmp:/home/www/配置的目录 坏处就是影响IO流
限制上传目录
vi /etc/php.ini
upload_tmp_dir = /tmp定义的上传目录,防止目录穿越。