正确设置 php-fpm子进程用户 提高网站安全性 防止被挂木马

核心总结:php-fpm 子进程所使用的用户,不能是网站文件所有者。 凡是违背这个原则,则不符合最小权限原则。

根据生产环境不断反馈,发现不断有 php网站被挂木马,绝大部分原因是因为权限设置不合理造成。因为服务器软件,或是 php 程序中存在漏洞都是难免的,在这种情况下,如果能正确设置 Linux 网站目录权限, php 进程权限,那么网站的安全性实际上是可以得到保障的。

那么,造成网站被挂木马的原因是什么?

1.  ftp 连接信息被破解,对这个原因,可行的办法就是使用非常复杂的FTP 用户名(不要使用常用的用户名),如果是固定作业,可考虑使用 iptables 防火墙限制来源 IP 。但是一些情景下,可能需要使用 VPN 以便远程维护。 即网站维护者需要使用 FTP 修改网站文件时,必须先登录到 IDC 机房的 VPN 服务器上,再进行后续的操作。

2.  网站服务器软件/ 配置 /php 程序存在漏洞,被利用
在讨论这个问题前,先说明文件及进程权限的几个概念:
A. FTP用户对网站目录具有最大修改权限,那么网站的文件所有者一定属于 FTP,  这是毋庸置疑的 , 否则如何修改文件呢?
B. php-fpm进程, nginx 进程对网站文件至少需要有读取权限,例如,以下命令即可查看这两个进程所使用的账号:
服务器安全
服务器安全
通过上图,我们可以发现,nginx 和 php-fpm 子进程账号是 nobody 。

我们再查看网站文件目录的权限:
服务器安全
发现网站文件所有者是www 账号,那说明:
| nginx和 php 对网站只有读取权限,无写入权限
l 如果php 程序需要对网站某些文件有写入权限,需要手工将文件或目录权限修改为 777
l 因为php-fpm 子进程是以 nobody 运行,那么 php-fpm 生成的新文件所有者也是 nobody, 这时 ftp 用户将无法修改这些文件,解铃还需系铃人,当 php 生成文件后,需要调用 chmod(“/somedir/somefile”, 0777) 将文件权限修改为 777 ,以便 FTP 用户也可以修改这个文件。
l 经常有开发人员找我请求重设php 生成的文件的权限。

l 如果php-fpm 子进程以网站文件所有者用户运行,那意味着 php-fpm 进程对整个网站目录具有可写权限,噩梦也就由此开始。

但是我们发现,有不少系统管理员为了省事,违背了Linux 最小化权限的原则,设置 php-fpm 进程以网站文件所有者账号运行,当然这样可能会方便 php 开发人员( php-fpm 进程对整个网站目录具有可写权限),但是这样一来, Linux 体系的文件系统权限原则将被打破,所有的安全措施将形同虚设。可以想象的是,万一 php 程序中有漏洞,攻击者上传木马,便可以修改网站的所有文件,网站首页被黑,也就不足为怪了。

退一步,如果我们设置了较严格的权限,就算php 程序中存在漏洞,那么攻击者也只能篡改权限为 777 的目录,其它的文件是无法被改写的,网站不就就得更安全了吗?

核心总结:php-fpm 子进程所使用的用户,不能是网站文件所有者。 凡是违背这个原则,则不符合最小权限原则。

经过我参阅网上关于nginx, php-fpm 配置的文章教程和市面上的一些书籍,发现有不少人受这些文章的误导,直接让 php-fpm 子进程以网站所有者账号运行,例如张宴的《实战 nginx 取代 apache 的高性能 Web 服务器》一书的 52 页中,存在以下设置:
www
www

而在第50 页,设置网站文件所有者也为 www 用户:
chown -R www:www /data0/htdocs/blog
显然,此书的这部分内部,对初学者有误导,针对这个问题,我已经向本书作者发邮件,希望其能在第二版中进行强调声明,以免由于过度宽松的权限配置,造成一些安全隐患。

官方提供的配置文件中,php-fpm 子进程使用 nobody 用户,这完全是合理的,无须修改。

那么nginx 的子进程用户,如何设置合理? 我的建议是也使用 nobody (对错误日志写入等无影响),设置方法如下:
nginx.conf文件第一行设置为 user nobody; , 再执行 nginx -s reload 即可。

php-fpm子进程用户设置方法:
编辑文件php-fpm.conf (一般位于 /usr/local/php/etc/php-fpm.conf, 视安装参数为准),找到 user 、 group 两个参数的定义,将其设置为nobody( 默认已经是 nobody) ,再重启 php-fpm 进程即可。

网站可写目录的特殊注意
这里的可写,是相对php-fpm 子进程而言。一个网站最容易出安全问题的即是可写目录,如果可写目录权限能控制严格,安全系数也将大大提高。
我们认为,一个网站可写目录主要分为以下几种:
1.  php 数据缓存目录,如 discuz 的 forumdata 目录,就存放了大量数据缓存文件。此类目录一般会禁止用户直接访问,但是 discuz 在这个目录下又存放了不少 js, css 文件,我们并不能简单地拒绝用户访问这个目录。显然,这个目录下的所有文件,不能直接交给 php 解析,我们后面会给出解决方案。
2.  附件上传目录。显然此类目录需要开启访问,但不能交由php 引擎解析(即这个目录下的所有文件均视为普通静态文件)。
3.  静态文件生成目录,这类目录下的文件全部应视为静态文件。
4.  日志目录, 一般都会拒绝用户直接访问之。

也就是说对网站开发人员而言,需要对可写目录实现动静分离,不同性能的文件,应该区别对待之,这样也就方便系统管理员,设置合理的nginx 规则,以提高安全性。

简单地去掉php 文件的执行权限,并不能阻止 php-fpm 进程解析之。

接下来,根据以上总结,系统管理员如何配置nginx 的目录规则,才更安全呢?
1.  数据缓存目录 /cache/
这个目录的特点是需要777 权限,无须提供给用户访问,那么可以按以下参考配置 nginx
location ~ “^/cache” {
return 403;
}

location ~ “.php$” {
fastcgi_pass 127.0.0.0:9000;
………………..
}

这时,任何用户将无法访问/cache/ 目录内容,即使
2. 附件上传目录 attachments
此目录的特点是需要开放访问权限,但所有文件不能由php 引擎解析(包括后缀名改为 gif 的木马文件)
location ~ “^/attachments” {

}

location ~ “.php$” {
fastcgi_pass 127.0.0.0:9000;
………………..
}

注意,上面对attachments 目录的 location 定义中是没有任何语句的。 nginx 对正则表达式的 location 匹配优先级最高,任何一个用正则表达式定义的 location, 只要匹配一次,将不会再匹配其它正则表达式定义的 location 。

现在,请在attachments 目录下建立一个 php 脚本文件,再通过浏览器访问安,我们发现浏览器提示下载,这说明 nginx 把 attachments 目录下的文件当成静态文件处理,并没有交给 php fastcgi 处理。这样即使可写目录被植入木马,但因为其无法被执行,网站也就更安全了。

显然,重要的php 配置文件,请勿放在此类目录下。

3.  静态文件生成目录 public
这些目录一般都是php 生成的静态页的保存目录,显然与附件目录有类似之处,按附件目录的权限设置即可。
可以预见的是,如果我们设置了较严格的权限,即使网站php 程序存在漏洞,木马脚本也只能被写入到权限为 777 的目录中去,如果配合上述严格的目录权限控制,木马也无法被触发运行,整个系统的安全性显然会有显著的提高。

但是网站可写目录的作用及权限,只有开发人员最为清楚。这方面需要php 开发人员和系统管理员积极沟通。我们使用的方式是:项目上线前,开发人员根据以文档形式提供网站可写目录的作用及权限,由系统管理员针对不同目录进行权限设置。任何一方修改了网站目录权限,但未体现到文档中,我们认为是违反工作流程的。
原文:http://zhangxugg-163-com.iteye.com/blog/1171572

使用apache2-mpm-itk以不同用户运行apache虚拟主机

我们运行在apache的虚拟主机,有时候为了安全,需要为每个网站以不同的用户运行,这样当虚拟主机中的一个网站被入侵时,而不会影响到其它的虚拟主机。我们这里使用apache2-mpm-itk补丁来实现这种功能。

1、下载apache2和itk

到apache2-mpm-itk网站下载最新版的补丁http://mpm-itk.sesse.net/

  1. wget  http://apache.ziply.com//httpd/httpd-2.2.21.tar.gz
  2. tar xzvf httpd-2.2.21.tar.gz
  3. wget http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01.patch

2、为apache2打上mpm-itk补丁

  1. cd httpd-2.2.21
  2. patch -p1 < ../apache2.2-mpm-itk-2.2.17-01.patch
  3. autoconf

3、编译apache2

编译apache2时,带上编译选项–with-mpm=itk,如:

  1. ./configure –with-mpm=itk
  2. make
  3. make install

4、配置apache2

  1. <VirtualHost *:80>
  2. ServerName www.example.com
  3.  
  4. <IfModule mpm_itk_module>
  5. AssignUserId siteuser sitegroup
  6. </IfModule>
  7. </VirtualHost>

sitesuer是指apache以siteuser用户运行
sitegroup是指apache以sitegroup用户组运行

rsync错误:@ERROR: auth failed on module XXX 的原因之一

在Linux下使用rsync,将远程目录下的文件同步到本地目录时,可能会出现以下错误:
@ERROR: auth failed on module XXX
其中,XXX 表示你的远程rsync服务模块名称。
出现这种情况,先检查你的用户名和密码是否正确,如果都正确,有一个可能是原因是:远程rsync服务器的帐户密码文件的权限必须为600,例如,你在rsyncd.conf中设置了secrets file = /etc/rsyncd/rsync_pwd
那么你就必须确保rsync_pwd的访问权限为600:
chmod 600 /etc/rsyncd/rsync_pwd
然后你的问题可能就解决了。
来源:http://blog.csdn.net/learnhard/article/details/5542765

使用MySQL自带工具mysqlhotcopy快速备份mysql数据库

mysqlhotcopy是一个Perl脚本,最初由Tim Bunce编写并提供。它使用LOCK TABLES、FLUSH TABLES和cp或scp来快速备份数据库。它是备份数据库或单个表的最快的途径,但它只能运行在数据库目录所在的机器上。mysqlhotcopy只用于备份MyISAM。它运行在Unix和NetWare中。
  与mysqldump比较:
  1、前者是一个快速文件意义上的COPY,后者是一个数据库端的SQL语句集合。
  2、前者只能运行在数据库目录所在的机器上,后者可以用在远程客户端,不过备份的文件还是保存在服务器上。
  3、相同的地方都是在线执行 LOCK TABLES 以及 UNLOCK TABLES
  4、前者恢复只需要COPY备份文件到源目录覆盖即可,后者需要导入SQL文件到原库中。(source 或 mysql < bakfile.sql)
  5、前者只适用于 MyISAM 引擎,而后则则可同时使用于MyISAM引擎和InodDB引擎.
  6、前者在使用前必须安装perl-DBD-mysql包,而后者则不需要.
使用mysqlhotcopy之前需要安装perl-DBI和DBD-mysql:
1、执行yum install perl-DBI安装perl-DBI。
2、执行yum install perl-DBD-MySQL或者http://devops.webres.wang/2011/11/linux-install-perl-dbd-mysql/
一个常用的备份例子:

  1. /usr/local/mysql/bin/mysqlhotcopy -u root -proot –addtodest 数据库名1 数据库名2  备份目录

–addtodest的意思是当备份存在时,不中断备份,只添加新的文件进去。
更多的选项可以执行/usr/local/mysql/bin/mysqlhotcopy –help查看。
如何还原?
1、停止mysql服务器。
2、复制备份的数据库目录到mysql数据目录下。
3、更改目录所有者为mysql服务器运行的用户(如mysql)。
4、启动mysql服务器

Linux安装perl DBD-mysql驱动

到http://www.cpan.org/modules/by-module/DBD/找到最新的版本,现在最新的为DBD-mysql-4.020.tar.gz
开始下载安装:

  1. wget http://www.cpan.org/modules/by-module/DBD/DBD-mysql-4.020.tar.gz
  2. tar xzvf DBD-mysql-4.020.tar.gz
  3. cd DBD-mysql-4.020
  4. perl Makefile.PL –mysql_config=/usr/local/mysql/bin/mysql_config
  5. make
  6. make install

请确保mysql_config的路径正确。

Cherokee设置WordPress伪静态规则

Cherokke设置wordpress的伪静态需要在后台操作。我们假设你已经添加好wordpress的虚拟主机devops.webres.wang,下面我们介绍如何配置wordpress伪静态。
1、选择创建好的虚拟主机,切换到“行为”,点击“规则管理”,把所有已存在的规则删除,除了默认的。
2、选择默认规则,切换到“处理程序”,处理程序下拉框选择“转发”,点击“Add New RegEx”增加转发规则,在转发规则对话框中,显示选择“内部”,正则表达式输入^(.+)$,替换输入index.php。
3、增加目录规则,网页目录输入“/wp-admin”,切换到处理程序,处理程序选择“列表和发现”。
4、克隆两次第三步的规则,分别把网页目录更改为/wp-content和/wp-includes。
5、最后添加php扩展支持。如不明白如何操作,请参考http://devops.webres.wang/2011/11/cherokee-vhost-configure/
配置的最终结果如图:
Cherokee
6、最后点save-》重载

Cherokee配置虚拟主机支持PHP

上次我们学习了cherokee php mysql的安装,但安装完全可以正常打开静态文件,但无法访问php文件,因为这需要配置cherokee支持PHP。下面学习cherokee虚拟主机配置。

1、登录cherokee后台

执行cherokee-admin -b命令获取后台密码,执行命令之后请不要中断或关闭当前ssh,否则无法登录后台。如图:
Cherokee

2、更换后台语言为简体中文

在后台的首页右侧,Language的下拉菜单选择chinese simplfied,如图:
Cherokee

3、添加数据源

1、切换Sources,点击左侧的“+”添加数据库:
Cherokee
2、在添加数据源对话框输入昵称php-fpm(可以输入任何),连接:/tmp/php-cgi.sock。
Cherokee
3、配置数据源。在类型选择“本地解析器”,解释器输入

  1. /usr/local/php/sbin/php-fpm –fpm-config /usr/local/php/etc/php-fpm.conf

之后点击右上角的save保存数据,接着点击“重载”。
Cherokee

4、添加配置虚拟主机

1、切换“vServers”,点击左侧“+”新建虚拟主机。在手动配置中的昵称输入域名(如:devops.webres.wang),输入网站根目录(如/home/www/devops.webres.wang,必须是已存在的目录),点击“增加”新建虚拟主机。
Cherokee
2、在目录列表中输入“index.html,index.php”定义默认首页
Cherokee
3、切换到“行为”,点击规则管理,删除已存在的两个规则。并点击“+”增加新规则。
Cherokee
4、配置规则。在增加规则对话框,选择规则类型为“扩展”,在扩展中输入“php”,并勾选“check”,点击“增加”添加规则。
Cherokee
5、切换到处理程序,在处理程序下拉框中选择“快速CGI”,在下面的负载均衡中选择“Round Robin”,设置数据源中应用程序选择刚才设置的数据源昵称”php-fpm”,点击save保存。
Cherokee
6、验证是否配置成功。在/home/www/devops.webres.wang目录下新建文件p.php,输入

  1. <?php
  2. phpinfo();
  3. ?>

如果能正常显示php配置信息,则表示已经配置成功,如图:
Cherokee

CentOS 创建本地YUM软件库

首先从CentOS官方源(msync.centos.org),同步一份本地镜像(约7G左右),然后禁用原有的源,并创建一个本地的.repo仓库文件。

一、Rsync 同步脚本

  1. wget http://devops.webres.wang/wp-content/uploads/2011/11/rsync_repo.sh
  2. vim rsync_repo.sh //修改"local"值(本地镜像存放路径)
  3. chmod 755 rsync_repo.sh
  4. ./rsync_repo.sh

二、禁用原有的源

注:你也可以直接编辑.repos文件,加上参数”enabled=0″禁用源。

  1. for i in `ls /etc/yum.repos.d/`;do mv /etc/yum.repos.d/$i /etc/yum.repos.d/$i.bak;done

禁用fastestmirror插件,再也不需要这东西了。

  1. sed -i ‘s/plugins=1/plugins=0/g’  /etc/yum.conf

三、创建本地.repo文件

注意记得修改默认的”/mnt/hgfs/e/CentOS”本地镜像路径

  1. wget http://devops.webres.wang/wp-content/uploads/2011/11/CentOS-Local.repo -P /etc/yum.repos.d
  2. chmod 644 /etc/yum.repos.d/rsync_repo.sh
  3. yum -y update

来源:https://wangyan.org/blog/centos-local-yum-repo.html

CentOS安装Cherokee php mysql

Cherokee 号称是目前最快的 Web 服务器软件,Cherokee 的功能包括支持 FastCGI、SCGI、PHP、CGI、TLS 及 SSL 加密连接,虚拟主机,授权认证,实时编码,载入均衡,与 Apache 兼容的 log 文件等等。Cherokee 内含一个名为 cherokee-admin 的工具,执行后,允许管理员直接通过浏览器进入 http://localhost:9090/ 对其进行管理和配置。比如,开启或关闭服务器,进行一般选项的设定,配置虚拟服务器、信息源、图标、Mime 类型等项目。下面以centos 5.5 32位系统为例介绍如何安装cherokee php mysql。

安装mysql

安装必要软件包

  1. yum -y install make gcc gcc-c++ ncurses-devel

下面的rpm只适用于CentOS-5 32位,其它的到http://mirrors.sohu.com/fedora-epel/这里查找。

  1. rpm -Uvh http://mirrors.sohu.com/fedora-epel/5/i386/epel-release-5-4.noarch.rpm

下载软件

  1. cd /tmp
  2. wget -c http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.17.tar.gz/from/http://mysql.he.net/
  3. wget -c http://www.cmake.org/files/v2.8/cmake-2.8.6.tar.gz
  4. wget -c http://ftp.gnu.org/gnu/bison/bison-2.5.tar.gz

安装cmake和bison

  1. cd /tmp
  2. tar zxvf cmake-2.8.6.tar.gz
  3. cd cmake-2.8.6
  4. ./bootstrap
  5. make && make install
  6. cd /tmp
  7. tar zxvf bison-2.5.tar.gz
  8. cd bison-2.5
  9. ./configure
  10. make && make install

开始安装mysql

  1. /usr/sbin/groupadd mysql
  2. /usr/sbin/useradd -g mysql mysql
  3. cd /tmp
  4. tar xvf mysql-5.5.17.tar.gz
  5. cd mysql-5.5.17/
  6. cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql
  7. -DMYSQL_UNIX_ADDR=/tmp/mysql.sock
  8. -DDEFAULT_CHARSET=utf8
  9. -DDEFAULT_COLLATION=utf8_general_ci
  10. -DWITH_EXTRA_CHARSETS=all
  11. -DWITH_MYISAM_STORAGE_ENGINE=1
  12. -DWITH_INNOBASE_STORAGE_ENGINE=1
  13. -DWITH_MEMORY_STORAGE_ENGINE=1
  14. -DWITH_READLINE=1
  15. -DENABLED_LOCAL_INFILE=1
  16. -DMYSQL_DATADIR=/var/mysql/data
  17. -DMYSQL_USER=mysql
  18.  
  19. make && make install

一些相关设置

  1. chmod +w /usr/local/mysql
  2. chown -R mysql:mysql /usr/local/mysql
  3. ln -s /usr/local/mysql/lib/libmysqlclient.so.16 /usr/lib/libmysqlclient.so.16
  4. mkdir -p /var/mysql/
  5. mkdir -p /var/mysql/data/
  6. mkdir -p /var/mysql/log/
  7. chown -R mysql:mysql /var/mysql/
  8. cd support-files/
  9. cp my-medium.cnf /var/mysql/my.cnf
  10. cp mysql.server /etc/rc.d/init.d/mysqld
  11.  
  12. /usr/local/mysql/scripts/mysql_install_db
  13. –defaults-file=/var/mysql/my.cnf
  14. –basedir=/usr/local/mysql
  15. –datadir=/var/mysql/data
  16. –user=mysql
  17.  
  18. chmod +x /etc/init.d/mysqld

vi /etc/init.d/mysqld(编辑此文件,查找并修改以下变量内容:)

  1. basedir=/usr/local/mysql
  2. datadir=/var/mysql/data
  1. chkconfig –add mysqld
  2. chkconfig –level 345 mysqld on
  3. service mysqld start
  4. /usr/local/mysql/bin/mysqladmin password [new-password]

安装PHP

安装必要软件包

  1. yum -y install libxml2-devel openssl-devel curl-devel libjpeg-devel libpng-devel autoconf pcre-devel libtool-libs freetype-devel gd libmcrypt-devel zlib-devel zip unzip gettext

开始安装php

  1. cd /tmp
  2. groupadd www
  3. useradd -s /sbin/nologin -g www www
  4. wget -c http://cn2.php.net/get/php-5.3.8.tar.gz/from/this/mirror
  5. tar xzvf php-5.3.8.tar.gz
  6. cd php-5.3.8
  7. ./configure –prefix=/usr/local/php –enable-fpm –with-fpm-user=www –with-fpm-group=www –with-config-file-path=/etc –with-config-file-scan-dir=/etc/php.d  –with-libxml-dir –with-openssl –with-zlib –with-curl –enable-ftp –with-gd –with-jpeg-dir –with-png-dir –with-zlib-dir  –with-freetype-dir –enable-gd-native-ttf –with-gettext –enable-mbstring –with-mcrypt  –with-mysql=/usr/local/mysql –with-mysqli=/usr/local/mysql/bin/mysql_config –without-pear
  8. make && make install
  9. cp php.ini-production /etc/php.ini
  10. cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
  11. cp sapi/fpm/php-fpm.conf /usr/local/php/etc/php-fpm.conf

编辑php-fpm.conf,找到如下字段,删除前面的”;”号

  1. pid = run/php-fpm.pid
  2. pm.start_servers = 20
  3. pm.min_spare_servers = 5
  4. pm.max_spare_servers = 35

找到:

  1. listen = 127.0.0.1:9000

改为:

  1. listen = /tmp/php-cgi.sock
  1. chmod 755 /etc/init.d/php-fpm
  2. chkconfig –add php-fpm
  3. chkconfig –level 345 php-fpm on
  4. /etc/init.d/php-fpm start

安装cherokee

  1. yum -y install rrdtool
  2. groupadd www
  3. useradd -s /sbin/nologin -g www www
  4. wget http://www.cherokee-project.com/cherokee-latest-tarball -O -| tar zxvf –
  5. cd cherokee-1.2.101
  6. ./configure –prefix=/usr/local/cherokee –with-wwwroot=/home/www –with-wwwuser=www –with-wwwgroup=www
  7. make && make install
  8. wget http://devops.webres.wang/wp-content/uploads/2011/11/cherokee -O /etc/init.d/cherokee
  9. chmod +x /etc/init.d/cherokee
  10. chkconfig –add cherokee
  11. chkconfig –level 345 cherokee on
  12. ln -s /usr/local/cherokee/sbin/cherokee-admin /usr/sbin/
  13. service cherokee start

现在你已经可以访问默认的chreokee页面,执行cherokee-admin -b命令得到后台密码,并通过localhost:9090进入后台。关于配置cherokee支持PHP请看http://devops.webres.wang/2011/11/cherokee-vhost-configure/

服务不支持chkconfig

今天chkconfig –add nginx的时候,出现nginx 服务不支持chkconfig。
如果想让服务支持chkconfig,必须定义服务的启动级,启动优先级,关闭优先级,还有描述,如下

  1. # chkconfig: 345 85 15
  2. # description: Nginx is an HTTP server

345是启动级,85和15分别是启动优先级,关闭优先级,下面的就是描述了。