PHP 沙箱环境介绍

沙箱是我们的命根子,用户之间需要有一套比较完善的隔离方案。因此我们的沙箱做了这些事:

  • 文件权限隔离
  • 数据库沙箱
  • CPU 时间统计
  • 网络访问沙箱
  • 缓冲区调整
  • 危险函数拦截

下面来分别说说。

文件权限隔离

不同的虚拟主机之间的数据,原则上是无法互访的。大多数情况下我们可以用 open_basedir 进行隔离,而 PHP 在某些情况下会绕过这一隔离,因此我们的沙箱环境覆盖到了 open_basedir 无法保护到的部分。

数据库沙箱

拿到了用户名密码,再买个同网络的主机,是不是就能随便黑人家数据库了?在其他家可以,在Hostker&主机壳是行不通的。我们将数据库的权限精确匹配到每个用户开通的主机上,相同用户名下的主机才可互访数据库,不同用户之间即使持有正确用户名密码也无法连上数据库。

既然做了沙箱,就顺便把数据库查询次数和时间统计上,放在 HTTP Header 中,有兴趣的读者可以根据这些数据进行程序优化。

CPU 时间统计

如何确认一个用户所占用的计算资源?按运行时间?大多数情况下,时间有可能是消耗在网络 IO 上,因此对用户按请求时间计费并不公平。我们在沙箱上完成了系统态和用户态的 CPU 时间统计,并放在 HTTP Header 中供开发者参考。

网络访问沙箱

使用过 DEDEcms 的用户应该对 PHPDDOS 不陌生,这程序漏洞太多了,黑客都有一套自动化扫描入侵的程序,插一个 PHPDDOS 文件,死循环对某个攻击目标发送 HTTP 请求。这就非常危险了,很容易把服务器出口带宽吃光。

另外,黑客有可能手痒痒希望扫描我们的内网窥探 CDN 的分布情况。

针对这些问题我们的沙箱对全部的网络访问进行了一次过滤,对于有问题的请求会直接拦截掉,确保不会消耗大量出口带宽,并保证内网的节点安全。

缓冲区调整

上面提到的东西都需要在 Header 中出现,那么万一用户提前 flush 了数据怎么处理?我们的沙箱会拦截用户的输出行为,全部重定向到缓冲区中,直到一个请求彻底完成,才发送带有 CPU 时间、数据库时间、数据库查询次数的 Header,再将缓冲区的数据作为 Body 发出。

危险函数拦截

PHP 并不适合长时间运行,因此我们对 PHP 的运行时间有所限制。可是万一用户使用 set_timeout_limit() 进行调整怎么办?直接禁用函数?甩一脸错误?

针对比较危险的函数行为,我们会首先判断这一行为的合法性,例如 sleep、usleep 函数,对于小于 5 秒的相对合理的暂停是没问题的,如果超过 5 秒才会返回异常。而对于 set_timeout_limit() 我们判断是超过 60 秒就拒绝这一修改行为,小于 60 秒则放行。

但是对于大多数使用开源程序的用户,他们最害怕见到的就是错误,如果修改失败就会产生 Warning,因此我们函数返回的是 true,看起来是成功了,实际上配额还是我们给用户分配的默认配额。这样用户体验就会稍微好一点。

以上就是我们 PHP 沙箱的主要功能,还有更多细节这里不方便展开说明。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.