0x00 实验目的

根据文章”PHP绕过open_basedir列目录的研究”通过测试不同的配置验证本文的绕过basedir的方法是否有效,从而安全配置php open_basedir的目的.
文中后面几个方法都是windwos下采用枚举的方式列出目录,linux下需要做暴力猜解的方式才可以,所以不做测试.

测试”DirectoryIterator + Glob”方式是否可以绕过open_basedir
测试webshell工具”菜刀”是否可以绕过open_basedir

0x01 实验环境

nginx + PHP 5.6.7 fastcgi模式, centos7 linux
目前配置open_basedir有三处地方php-fpm.conf,nginx fastcgi_param,php.ini
下面逐一测试

0x02 测试详细

只在php-fpm.conf中配置

php_admin_value[open_basedir]=/home/wwwroot/:/proc/:/tmp/

结果

open_basedir的目录以外不能读,不能写,不过DirectoryIterator + Glob 可以成功列出全盘文件

当前open_basedir
open_basedir : /home/wwwroot/:/proc/:/tmp/

-- DirectoryIterator + Glob --.
..
.autorelabel
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
vagrant
var

菜刀不可跨出basedir

 

只在nginx的fastcgi_param配置

# set php open_basedir
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";

这里的”$document_root”是nginx中的变量,为nginx的每个server里的root目录
比如server www.iamle.com配置的root目录为/home/wwwroot/www.iamle.com

认真读php手册有下面这段话
PHP配置值通过 php_value 或者 php_flag 设置,并且会覆盖以前的值。
请注意 disable_functions 或者 disable_classes 在 php.ini 之中定义的值不会被覆盖掉,但是会将新的设置附加在原有值的后面。
使用 php_admin_value 或者 php_admin_flag 定义的值,不能被 PHP
代码中的 ini_set() 覆盖。自 5.3.3 起,也可以通过 web 服务器设置
PHP 的设定。也就是nignx中fastcgi_param配置php的配置
php_flag用来专门设置布尔值,如on, off, 1, 0, true, false, yes, no,
而php_value用来设置所有类型的值

结果和上面一样

open_basedir的目录以外不能读,不能写,不过DirectoryIterator + Glob 可以成功列出全盘文件

菜刀不可跨出basedir

 

只在php.ini配置

[HOST=www.iamle.com]
open_basedir=/home/wwwroot/www.iamle.com/:/proc/:/tmp/
[PATH=/home/wwwroot/www.iamle.com/]
open_basedir=/home/wwwroot/www.iamle.com/:/proc/:/tmp/

意思是当HOST=www.iamle.com设置open_basedir,当PATH=/home/wwwroot/www.iamle.com/

设置open_basedir,我测试的时候2个任意设置一个都是有效的

结果和上面一样

open_basedir的目录以外不能读,不能写,不过DirectoryIterator + Glob 可以成功列出全盘文件

菜刀不可跨出basedir

 

0x03 个人结论

DirectoryIterator + Glob的方式可以列出php服务器上所有文件,看似没什么危害,实际上对于长期的APT绝对有帮助.
open_basedir不是想象的那么安全,说不定别人手上有甚至有能读写open_basedir的0day

0x04 个人推荐的nginx + php(fastcgi fpm-php)(lnmp) open_basedir的配置

先设置fpm-php中pool池中的总open_basedir这叫顶层设计,有个总限制,比如统一限制到/home/wwwroot/这样的web目录下
再对nginx中单个server 通过 fastcgi_param PHP_ADMIN_VALUE 设置
再对php.ini设置 [HOST=XXX] [PATH=XXX]
三管齐下妈妈再也不用担心我的php open_basedir了(希望吧)
虽然很啰嗦,但是这样岂不是更放心
总而言之就是下面的结果,我就是下面这种啰嗦的配置

 

#在php-fpm.conf对应的pool池中行尾配置
php_admin_value[open_basedir]=/home/wwwroot/:/proc/:/tmp/

#在nginx fastcgi fastcgi_param配置
#这里用$document_root是一种取巧的方法,也可以设置绝对路径
# set php open_basedir
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";

#在php.ini行尾配置
[HOST=www.iamle.com]
open_basedir=/home/wwwroot/www.iamle.com/:/proc/:/tmp/
[PATH=/home/wwwroot/www.iamle.com/]
open_basedir=/home/wwwroot/www.iamle.com/:/proc/:/tmp/

 

测试中还发现这三个地方配置的优先级如下

“php.ini” > “nginx fastcgi fastcgi_param” > “php-fpm.conf”

 

如果有错误欢迎大家留言斧正,感谢!

 

0x05 参考文档

PHP绕过open_basedir列目录的研究
open_basedir bypass exploit
php-fpm.conf 全局配置段
php.ini HOST PATH配置

 

#安装依赖库
yum -y install mysql-devel libcurl-devel net-snmp-devel Percona-Server-devel-55
#因为我的mysql使用的是percona55 所以这里需要装 Percona-Server-devel-55

#给zabbix在mysql中创建库和用户
create database zabbix character set utf8;
grant all privileges on zabbix.* to zabbix@localhost identified by 'zabbix';


#创建zabbix运行的独立用户
groupadd zabbix
useradd zabbix -g zabbix -s /sbin/nologin

#下载编译安装zabbix
wget -O zabbix.tar.gz -c "http://sourceforge.net/projects/zabbix/files/ZABBIX%20Latest%20Stable/2.2.4/zabbix-2.2.4.tar.gz/download"

tar zxvf zabbix.tar.gz
cd zabbix-2.2.4/

./configure --prefix=/usr/local/zabbix --enable-server --enable-agent \
--with-mysql --with-net-snmp --with-libcurl
make install

##编译错误解决
#checking for mysql_config... /usr/bin/mysql_config
#checking for main in -lmysqlclient... no
#configure: error: Not found mysqlclient library
ln -s /usr/lib64/mysql/libmysqlclient.so.16.0.0 /usr/lib64/mysql/libmysqlclient.so
ln -s /usr/lib64/mysql/libmysqlclient_r.so.16.0.0 /usr/lib64/mysql/libmysqlclient_r.so
ln -s /usr/lib64/libmysqlclient.so.16.0.0 /usr/lib64/libmysqlclient.so
ln -s /usr/lib64/libmysqlclient_r.so.16.0.0 /usr/lib64/libmysqlclient_r.so

#导入zabbix的数据库
mysql -uzabbix -pzabbix -hlocalhost zabbix < database/mysql/schema.sql
mysql -uzabbix -pzabbix -hlocalhost zabbix < database/mysql/images.sql
mysql -uzabbix -pzabbix -hlocalhost zabbix < database/mysql/data.sql

#修改配置文件
cp misc/init.d/fedora/core/zabbix_server /etc/init.d/
cp misc/init.d/fedora/core/zabbix_agentd /etc/init.d/
cp -R frontends/php /data/wwwroot/zabbix  #复制web文件到网站目录,替换成你自己的
sed -i 's/^DBUser=.*$/DBUser=zabbix/g' /usr/local/zabbix/etc/zabbix_server.conf
sed -i 's/^.*DBPassword=.*$/DBPassword=zabbix/g' /usr/local/zabbix/etc/zabbix_server.conf
sed -i 's/BASEDIR=\/usr\/local/BASEDIR=\/usr\/local\/zabbix/g' /etc/init.d/zabbix_server
sed -i 's/BASEDIR=\/usr\/local/BASEDIR=\/usr\/local\/zabbix/g' /etc/init.d/zabbix_agentd

#增加服务端口<br>
cat >>/etc/services <<EOF
zabbix-agent 10050/tcp #Zabbix Agent
zabbix-agent 10050/udp #Zabbix Agent
zabbix-trapper 10051/tcp #Zabbix Trapper
zabbix-trapper 10051/udp #Zabbix Trapper
EOF

#启动服务
/etc/init.d/zabbix_server start
/etc/init.d/zabbix_agentd start
chkconfig zabbix_server on   #开机启动启动服务
#chkconfig zabbix_agentd on  #被控端
#echo "/etc/init.d/zabbix_server start" >> /etc/rc.local
#echo "/etc/init.d/zabbix_agentd start" >> /etc/rc.local

问题处理

zabbix_server  不能监听端口tcp  10051 ?

打开日志 cat /tmp/zabbix_server.log

1635:20140706:015834.413 [Z3001] connection to database ‘zabbix’ failed: [2002] Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’ (2)
1635:20140706:015834.413 Database is down. Reconnecting in 10 seconds.

看来是mysql sock错误了。 找到 #DBSocket=/tmp/mysql.sock 去掉前面的#注释即可。

zabbix2.2.4 web中 语言没有中文可选?

1、服务器端找到 zabbix/include/ locales.inc.php 文件

2、修改 locales.inc.php内容为:’zh_CN’ => array(‘name’ => _(‘Chinese (zh_CN)’),        ‘display’ => true),

       默认是false,所以不显示Chinese(zh_CN)。保存退出。

  •        
  •       ◆简介

      虽然lnmp中带的php5.2.10已经能够满足目前的php程序运行。不过看到php5.3.3发布后一直没有更新。就像我用nginx一只用着最新的工程预览版。看了下php5.3.3已经自带php-fpm了。只需要咋编译配置php的时候加上 –enable-fpm 参数。以前补丁上fpm是通过xml文件配置的。新版本的php5.3.3的fpm是通过ini文件配置的。遗憾的是php5.3.3 不支持Zend Optimizer  还有文中我用旧php.ini文件放到里面产生了很多问题,如果你遇到什么问题请留言给我。贴出启动php-pmf的报错代码。^_^。2010年8月17日13:21:32成功升级php为php5.3.3

php 5.3.3 源码中开始包含 php-fpm,不用专门再打补丁了,只需要解开源码直接configure,关于php-fpm的编译参数有 –enable-fpm –with-fpm-user=www –with-fpm-group=www –with-libevent-dir=libevent位置。

这个php-fpm 不再支持 php-fpm 补丁具有的 /usr/local/php/sbin/php-fpm (start|stop|reload)等命令,需要使用信号控制:

master进程可以理解以下信号

SIGINT, SIGTERM 立刻终止

SIGQUIT 平滑终止

SIGUSR1 重新打开日志文件

SIGUSR2 平滑重载所有worker进程并重新载入配置和二进制模块

示例:

php-fpm 关闭:

kill -SIGINT `cat /usr/local/php/var/run/php-fpm.pid`

php-fpm 重启:

kill -SIGUSR2 `cat /usr/local/php/var/run/php-fpm.pid`

继续阅读

如果你是采用www.lnmp.org一键包搭建的lnmp环境。软件目录结构一样。复制以下代码到ssh中直接升级nginx到新版本。

Bash语言: Codee#12550
01 wget http://www.nginx.org/download/nginx-0.8.49.tar.gz
02 tar zxvf nginx-0.8.49.tar.gz
03 cd nginx-0.8.49
04 ./configure –user=www –group=www –prefix=/usr/local/nginx –with-http_stub_status_module –with-http_ssl_module  –with-http_sub_module
05 make
06 mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
07 cd objs/
08 cp nginx /usr/local/nginx/sbin/
09 /usr/local/nginx/sbin/nginx -t
10 kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
11 kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
12 /usr/local/nginx/sbin/nginx -v
13 cd ..
14 cd ..
15 rm -rf nginx-0.8.49
16 rm -rf nginx-0.8.49.tar.gz

复制以上代码到ssh执行即可。 以后只需要替换 0.8.48 nginx的版本号即可。