Suhosin是什么东西?
我第一次听见这个名字是在Debian的Apache+PHP套件上 这个东西感觉读起来很拗口 感觉不是什么正常的英文单词 所以也就没什么欲望去了解他
不过今天确不得不和他接触了
接二连三某同学(话说他运气真好 为什么我自己就遇不到)告诉我在学校PT上做种子发布后部分种子在 μtorrent中提示 "失败: 错误:缺少参数 info_hash"
更加奇怪的是 他只是1-2个种子出这种问题,其他种子正常
PT代码使用的是晨光的方案 我自己排查结果未果 就向Ditto老大(下文简称D大)咨询 乃知道D大说 这是个“常见问题” 具体原因还没搞清楚。然后我,D大,还有Demon就开始探讨原因。
首先,抓包显示 μtorrent确实传递了info_hash 在Nginx的日志里面确实存在info_hash的访问 但是我通过phpinfo进行info_hash查询的时候 在$_SERVER["QUERY_STRING"]和$_SERVER["REQUEST_URI"]两个变量里面都有info_hash存在 但是唯独程序需要的$_GET["info_hash"]不存在 连$_REQUEST["info_hash"]都没有。
那么问题的焦点被集中到了两个地方
1.Nginx确实接收到了info_hash 但是没能正确传递给FastCGI Server 可能是Nginx的Bug。
2.PHP可能在接受Nginx传的参数的时候解析出现了问题。可能是PHP的BUG。
接下来我为了验证到底问题出在哪里 开始反复的编译PHP和Nginx 通过替换法来确定问题所在
由于不是所有的种子都有这个问题,我把从问题的Info_Hash单独提出出来 在phpinfo后面进行查询(这样能看的比较清楚) 这个出问题的info_hash是
info_hash=t%01%2bX%90X%00%b5%efzP%e9%2c%e1V%3fX%d9V%f6
奇怪的是 无论是php5.3.6还是php 5.3.5 无论是nginx/0.8.54 stable还是Debian源里面的Nginx 0.6.32 都不能重现该BUG
但是在PT上 确实存在这样的问题 采用同一方案部署的新BBS也存在这样的问题。与此同时 在我先编译测试PHP 5.3.5的时候.我已经包5.3.6测试结果汇报给了D大 刚开始还不知道PHP 5.3.5也没问题。还以为是PHP 5.3.5的问题而PHP 5.3.6解决了。于是D大开始翻阅PHP官方SVN的日志 但是没有什么收获。到后面PHP 5.3.5编译出来 也还是没问题。我就开始崩溃了。
我开始怀疑是不是源的问题 于是就在试验机上把编译的和非编译的PHP的版本全部清空了 然后重新从源里面再进行安装(安装的时候出了点小问题 前面编译的时候可能还有东西没卸载干净 导致扩展起不来 我火了,就把扩展全部禁用了) 发现装出来的PHP也没有这个问题
我开始把怀疑的目光放到PHP的扩展上。
于是我把PT所有扩展全部停用 通过phpinfo进行对info_hash查询,发现终于发现了$_GET["info_hash"]和$_REQUEST["info_hash"]的踪影。然后我就一个一个扩展的测试 最后找到了“罪魁祸首” Suhosin 。把这个扩展禁用后,一切OK。
Google了一下 Suhosin
官方网站 Suhosin http://www.hardened-php.net/
其大致作用是
解决php的“远程文件包含”带来的安全隐患,例如PHP禁止allow_url_fopen选项,但不能彻底禁止通过PHP的攻击,Suhosin就修补了这个缺憾.
若果用户呈交的资料包含 GLOBALS、_GET、_COOKIE 等敏感名称,一律过滤掉
可使用额外的配置来禁止一些php中可能带来安全隐患的功能
另外,Suhosin是兼容ZendOptimizer 的
当我还疑惑着是不是Suhosin在处理一些特殊字符的Bug的时候(那串info_hash怎么看怎么不像安全“敏感词”) Demon兄弟给出了答案
在Suhosin的源代码里面 对GET和POST过来的ASCII-NUL字符进行了过滤 Suhosin认为这是一种攻击,从而阻止了从queryString到$_GET里面的转化。这也就是为什么这些特殊的info_hash不能被PHP正确获得的原因。也解释了为什么禁用扩展后问题能解决。
同时 Demon指出 从Suhosin源代码看出 这些事件Suhosin应该会做记录。
但是日志遍寻不着 居然在syslog里面找到了 果然如demon说说 syslog里面都是这样的记录
Mar 28 14:44:11 CCZU-PT suhosin[21982]: ALERT - ASCII-NUL chars not allowed within request variables - dropped variable 'info_hash' (attacker '219.230.144.196', file '/**********/announce.php')
从源代码看 Suhosin对ASCII-NUL的过滤是做了if判断的(Via :Demon)所以在配置文件里面应该可以关掉。
Demon兄弟提供了一份Suhosin源代码里面自带的配置文件(这个sample是作者从Mandriva Linux维护的Suhosin包里面提取出来的 并且得到了Mandriva官方的许可 作为再分发)里面有详细的设定说明。根据这个说明 在关闭
suhosin.request.disallow_nul = 0
suhosin.get.disallow_nul = 0
suhosin.post.disallow_nul = 0
三个选项后 安全的启用Suhosin扩展,同时不引起info_hash的问题。
这个配置文件可以在这里下载
[download id="28" format="2"]
遇到问题多动脑 动手 多讨论 其乐无穷。
不过,Suhosin这种过滤强度应该会引起很多问题。后面估计还可能会遇到。立此存照。
扩展阅读 http://demon.tw/software/suhosin-php.html
@ihipop
Ditto 14:40:45
重复跟过滤不过滤没关系,另外我这也没用过这种安全扩展
@Demon
那D大说的info_hash重复是不是被这货过滤的结果?
作为“保护神”,这种过滤强度是无可厚非的。
mysql_real_escape_string过滤掉的是\x00, \n, \r, \, ', ", \x1a
@Demon
甘愿被鄙视
······················
我是前来鄙视你的