修改PHP源代码解决Nginx下WebShell的问题

Nginx / Lighttpd + PHP FastCGI的方式正在被越来越多的网站应用,其中让需要虚拟主机支持的用户最烦心的一件事情莫过于站点权限隔离。 目前无论是spawn-cgi或者是php-fpm的方式,都无法动态转变执行用户。尽管可以通过给不同网站以不同的用户身份执行FastCGI,但这也同样失去了FastCGI统一管理的优势,需要为每个网站保留足够的处理进程而不是整体规划。

Google搜之有两个比较广为流传的方法,其中最完美的莫过于直接修改PHP源代码,对打开目录进行鉴权(搜出来的资料最早是anxsoft.com提供的代码)。 方法是在php源代码目录中执行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;
            }
        }
 

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

编译后测试发现确实的解决了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/;

注:该网站的root为/web/zend.hly1980.cn/html。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值