何为敏感信息?简单点来说就是你不想让别人知道的信息,比如说数据库的地址,用户名,密码等等,此类信息往往知道的人越少越好。
通常,PHP程序里的配置文件大致如下所示:
<?php return array( 'database' => array( 'host' => '192.168.0.1', 'username' => 'administrator', 'password' => 'e1bfd762321e409cee4ac0b6e841963c', ), ); ?>
有时候出于某些原因,比如说代码审查,亦或者合作开发等等,第三方需要获取代码版本仓库的读权限,一旦授权,数据库的地址,用户名,密码等敏感信息就暴露了。当然也可以不在代码版本仓库里保存配置文件,取而代之是撰写文档进行说明,但我不喜欢这样的方法,因为如此一来,代码本身是不完整的。
如何解决此类问题呢?最直接的方法是把敏感信息从代码中拿掉,换个地方保存。具体保存到哪里呢?有很多选择,比如说通过nginx的fastcgi_param来设置:
fastcgi_param DATABASE_HOST 192.168.0.1; fastcgi_param DATABASE_USERNAME administrator; fastcgi_param DATABASE_PASSWORD e1bfd762321e409cee4ac0b6e841963c;
经过这样的映射后,我们的代码就不会直接包含敏感信息了:
<?php return array( 'database' => array( 'host' => $_SERVER['DATABASE_HOST'], 'user' => $_SERVER['DATABASE_USERNAME'], 'password' => $_SERVER['DATABASE_PASSWORD'], ), ); ?>
此外,还可以通过php-fpm的env指令来设置:
env[DATABASE_HOST] = 192.168.0.1 env[DATABASE_USERNAME] = administrator env[DATABASE_PASSWORD] = e1bfd762321e409cee4ac0b6e841963c
需要说明的一点是,这个设置必须放在主配置文件php-fpm.conf里,不能放到include指令设置的子配置文件里,否则会报错:「Array are not allowed in the global section」;另外一点,虽然是通过env设置的,但结果还是在$_SERVER里,而不是$_ENV。
…
通过nginx和php-fpm配置文件来解决问题的话,有一个缺点,仅对Web有效,如果通过命令行来运行,那么无法在$_SERVER里获取相关信息,不过这不算什么难事儿,只要写个公共的脚本正则匹配一下nginx或者php-fpm的配置文件,就可以动态的把这些信息映射到命令行环境,具体怎么搞就留给大家自己操作吧。
…
说明: @Laruence 提醒了我,如果配置信息通过nginx的fastcgi_param来设置的话,当nginx和php交互时,会带来大量的数据传输(如此看来通过php-fpm的env来设置相对更有优势),鸟哥建议使用独立的扩展来搞定,比如「hidef」。如果你使用hidef的话,需要注意一点,hidef定义的常量通过phpinfo函数可以一览无遗,为了安全性,你应该在配置文件php.ini里禁用相关函数:「disable_functions = phpinfo」。
…
看起来还是hidef可用性更好些,具体选择就看客观情况而定吧,如果能够安装扩展,那么就推荐使用hidef,否则就推荐使用env的方法。
蛮有趣的,我们倒是把测试与生产的配置文件分离 也解决了这个问题了。
他说也只不过让攻击者绕了路子而已, 假如照他这样说的话,还不如把数据库源代码加密呢? 他说的扩展, 是调用也好 还是api也好 数据库连接代码肯定要使用到, 最终还是找到的。 并且这个方法只能用于公司有运维的人 假如不是很懂技术草根站长, 配置这个都觉得麻烦呢。
不错的方法。。。可以做为自己产品使用,但是作为一款开源的产品,感觉如果这样做,就太麻烦了。。。
通过hidef扩展设置常量时,多个网站时都是共用设置吗?能根据网站分别设置吗?
Pingback引用通告: 该不该把信息写在服务器配置文件里? - I am a php programmer
集群环境里建一个持久化的ConfigServer吧,譬如用淘宝开源的Diamond(http://code.taobao.org/p/diamond/wiki/index/ )打底子。
fastcgi_param 里第二该是 DATABASE_USERNAME 吧…
Fixed,多谢提醒!
不用这么麻烦,直接将敏感信息独立成一个配置文件,这个配置文件不进代码库,再拷贝一个 database.example.conf 进代码库。
在每个需要跑实例的地方再拷贝一个 database.conf 就行了。
通用做法
nginx 于 php进程 php交互时 如果需要传递大量数据 不用 fastcgi_param
还有其他方案么 ?
会不会导致一个phpinfo或者debug信息就把你这个需要保护的信息反而泄漏了