11.28 限定某个目录禁止解析php
需求:假设有一个目录是可以上传图片,但是可能被有心之人上传php上去,因为httpd开放了php模块,所以如果被人上传了木马文件(php类型),httpd就有可能会进行执行,一旦执行,就会让对方获得我们服务器的root权限,或者是被恶意删除或修改一些参数,导致服务器瘫痪或者是被攻击
案例:
一台服务器,网站被入侵,但不知道是什么原因,不知道怎么入侵的,也不知道入侵到什么程度,只知道他们公司的数据库泄露了,数据是一些电话号码,黑客并没有去删除数据,因为他知道这个服务器的数据库里,电话号码每天都在增长,他就可以源源不断的获得新的电话号码,获得的电话号码可以卖给第三方;
解决方式:
把一个没有在这个服务器提交过的电话号码,在这个服务器的网站上提交一次,结果,马上就有人打电话过来,证明,黑客获得电话号码,到打电话给新的用户,这套体系,已经完全自动化了(每天都会去抓取一个新的电话号码来队列,然后马上卖给第三方,第三方马上打电话给这个用户),所以就猜测,网站的程序(php)存在漏洞,另一种可能就是sql注入的漏洞(可以把查询的sql通过一些特殊的提交,提交到服务器上,服务器就会把这个sql语句转换成正常的查询,最终获得一些数据回来);但是sql注入漏洞,很容易修复,只要在网站提交的入口,增加一些特殊符号的过滤,就能完全的阻断sql注入的漏洞。
首先抓包,监控数据的查询,因为电话号码是通过查询了数据来的,写一个死循环的脚本,每隔一分钟抓一次查询数据,抓完以后生成一个日志文件, 查看日志以后,发现有一条sql查询,和网站源生的查询不一样,通过日志定位到了时间点,然后就去web服务器上查看时间点的访问日志,通过日志查看到了一个非常特殊的请求,名字是以php结尾的文件,而且这个php文件是在图片的目录下进行访问的,然后去查看这个php 文件,发现这个文件内容,是获取服务器的权限,相当于在服务器开了一个后门;这个问题产生的根本原因,就是因为上传图片目录并没有禁止解析php\
- sql注入
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。[1] 比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击..
修改配置文件
<Directory /data/wwwroot/111.com/upload>
php_admin_flag engine off //禁止解析php
<FilesMatch (.*)\.php(.*)>
Order allow,deny //如果不做这个deny,就会直接访问到源代码,这样就不太友好
Deny from all
</FilesMatch>
</Directory>
创建需求的目录及文件
[root@localhost 111.com]# pwd
/data/wwwroot/111.com
[root@localhost 111.com]# mkdir upload
[root@localhost 111.com]# ls
123.php 123.png admin index.php upload
[root@localhost 111.com]# cp 123.png upload/
[root@localhost 111.com]# cp 123.php upload/
[root@localhost 111.com]# ls upload/
123.php 123.png
开始测试
先把之前添加的deny,注释掉
因为之前配置有 php_admin_flag engine off 所以php不进行解析,看到的直接是源代码,使用-I 看是也的通的返回码200
[root@localhost 111.com]# curl -x127.0.0.1:80 'http://111.com/upload/123.php' -I
HTTP/1.1 200 OK
Date: Thu, 03 Aug 2017 14:29:36 GMT
Server: Apache/2.4.27 (Unix) PHP/5.6.30
Last-Modified: Thu, 03 Aug 2017 14:24:05 GMT
ETag: "1c-555da22064fe0"
Accept-Ranges: bytes
Content-Length: 28
Content-Type: application/x-httpd-php
[root@localhost 111.com]# curl -x127.0.0.1:80 'http://111.com/upload/123.php'
<?php
echo "holle wold";
?>
在浏览器上打开 http://111.com/upload/123.php 是直接进行下载,因为123.php无法解析,这样做的话,不是很友好,所以才进一步的配置使 php直接无法访问
打开配置以后,重新curl 如下提示
[root@localhost 111.com]# curl -x127.0.0.1:80 'http://111.com/upload/123.php'
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /upload/123.php
on this server.<br />
</p>
</body></html>
[root@localhost 111.com]# curl -x127.0.0.1:80 'http://111.com/upload/123.php' -I
HTTP/1.1 403 Forbidden
Date: Thu, 03 Aug 2017 14:36:40 GMT
Server: Apache/2.4.27 (Unix) PHP/5.6.30
Content-Type: text/html; charset=iso-8859-1
直接提示无法访问403
==禁止php解析,是为让服务器更加安全,尤其是针对可以写的目录;可以写的目录,一般是不需要解析php,这个需要牢记,一般静态文件存放的目录是不允许解析php 的==
11.29 限制user_agent
有时候,网站会受到一种叫 cc 攻击,CC攻击就是黑客,通过软件,肉鸡同时去访问一个站点,超过服务器的并发,就会导致站点宕机;通过肉鸡,软件去访问站点,就是普通的访问,没有什么特殊的,只是让站点超过并发导致严重超负荷而宕机,所以没办法去进行控制;所谓CC攻击都会有一个规律的特征,就是user_agent是一致的,比如同一个IP、同一个标识、同一个地址;遇到这种规律的user_agent频繁访问的情况我们就可以判定他就是CC攻击,我们就可以通过限制他的user_agent 减轻服务器压力,只需要让他从正常访问的200,限制为403,就能减轻服务器的压力,因为403仅仅是一个请求,只会使用到很少的带宽,毕竟他没有牵扯到php 和mysql
- cc攻击
-
攻击者借助代理服务器生成指向受害主机的合法请求,实现DDOS和伪装就叫:CC(ChallengeCollapsar)。
-
CC主要是用来攻击页面的。大家都有这样的经历,就是在访问论坛时,如果这个论坛比较大,访问的人比较多,打开页面的速度会比较慢,访问的人越多,论坛的页面越多,数据库压力就越大,被访问的频率也越高,占用的系统资源也就相当可观。
-
一个静态页面不需要服务器多少资源,甚至可以说直接从内存中读出来发给你就可以了,但是论坛就不一样了,我看一个帖子,系统需要到数据库中判断我是否有读帖子的权限,如果有,就读出帖子里面的内容,显示出来——这里至少访问了2次数据库,如果数据库的数据容量有200MB大小,系统很可能就要在这200MB大小的数据空间搜索一遍,这需要多少的CPU资源和时间?如果我是查找一个关键字,那么时间更加可观,因为前面的搜索可以限定在一个很小的范围内,比如用户权限只查用户表,帖子内容只查帖子表,而且查到就可以马上停止查询,而搜索肯定会对所有的数据进行一次判断,消耗的时间是相当的大。
-
CC就是充分利用了这个特点,模拟多个用户(多少线程就是多少用户)不停的进行访问(访问那些需要大量数据操作,就是需要大量CPU时间的页面).这一点用一个一般的性能测试软件就可以做到大量模拟用户并发。
- 肉鸡 (受黑客远程控制的电脑)
-
肉鸡也称傀儡机,是指可以被黑客远程控制的机器。比如用"灰鸽子"等诱导客户点击或者电脑被黑客攻破或用户电脑有漏洞被种植了木马,黑客可以随意操纵它并利用它做任何事情。
-
肉鸡通常被用作DDOS攻击。可以是各种系统,如windows、linux、unix等,更可以是一家公司、企业、学校甚至是政府军队的服务器。
对httpd.conf配置文件新增几行配置
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} .*curl.* [NC,OR] //条件
RewriteCond %{HTTP_USER_AGENT} .*baidu.com.* [NC] //条件
RewriteRule .* - [F]
</IfModule>
- 在两个条件中用OR做了一个连接符,理解起来就是 匹配第一条规则或者第二条规则;如果不加OR就是并且的意思,必须两个条件同时匹配以后才会执行
- NC表示忽略大小写,因为user_agent,可能会是大写的,比如:Mozilla/5.0,他首字母就是大写的
- RewriteRule .* - [F] 匹配上面条件的所有,直接执行 403
测试
[root@localhost 111.com]# curl -x127.0.0.1:80 'http://111.com/upload/123.php' -I
HTTP/1.1 403 Forbidden
Date: Thu, 03 Aug 2017 15:06:43 GMT
Server: Apache/2.4.27 (Unix) PHP/5.6.30
Content-Type: text/html; charset=iso-8859-1
因为定义了curl 直接执行 Forbidden ,但是我们可能会有怀疑,并不是因为是curl的原因,那么我们就自定义user_agent尝试一下看看
curl -A "aminglinux aminglinux" -x127.0.0.1:80 'http://111.com/123.php'
[root@localhost 111.com]# curl -A "aminglinux aminglinux" -x127.0.0.1:80 'http://111.com/123.php'
HTTP/1.1 200 OK
Date: Thu, 03 Aug 2017 15:19:41 GMT
Server: Apache/2.4.27 (Unix) PHP/5.6.30
X-Powered-By: PHP/5.6.30
Content-Type: text/html; charset=UTF-8
查看一下访问日志
[root@localhost 111.com]# tail /usr/local/apache2.4/logs/111.com-access_20170803.log
127.0.0.1 - - [03/Aug/2017:22:29:46 +0800] "GET http://111.com/upload/123.php HTTP/1.1" 200 28 "-" "curl/7.29.0"
127.0.0.1 - - [03/Aug/2017:22:36:33 +0800] "GET http://111.com/upload/123.php HTTP/1.1" 403 223 "-" "curl/7.29.0"
127.0.0.1 - - [03/Aug/2017:22:36:40 +0800] "HEAD http://111.com/upload/123.php HTTP/1.1" 403 - "-" "curl/7.29.0"
127.0.0.1 - - [03/Aug/2017:23:06:43 +0800] "HEAD http://111.com/upload/123.php HTTP/1.1" 403 - "-" "curl/7.29.0"
127.0.0.1 - - [03/Aug/2017:23:18:46 +0800] "HEAD http://111.com/upload/123.php HTTP/1.1" 403 - "-" "\xe2\x80\x9caminglinux"
127.0.0.1 - - [03/Aug/2017:23:19:13 +0800] "HEAD http://111.com/123.php HTTP/1.1" 200 - "-" "\xe2\x80\x9caminglinux"
127.0.0.1 - - [03/Aug/2017:23:19:41 +0800] "HEAD http://111.com/123.php HTTP/1.1" 200 - "-" "\xe2\x80\x9caminglinux"
127.0.0.1 - - [03/Aug/2017:23:21:11 +0800] "GET http://111.com/123.php HTTP/1.1" 200 10 "-" "\xe2\x80\x9caminglinux"
127.0.0.1 - - [03/Aug/2017:23:22:30 +0800] "GET http://111.com/123.php HTTP/1.1" 200 10 "-" "aminglinux aminglinux"
127.0.0.1 - - [03/Aug/2017:23:23:44 +0800] "HEAD http://111.com/123.php HTTP/1.1" 200 - "-" "aminglinux aminglinux"
标识也变为 aminglinux aminglinux
11.30/11.31 php相关配置
查看php配置文件的位置,通过浏览器,访问phpinfo找到配置文件的路径,也可以用/usr/local/php/bin/php -i |grep -i "loaded configuration file"找到他的路径;但是有些情况“php -i ”是不准的,因为Apache他是调用了php 的一模块,而且“php -i” 只是php 的一个程序,他和libphp5.so可能有关系也可能没有关系;
案例:
有时改了php.ini,改动了也重启了服务,结果配置还是不生效;因为使用“php -i”\ 找到的配置文件和在web上的phpinfo找到的php.ini不是同一个,如果想要准确的找到php.ini配置文件,就在对应的站点目录下,创建一个phpinfo的php文件,在web上打开,在phpinfo上找到的,才是最准确的
设置安全函数
disable_functions //安全函数
eval 之前提到的“一句话木马”涉及到函数,如果把这个函数禁用,那么那个木马将不会生效
eval,assert,popen,passthru,escapeshellarg,escapeshellcmd,passthru,exec,system,chroot,scandir,chgrp,chown,escapeshellcmd,escapeshellarg,shell_exec,proc_get_status,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,leak,popepassthru,stream_socket_server,popen,proc_open,proc_close
以上是比较危险的函数
php.ini配置里面的 disable_functions这个是为空的,只需要把相关的函数输入进去即可
303 行
disable_functions = eval,assert,popen,passthru,escapeshellarg,escapeshellcmd,passthru,exec,system,chroot,scandir,chgrp,chown,escapeshellcmd,escapeshellarg,shell_exec,proc_get_status,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,leak,popepassthru,stream_socket_server,popen,proc_open,proc_close ,phpinfo
当然也可以把phpinfo 禁掉,很多企业在生产环境都会禁掉,因为phpinfo涉及到服务器很多php 的配置相关,如果一不小心上传到了线上,那么久很容易被黑客查到,进行对应的攻击
设置时区
需要删除 ; 分号,打开配置
date.timezone // 定义时区,如果不定义时区的话,有时候会有一些告警信息,一般定义到上海(Shanghai)或者重庆(Chongqing)
date.timezone = Asia/Shanghai
打开、配置、调试错误日志
错误信息,是否直接显示在屏幕上(On显示,Off不显示)
如果打开的话,出现错误的时候,会直接显示错信息,也会间接的暴露了网站的路径
如果设置的Off的话,错误信息没有了,那么页面将直接显示空白页,这样我们将不知道页面真实情况,所以,一定Off这个配置,就必须做下一个配置
display_errors = Off
错误日志,是否打开(On Off)
log_errors = On
配置错误日志的存放路径
需要删除 ; 分号,打开配置
error_log =/tmp/php_errors.log
定于error_log的级别,因为如果这个级别比较高的话,那么这个错误日志,只会记录一些比较严重的错误
; Common Values:
; E_ALL (Show all errors, warnings and notices including coding standards.)
; E_ALL & ~E_NOTICE (Show all errors, except for notices) //生产环境用这个就行
; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.)
; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
error_reporting = E_ALL & ~E_NOTICE
错误日志是由daemon的用户生成的
[root@localhost tmp]# ls -lhtr php_errors.log
-rw-r--r--. 1 daemon daemon 290 8月 4 00:34 php_errors.log
实际上,错误日志是以httpd这个进程的身份去生成的
[root@localhost tmp]# ps aux |grep httpd
root 2293 0.0 0.6 257256 12632 ? Ss 8月03 0:00 /usr/local/apache2.4/bin/httpd -k restart
daemon 3843 0.0 0.5 544084 9584 ? Sl 00:34 0:00 /usr/local/apache2.4/bin/httpd -k restart
daemon 3844 0.0 0.5 544084 9584 ? Sl 00:34 0:00 /usr/local/apache2.4/bin/httpd -k restart
daemon 3845 0.0 0.7 675156 13276 ? Sl 00:34 0:00 /usr/local/apache2.4/bin/httpd -k restart
root 3933 0.0 0.0 112664 976 pts/1 R+ 00:37 0:00 grep --color=auto httpd
有时候,定义了一个错误日志,但是这个错误日志始终没有生成,那么就需要检查一下定义错误日志所在的目录,到底httpd有没有写权限, 最保险的办法,就是在所在目录创建一个错误日志的文件,然后赋予它777的权限,这样就不需要担心这个文件httpd是否有写权限了
测试查看错误日志
[root@localhost tmp]# cat php_errors.log
[04-Aug-2017 00:34:27 Asia/Shanghai] PHP Warning: phpinfo() has been disabled for security reasons in /data/wwwroot/111.com/index.php on line 2
[04-Aug-2017 00:34:29 Asia/Shanghai] PHP Warning: phpinfo() has been disabled for security reasons in /data/wwwroot/111.com/index.php on line 2
安全相关的参数
一台服务器上,运行了多个站点,有一台服务器假如代码有问题,结果这个站点被黑客攻击了,被黑客拿到了权限,黑客拿了权限肯定会继续往里渗透,继续往里渗透,就会有可能渗透到其他的站点,同时导致其他的站点被黑
open_basedir 限制不能串岗
open_basedir = /data/wwwroot/1111.com:/tmp
这里配置 /tmp的目的是因为,打开任何文件的时候都会产生一个缓存文件,如果不允许/tmp的话会导致任何站点都没有办法访问
配置好以后测试访问情况
[root@localhost tmp]# curl -x127.0.0.1:80 111.com/123.php -I
HTTP/1.0 500 Internal Server Error
Date: Thu, 03 Aug 2017 17:07:06 GMT
Server: Apache/2.4.27 (Unix) PHP/5.6.30
X-Powered-By: PHP/5.6.30
Connection: close
Content-Type: text/html; charset=UTF-8
[root@localhost tmp]# cat /tmp/php_errors.log
[04-Aug-2017 00:34:27 Asia/Shanghai] PHP Warning: phpinfo() has been disabled for security reasons in /data/wwwroot/111.com/index.php on line 2
[04-Aug-2017 00:34:29 Asia/Shanghai] PHP Warning: phpinfo() has been disabled for security reasons in /data/wwwroot/111.com/index.php on line 2
[04-Aug-2017 01:04:16 Asia/Shanghai] PHP Warning: phpinfo() has been disabled for security reasons in /data/wwwroot/111.com/index.php on line 2
[04-Aug-2017 01:07:06 Asia/Shanghai] PHP Warning: Unknown: open_basedir restriction in effect. File(/data/wwwroot/111.com/123.php) is not within the allowed path(s): (/data/wwwroot/1111.com:/tmp) in Unknown on line 0
[04-Aug-2017 01:07:06 Asia/Shanghai] PHP Warning: Unknown: failed to open stream: Operation not permitted in Unknown on line 0
[04-Aug-2017 01:07:06 Asia/Shanghai] PHP Fatal error: Unknown: Failed opening required '/data/wwwroot/111.com/123.php' (include_path='.:/usr/local/php/lib/php') in Unknown on line 0
提示说,来源是/data/wwwroot/111.com/123.php 目录,所以不能访问
这个安全模块,在php.ini里配置,只能对整个php进行配置,所以如果有多个站点的话,在这里配置并没有什么作用
配置这个模块只能去虚拟主机配置文件httpd-vhosts文件里针对虚拟主机进行配置