标题:通过修改PHP源代码解决Nginx下WebShell跨站的问题 出处:沧海一粟 时间:Thu, 09 Dec 2010 15:41:38 +0000 作者:jed 地址:http://www.dzhope.com/post/715/ 内容: 看了很多方法,试了一下这个最好用,需要更改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/; Generated by Bo-blog 2.1.1 Release