搭建web运行的基础环境
基本信息
- 任务目标:准备学习环境,学习web服务器的搭建过程,并做相应的加固学习
- 操作系统:win10家庭版+ vm15
- 预装环境:ubuntu 18.04 + nginx + php-fpm + mysql
- 报告要求:搭建过程详细记录,收集加固文档,学习加固技术
搭建 0x01
安装 nginx + php-fpm + mysql
Nginx的安装
这篇文章涵盖nginx + php-fpm + mysql的详细安装过程和指南
更新系统软件源
- 备份原有软件源文件
cp /etc/apt/sources.list /etc/apt/sources.list.bak
- 打开并更改
sudo gedit /etc/apt/sources.list
- 添加源
1 | #添加阿里源 |
更新
sudo apt-get update
sudo apt-get upgrade
当
sudo apt-get update
出现
W: Some index files failed to download. They have been ignored, or old ones used instead.时
解决方案sudo vim /etc/resolv.conf
添加
1 | #这里用的使用的是阿里云的DNS服务器,根据你使用的源来填写 |
再次更新
参考:
https://blog.csdn.net/feiniao8651/article/details/60332535
- 其他
其他源
但从个人经历而言
最好的方法是使用Software & Update的Select Best Server来选择源
点击Download from
后选择Select Best Server
安装 nginx
sudo apt-get install nginx
文件结构大致如下:
- 所有配置文件在
/etc/nginx
,且每个虚拟主机已经安排在/etc/nginx/sites-acailable/
- 程序文件在
/usr/sbin/nginx
但目前没有? - 日志文件在
/var/log/nginx
- 默认的虚拟主机的目录设置在
/var/www/html
注意,请看配置文件/etc/nginx/sites-acailable/
- 启动脚本
sudo /etc/init.d/nginx start
,访问 http://127.0.0.1
安装php ,mysql
考虑版本更新问题,装php7.4版本
php支援版本信息
- Add PHP PPA Repository
1 | sudo apt-get update |
可能遇到问题
add-apt-repository ppa:ondrej/php
会有错误或长时间无回应
字符编码的锅
解决方案
1 | sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php |
- 但有Error显示
Error: retrieving gpg key timed out.
需要手动添加ppa源
PPA源
注意要选择版本
1 | deb http://ppa.launchpad.net/ondrej/php/ubuntu bionic main |
打开源并添加sudo gedit /etc/apt/sources.list
1 | deb http://ppa.launchpad.net/ondrej/php/ubuntu bionic main |
在Terminal添加Signing Keysudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 14AA40EC0831756756D7F66C4F4EA0AAE5267A6C
再更新sudo apt-get update && sudo apt-get upgrade
推荐另一种方法 install PHP 7.4 & mysql
首先添加sury.org提供的存储库
1 | sudo apt-get install apt-transport-https -y |
更新软件包列表
1 | sudo apt-get update |
安装用于nginx和PHP -fpm功能的PHP 7.4包
1 | sudo apt-get install php7.4-cli php7.4-curl php7.4-mysql php7.4-fpm php7.4-gd php7.4-xml php7.4-mbstring php7.4-zip php7.4-soap php7.4-dev -y |
如果这步报错试试
1 | sudo apt-get install libcurl3 |
将CLI更新到PHP 7.4
1 | sudo update-alternatives --set php /usr/bin/php7.4 |
mysql install
1 | sudo apt install mysql-server |
进行安装与配置
1 | sudo mysql_secure_installation |
安装之后便可使用
1 | sudo mysql |
配置 Nginx
修改主机名于配置文件
1 | sudo gedit /etc/nginx/sites-available/default |
添加index.php
更改一下注释为
1 | location ~ \.php$ { |
重启nginx和php
1 | sudo service nginx restart |
测试
1 | vim /var/www/html/info.php |
访问localhost/info
/var/www/html
目录下,创建数据库连接文件conmysql.php
1 |
|
url localhost/conmysql.php
参考文章:
php7.4 install
Install PHP 7.4 FPM on Ubuntu 18.04
Ubuntu Nginx
how-to-install-linux-nginx-mysql-php-lemp-stack-ubuntu-18-04
Ubuntu 16.04中配置nginx + php + mysql
模拟环境搭建
在安全加固之前,可以先搭建模拟环境,同时也便于今后学习。这一点从Keefe_blog学来。
- 创建数据库
1 | mysql - u root -p123 |
conmysql.php
1 |
|
index.php
1 | <!DOCTYPE html> |
参考:
搭建 LNMP 环境及一些安全加固总结
runoob_php
安全加固
此部分的学习基本上源于网上的相关文档。分别从php、msyql、nginx、ubuntu四个部分进行安全加固。
参考文章:
web安全加固
https://github.com/php/php-src
PHP环境安全加固
centos lnmp及安全加固
[nginx安全配置 ][nginx安全配置 ]
Nginx 加固
配置文件
- 安装位置: /etc/nginx
- 全局站点的配置文件: /etc/nginx/nginx.conf
- 网站默认站点配置文件: /etc/nginx/sites-available/default
- 需注意修改文件后,要重新加载
1 | sudo service nginx reload |
隐藏nginx版本号
nginx版本信息的泄露,将便于黑客查找相应版本的漏洞并利用。
修改 /etc/nginx/nginx.conf
将server_token off
前的注释删去即可。
此时报错后无版本信息
禁止目录浏览
打开目录浏览,会将文件和文件夹信息暴力出来,一般默认关闭
/etc/nginx/sites-available/default
相应效果
autoindex off;
当关闭时,会显示403
限制访问敏感文件
这类问题主要是源代码或敏感信息泄露。
常见的有.DS_Store,.git,.ht,各类压缩文件(.rar .zip .7z .tar.gz ),备份文件(.bak) ,.txt
之外 还有 SVN导致文件泄露, WEB-INF/web.xml泄露 CVS泄漏
修改文件为/etc/nginx/sites-available/default
1 | # Restrict access to sensitive files in test folder |
这将禁止可以防止.ht .git .bak .7z .zip .rar .txt文件泄露,但最好的方法还是删除 不必要的文件
推荐:
限制HTTP请求方式
只允许GET|POST|HEAD 这三种方式请求,如果是之外的请求,则返回444状态码
444 是 Nginx 定义的响应状态码,会立即断开连接,没有响应正文
1 | if ($request_method !~ ^(GET|HEAD|POST)$ ) { |
Nginx降权启动
在 /etc/nginx/nginx.conf
修改
1 | user nobody; |
当然也可以使用普通用户,来防止ROOT分配权限过大。
nobody在linux中是一个不能登陆的帐号,一些服务进程如apache,aquid等都采用一些特殊的帐号来运行,比如nobody,news,games等等,这是就可以防止程序本身有安全问题的时候,不会被黑客获得root权限
禁止文件上传目录执行php
其配置方式与限制访问敏感文件一致
注意空格
1 | location ~* ^/(attachments|data)/.*\.(php|php5)$ { |
针对SQL注入的配置
参考于:
https://blog.csdn.net/lyj1101066558/article/details/54346053
https://www.imydl.tech/lnmp/762.html
1 | if ($request_method !~* GET|POST) { return 444; } |
PHP 加固
配置文件
php 的 配置文件为 php.ini,其具体位置可通过phpinfo()查询(/etc/php/7.4/fpm/php.ini)。
关于PHP的安全模式
1 | safe_mode = on |
但safe_mode早在php5.3起废除,并将自 PHP 5.4.0 起移除。当然也不排除有些网站还会使用php5.3之前的版本.
具体信息features.safe-mode.php
禁用不安全的PHP 函数
我这边php.ini中之前有默认设置
1 | disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, |
然后添加了
1 | 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 |
关闭错误显示
display_errors = Off
避免因为错误而泄露相关信息
设置错误日志
log_errors = On
错误和日志记录配置选项
Session 安全配置可以查看
session.security.ini.phpsession.cookie_httponly=On
禁止 JavaScript 访问会话 cookie。 此设置项可以保护 cookie 不被 JavaScript 窃取。推荐会话ID cookie 设置 httponly 为 On。
关闭PHP信息
限制跨目录访问
open_basedir = /www/
默认是所有文件
将PHP可以访问的文件限制在指定的目录树中,包括文件本身。这个指令不受安全模式是开启还是关闭的影响。官方手册描述
Note:
As of PHP 5.3.0 open_basedir can be tightened at run-time. This means that if open_basedir is set to /www/ in php.ini a script can tighten the configuration to /www/tmp/ at run-time with ini_set(). When listing several directories, you can use the PATH_SEPARATOR constant as a separator regardless of the operating system.
上传目录限制
upload_tmp_dir = /tmp
执行文件上载时用于存储文件的临时目录。必须是可写的任何用户PHP正在运行。如果没有指定,PHP将使用系统的默认值 . 其他有关upload 的还有 file_uploads upload_max_filesize max_file_uploads
SQL注入防护
magci_quotes_gps
为 GPC (Get/Post/Cookie) 操作设置 magic_quotes 状态。 当 magic_quotes 为 on,所有的 ‘ (单引号)、” (双引号)、\(反斜杠)和 NUL’s 被一个反斜杠自动转义。适用版本:在 PHP <= 4.2.3 是 PHP_INI_ALL,在 PHP 5.4.0 中被移除
Note:
如果 magic_quotes_sybase 也是 ON,它会完全覆盖 magic_quotes_gpc。 两个指令都启用意味着只有单引号被转义为 ‘’。 双引号、反斜杠和 NUL’s 不会被转义。
mysql加固
参考:
账户安全
- 禁止使用管理员权限运行
以普通账户安全运行mysqld,禁止以管理员账号权限来运行MYSQL 服务,
配置文件/etc/mysql/my.cnf
为全局选项, ~/.my.cnf
为用户特定选项
修改为
[mysql.server] user=mysql
刷新生效1
2
3
4
5
6
7
* 避免不同用户间共享账号
* * 创建用户 xzlxr 密码 xzlxr2333
```mysql
GRANT USAGE ON *.* TO 'xzlxr'@'%' IDENTIFIED BY 'any@hin$' WITH GRANT OPTION;查看账户1
FLUSH PRIVILEGES;
1
select host,user,authentication_string from mysql.user;
切换账号
1
mysql -u xzlxr -p
删除账号
使用DROP USER 可以删除一个或多个MYSQL账户。使用 DROP USER 语句必须拥有 MySQL 中的 MySQL 数据库的 DELETE 权限或全局 CREATE USER 权限。在 DROP USER 语句的使用中,若没有明确地给出账户的主机名,则该主机名默认为“%”
没有权限时的ERROR
ERROR 1227 (42000): Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation
口令
检查账户默认密码和弱密码。口令长度需要至少八位,并包括数字、小写字母、大写字母和特殊符号四类中的至少两种类型,且五次以内不得设置相同的口令。密码应至少每 90 天进行一次更换。
1 | update user set authentication_string=password('any@hin$') where user="xzlxr"; |
授权
在数据库权限配置能力范围内,根据用户的业务需要,配置其所需的最小权限。
查看数据库授权情况
1
2
3
4
5
6use mysql;
select * from user;
select * from db;
select * from host;
select * from tables_priv;
select * from columns_priv;更新权限,为xzlxr用户添加SELECT 权限
1
2
3SELECT Host,User,Select_priv,Grant_priv from user where user = 'xzlxr'; #查看权限
update user set Select_priv = "Y" where user='xzlxr';
flush privileges通过 revoke 命令回收不必要的或危险的授权。
可以使用
help revoke
来查看使用
开启日志审核功能
数据库应配置日志功能,便于记录运行状况和操作行为。
MySQL服务有以下几种日志类型:
错误日志 | -log-err |
---|---|
查询日志 | -log (可选) |
慢查询日志 | -log-slow-queries (可选) |
更新日志 | -log-update |
二进制日志 | -log-bin |
1 | #Enter a name for the binary log. |
日志查询操作说明
执行show variables like 'log_%';
命令可查看所有的 log。
此处已经添加error.log
my.cnf的其他配置
其他配置推荐看这篇
搭建 0x02
Apache
安装 Apache
apache2的安装我还是安装在原ubuntu上的
1 | sudo apt install apache2 |
配置文件
- apache2的配置文件在
1 | /etc/apache2/apache2.conf |
同时在apache2.conf 描述了配置文件,apache2.conf 为一个主配置文件,通过including 方式包含其他配置文件.如果需要更多详细信息可以看官网
此外,在/usr/share/doc/apache2/README.Debian.gz
中描述了apache2在Debain中的特殊点
两个文件都写的很仔细,好评
- apache2的目录
1 | # /etc/apache2/ |
- 端口配置文件为
/etc/apache2/ports.conf
1 | # If you just change the port or add more ports here, you will likely also |
mods-availablel
和mods-enabled
文件夹:这两个文件夹里面存放的都是一些apache2的读写操作等模块,mods-enabled
是apache2服务器启动配置的文件,mods-available
是apache2服务器可以用的配置文件
如果需要添加功能模块,可在mods-available
中建立软连接到mods-enabled
.
site-available
和site-enabled
是网站根目录的配置文件.
同样在site-enabled
中保留的是site-available
的软连接
在 site-available
有两个文件
配置文件名称 | 说明 |
---|---|
000-default.conf | 使用http协议网站的默认网站配置文件 |
default-ss.conf | https协议网站才使用的默认网站配置文件,使用的话,还需申请SSL证书。 |
000-default.conf
所以主要的配置工作是在000-default.conf
中
1 | <VirtualHost *:80> |
ServerAdmin webmaster@localhost
#设置站点邮箱
DocumentRoot /var/www/html
#DocumentRoot 为该站点的根目录
- 在
etc/apache2/mods-available/dir.conf
中,DirectoryIndex为Apache默认起始页面
1 | <IfModule mod_dir.c> |
- 配置中添加php配置
1 | ln -s /etc/apache2/conf-available/php7.4-fpm.conf /etc/apache2/conf-enabled/php7.4-fpm.conf |
软连接即可
访问index.php
安全加固
参考:
Apache2 security_tips
Apache服务安全加固
推荐:http-announce以获取Apache信息
网上对这部分基本相识
账号设置
根据需要,为 Apache 服务创建用户及用户组。如果没有设置用户和组(默认是www-data),则新建用户,并在 Apache 配置文件中进行指定。
1 | groupadd apache #创建 Apache 用户组 |
根据在apache2.conf
中的信息
1 | These need to be set in /etc/apache2/envvars |
之后再修改/etc/apache2/envvars
文件(注此为Ubuntu系统)
1 | export APACHE_RUN_USER=apache |
授权设置
- 严格控制 Apache 主目录的访问权限,非超级用户不能修改该目录中的内容。
1 | ServerRoot: The top of the directory tree under which the server's |
一般而言,默认配置已经符合要求。
这里有个疑惑为什么给的配置文件中给ServerRoot注释掉?
- 严格设置配置文件和日志文件的权限,防止未授权访问。
/etc/apache/
默认属主可读写,其他用户拥有只读权限。
1
2
3
4
5
6
7
8
9
10
11
12
13 total 96
drwxr-xr-x 8 root root 4096 Mar 14 10:15 .
drwxr-xr-x 132 root root 12288 Mar 14 09:14 ..
-rw-r--r-- 1 root root 7224 Dec 3 07:55 apache2.conf
drwxr-xr-x 2 root root 4096 Mar 14 21:05 conf-available
drwxr-xr-x 2 root root 4096 Mar 14 21:07 conf-enabled
-rw-r--r-- 1 root root 1782 Jul 16 2019 envvars
-rw-r--r-- 1 root root 31063 Jul 16 2019 magic
drwxr-xr-x 2 root root 12288 Mar 14 21:05 mods-available
drwxr-xr-x 2 root root 4096 Mar 14 21:05 mods-enabled
-rw-r--r-- 1 root root 320 Jul 16 2019 ports.conf
drwxr-xr-x 2 root root 4096 Mar 14 01:37 sites-available
drwxr-xr-x 2 root root 4096 Mar 14 01:37 sites-enabled
将apache2.conf
改为600权限,即仅ROOT用户读写
1
2
3
4
5
6
7
8
9
10
11
12 drwxr-xr-x 8 root root 4096 Mar 14 10:15 .
drwxr-xr-x 132 root root 12288 Mar 14 09:14 ..
-rw------- 1 root root 7224 Dec 3 07:55 apache2.conf
drwxr-xr-x 2 root root 4096 Mar 14 21:05 conf-available
drwxr-xr-x 2 root root 4096 Mar 14 21:07 conf-enabled
-rw-r--r-- 1 root root 1782 Jul 16 2019 envvars
-rw-r--r-- 1 root root 31063 Jul 16 2019 magic
drwxr-xr-x 2 root root 12288 Mar 14 21:05 mods-available
drwxr-xr-x 2 root root 4096 Mar 14 21:05 mods-enabled
-rw-r--r-- 1 root root 320 Jul 16 2019 ports.conf
drwxr-xr-x 2 root root 4096 Mar 14 01:37 sites-available
drwxr-xr-x 2 root root 4096 Mar 14 01:37 sites-enabled
日志设置
Apache 设备应配置日志功能,对运行错误、用户访问等事件进行记录,记录内容包括时间,用户使用的 IP 地址等内容,它们也会让您了解对服务器引发的攻击,并允许您检查是否存在必要的安全级别。
- error.log
1 | ErrorLog: The location of the error log file. |
${APACHE_LOG_DIR}
在envvars
文件有描述
1
2 Only /var/log/apache2 is handled by /etc/logrotate.d/apache2.
export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
LogLevel
命令用于调整记录在错误日志中的信息的详细程度,建议设置为 notice。日志的级别,默认是 warn 级别,notice 级别比较详细,但在实际中由于日志会占用大量硬盘空间。
1
2
3
4
5
6
7 LogLevel: Control the severity of messages logged to the error_log.
Available values: trace8, ..., trace1, debug, info, notice, warn,
error, crit, alert, emerg.
It is also possible to configure the log level for particular modules, e.g.
"LogLevel info ssl:warn"
LogLevel warn
- access_log
http://httpd.apache.org/docs/2.4/logs.html#accesslog
默认是
1 |
|
添加CustomLog /var/log/apache2/access_log vhost_combined
重启Apache
1 | root@ubuntu:/etc/apache2# find /var -name access_log |
禁止访问外部文件 和 禁止目录列出
禁止 Apache 访问 Web 目录之外的任何文件。
禁止访问设置在原配置文件中是有说明的,且在官方网站上的安全提示中也提到
- 说明
1 | Sets the default security model of the Apache2 HTTPD server. It does |
- 与上面说明相对于的默认配置
1 | <Directory /> |
简单说明
不允许访问
/usr/share
和/var/www
之外的根文件系统。
/usr/share
用于Debian中打包的Web应用程序
/var/www
用于Web服务器服务的本地目录
- 禁止目录列出
在/var/www
设置中有Options Indexes FollowSymLinks
Indexes 的作用就是当该目录下没有 index.html 文件时,就显示目录结构,去掉 Indexes,Apache 就不会显示该目录的列表了。
即
1 | <Directory /var/www/> |
效果
错误页面重新定向
Apache 错误页面重定向功能可以防止敏感信息泄露。
参考:
https://www.howtoing.com/how-to-configure-apache-to-use-custom-error-pages-on-ubuntu-14-04
- 在重新定向前,需要创建一些自定义的页面
custom_404.html
1 | <h1 style='color:red'>Error 404: Not found :-(</h1> |
custom_50x.html
1 | <h1>Oops! Something went wrong...</h1> |
- 配置
配置文件是000-default.conf
1 | <VirtualHost *:80> |
- 404 当访问不存在的页面时,报错
拒绝服务(dos)攻击
所有网络服务器都可能遭受拒绝服务攻击,这种攻击试图通过占用服务器的资源来阻止对客户机的响应。完全阻止这种攻击是不可能的,但是您可以做一些事情来减轻它们所造成的问题。通常最有效的反dos工具是防火墙或其他操作系统配置。例如,可以将大多数防火墙配置为限制来自任何单个IP地址或网络的并发连接数量,从而防止一系列简单的攻击。当然,这对抵抗分布式拒绝服务攻击(DDoS)毫无帮助。
还有一些特定的Apache HTTP服务器配置设置可以帮助缓解问题
同样该点在官网http://httpd.apache.org/docs/2.4/misc/security_tips.html#page-header 提及,并给出一些设置方案
配置文件为apache.conf
# # KeepAlive: Whether or not to allow persistent connections (more than # one request per connection). Set to "Off" to deactivate. # KeepAlive On # # MaxKeepAliveRequests: The maximum number of requests to allow # during a persistent connection. Set to 0 to allow an unlimited amount. # We recommend you leave this number high, for maximum performance. # MaxKeepAliveRequests 100 # # KeepAliveTimeout: Number of seconds to wait for the next request from the # same client on the same connection. # KeepAliveTimeout 5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
* `Timeout 300` #客户端与服务器端建立连接前的时间间隔
* 可通过http://modules.apache.org/提供许多第三方模块,这些模块可以限制某些客户端行为,从而缓解 DoS 问题。
###### 隐藏 Apache 的版本号
Apache主机在默认状态下,如果遭遇错误页面,除了提示出错之外,还会将你的机器软件环境显示出来,如你的Apache版本,PHP版本。
详细介绍:
[ubuntu隐藏 Apache 的版本号](http://blog.sina.com.cn/s/blog_4a2ee3fb0102vb04.html)
配置文件`/etc/apache2/conf-available/security`
修改后内容
```bash
#
# ServerTokens
# This directive configures what you return as the Server HTTP response
# Header. The default is 'Full' which sends information about the OS-Type
# and compiled in modules.
# Set to one of: Full | OS | Minimal | Minor | Major | Prod
# where Full conveys the most information, and Prod the least.
#ServerTokens Minimal
ServerTokens Prod
#ServerTokens Full
#
# Optionally add a line containing the server version and virtual host
# name to server-generated pages (internal error documents, FTP directory
# listings, mod_status and mod_info output etc., but not CGI generated
# documents or custom error documents).
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of: On | Off | EMail
#ServerSignature Off
ServerSignature Off
详细介绍可以看上面的注释
关闭 TRACE功能
关闭 TRACE 功能,防止 TRACE 方法被访问者恶意利用。
与上面一样,配置文件为/etc/apache2/conf-available/security
1 | # |
CGI
建议看官方建议。
动态内容安全性
在 Apache中,mod_security的模块可以被视为 HTTP 防火墙,并且只要配置得足够好,可以
增强动态内容安全性。
后记
收获很多
感觉实际配置中,使用docker的可能性更大,也相对方便、安全。