通过修改PHP源代码解决Nginx下WebShell跨站的问题 不指定

jed , 2010-12-9 15:41 , 服务器技术 , 评论(0) , 阅读(4033) , Via 本站原创 | |
看了很多方法,试了一下这个最好用,需要更改php源程序后,重新编译php。在使用fpm方式安装时,打补丁过程中会修改php的文件,所以需要在打完fpm补丁后再修改php源程序。

tar zxvf php-5.2.14.tar.gz
gzip -cd php-5.2.14-fpm-0.5.14.diff.gz | patch -d php-5.2.14 -p1
cd php-5.2.14/

vi  main/fopen_wrappers.c

并找到php_check_open_basedir_ex方法,在char *end;和pathbuf = estrdup(PG(open_basedir));之间插入以下的代码:


char path_copy[MAXPATHLEN];
        int path_len;
        path_len = strlen(path);
        if (path_len >= MAXPATHLEN) {
            errno = EPERM;
            return -1;
        }
        if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
            memcpy(path_copy, path, path_len+1);
            while (path_len > 1 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
            path_copy[path_len] = '\0';
            path = (const char *)&path_copy;
        }

        char *env_doc_root;
        if (PG(doc_root)) {
            env_doc_root = estrdup(PG(doc_root));
        } else {
            env_doc_root = sapi_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
        }
        if (env_doc_root) {
            int res_root = php_check_specific_open_basedir(env_doc_root, path TSRMLS_CC);
            efree(env_doc_root);
            if (res_root == 0) {
                return 0;
            }
            if (res_root == -2) {
                errno = EPERM;
                return -1;
            }
        }



并在php.ini中启用open_basedir如


open_basedir = "/var/tmp/:/tmp/"




以上是所有能找到的资料里代码最长也是考虑最完整的代码。 前段是用于去除传入的路径参数中最后的多个斜杠(/)对代码判断的影响。后段则是取得当前站点的文档根目录,并检查要打开的文件是否存在于这个目录下、是否有权限等。

编译后测试发现确实的解决了WebShell对同级目录的跨站访问。但运行某个基于Zend Framework的项目时则遇到了阻碍,无法读取application目录下的config.ini。原因是root目录位于application的同级目录html下。 其他一些项目也可能会有类似需求,需要访问root同级的upload或其他不开放的目录。这个需求很容易就能解决,参考检查DOCUMENT_ROOT的方式,优先检查另外一个SITE_ROOT的环境变量是否存在且有权,并在nginx的php fastcgi配置里加上一行即可:

fastcgi_param  SITE_ROOT /web/zend.hly1980.cn/;

Tags: , ,
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]