PHP安全编程:register_globals的安全性 全局变量注册(转)
如果你还能记起早期Web应用开发中使用C开发CGI程序的话,一定会对繁琐的表单处理深有体会。当PHP的register_globals配置选项打开时,复杂的原始表单处理不复存在,公用变量会自动建立。它让PHP编程变得容易和方便,但同时也带来了安全隐患。
用户输入从何而来?第一个源是 GET、POST 和 COOKIE 数据。一般称为 GPC 数据。此数据的可识别程序依赖于一个有争议的 php.ini设置:register_globals。在 PHP V4.3.0 以后,register_globals 默认情况下被设置为 Off。但是几年前,在 PHP 中,register_globals 的默认值是打开的,所以存在很多需要它的代码。
事实上,register_globals是无辜的,它并不会产生漏洞,同时还要开发者犯错才行。可是,有两个主要原因导致了您必须在开发和布署应用时关闭register_globals:
- 第一,它会增加安全漏洞的数量;
- 第二,隐藏了数据的来源,与开发者需要随时跟踪数据的责任相违背。
register_globals?本身并非安全风险。但是,它为跟踪用户输入和确保应用程序安全增加了难度。为什么会这样?因为如果打开register_globals,在全局名称空间和 $_GET、$_POST 或 $_COOKIE 数组中,将创建 GET、POST 和 COOKIE 传递到 PHP 脚本的所有变量。
下面是工作方式及其重要性的示例:
01 |
<?php |
02 |
03 |
// See if the user has the secret cookie. |
04 |
if (!empty($_COOKIE['secret'])) { |
05 |
$authorized = true; |
06 |
} |
07 |
08 |
// Now let's go through a list of press releases and show them. |
09 |
$releases = get_press_releases(); |
10 |
foreach ($releases as $release) { |
11 |
12 |
// Some releases are restricted. Only show them to people who can |
13 |
// see secrets. |
14 |
if ($release['secret']) { |
15 |
if (!$authorized) { |
16 |
continue; |
17 |
} |
18 |
} |
19 |
20 |
// We must be allowed to see it. |
21 |
showRelease($release); |
22 |
} |
23 |
?> |
您应该注意几件事。第一,依靠 cookie 来判断用户是否已通过身份验证不是个好主意 —— 因为人们可以很容易地设置自己的 cookie 值。我们将在另外一篇文章中叙述这一点。无论如何,此脚本的缺点在于,如果打开 register_globals,它就不具备安全性了。
下面介绍名为 press.php 的脚本。一般来说,当用户访问 press 发行版的脚本时,其浏览器将显示 http://www.example.com/company/press.php。
现在注意当用户擅自将其更改为 http://www.example.com/company/press.php?authorized=1 时将发生什么事?
看看前面的代码:仅当用户使用 cookie 时才设置 $authorized。它永远不会被设置为假。后来引入了 register_globals —— 它取代了刚才使用的 $_GET['authorized'],同时在全局范围内还存在一个值为 1 的变量 $authorized。因此,即使用户没有通过 cookie 检查,$authorized 后来在 foreach 循环中引用时,仍然会被验证为真。
修复此缺陷可以使用两种方式。其一,当然是关闭 register_globals。如果关闭它对您的生产站点没有影响,则这是个好主意。您需要测试一下应用程序,确保它没有因此中断运行。
另一种方式有点像“防御性编程”。我们只需要将 cookie 检查更改为以下形式即可:
1 |
<?php |
2 |
3 |
// See if the user has the secret cookie. |
4 |
$authorized = false; |
5 |
if (!empty($_COOKIE['secret'])) { |
6 |
$authorized = true; |
7 |
} |
8 |
?> |
这时,当用户将 ?authorized=1 添加到脚本 URL 时,$authorized 变量仍然被设置为 1 —— 但是它随即会被 $authorized = false 覆盖,只有那些实际具有秘密 cookie 的用户才能看到受限的 press 发行版。他们仍然可以设计自己的 cookie。
审计代码的教训:设法关闭 register_globals。如果不打开 register_globals 应用程序就不能运行,并且您无法修改它,或者在应用程序必须运行的地方您无法控制 PHP 配置,则需要在条件块中查找所有全局变量设置,或者通过某些函数调用进入全局范围。如果 register_globals 为打开状态,则这两种情形都是由用户将变量设置为任意值引起的。
找到这些变量的好办法是将 php.ini 设置 error_reporting 设置为 E_ALL,同时使用 log_errors 或 display_errors,这样,所有 PHP 警告和错误都会被分别记录在文件中或显示在屏幕上。每当使用未初始化的变量(假定具有值)时,您将得到一条 E_NOTICE。这像 C 和 Java? 语言中那样,仍然与让 PHP 要求声明 变量有所不同。结果,当我们的第一个版本的脚本运行时,出现的错误消息是:
1 |
Notice: Undefined variable: authorized in C:\var\www\articles\press.php |
2 |
on line 15 |
只要用户没有权限,错误就发生在第 15 行,而不是起初设置变量的第 5 行。PHP 在布尔上下文中将不确定的变量解释为假(参阅 参考资料 中列出的 PHP 手册中的“类型强制转换”),这样代码无论如何都会“正常运行”了 —— 除非有人暗中使用别的方式定义 $authorized。
如果您必须要开发一个在register_globals开启的环境中布署的应用时,很重要的一点是您必须要初始化所有变量并且把error_reporting 设为 E_ALL(或 E_ALL | E_STRICT)以对未初始化变量进行警告。当register_globals开启时,任何使用未初始化变量的行为几乎就意味着安全漏洞。
PHP安全编程:register_globals的安全性 全局变量注册(转)的更多相关文章
- PHP安全编程:register_globals的安全性
如果你还能记起早期Web应用开发中使用C开发CGI程序的话,一定会对繁琐的表单处理深有体会.当PHP的register_globals配置选项打开时,复杂的原始表单处理不复存在,公用变量会自动建立.它 ...
- php安全编程: register_globals的安全性
register_globals?本身并非安全风险.但是,它为跟踪用户输入和确保应用程序安全增加了难度.为什么会这样? 因为如果打开 register_globals,在全局名称空间和 $_GET.$ ...
- register_globals(全局变量注册开关)
register_globals,是php.ini文件里面的一个配置选项,接下来,我们可以通过例程来分析一下,当register_globals = on 与 register_globals = o ...
- python编程系列---多线程共享全局变量出现了安全问题的解决方法
多线程共享全局变量出现了安全问题的解决方法 当多线程共享全局变量时,可能出现安全问题,解决机制----互斥锁:即在在一段与全局变量修改相关的代码中,假设一个时间片不足以完成全局变量的修改,就在这段代码 ...
- Java多线程编程(3)--线程安全性
一.线程安全性 一般而言,如果一个类在单线程环境下能够运作正常,并且在多线程环境下,在其使用方不必为其做任何改变的情况下也能运作正常,那么我们就称其是线程安全的.反之,如果一个类在单线程环境下运作 ...
- Android 编程下两种方式注册广播的区别
常驻型广播 常驻型广播,当你的应用程序关闭了,如果有广播信息来,你写的广播接收器同样的能接收到,它的注册方式就是在你应用程序的AndroidManifast.xml 中进行注册,这种注册方式通常又被称 ...
- 转 Android 编程下两种方式注册广播的区别
常驻型广播 常驻型广播,当你的应用程序关闭了,如果有广播信息来,你写的广播接收器同样的能接收到,它的注册方式就是在你应用程序的AndroidManifast.xml 中进行注册,这种注册方式通常又被称 ...
- python学习,day3:函数式编程,局部变量和全局变量
# coding=utf-8 # Author: RyAn Bi school = 'THU' #全局变量 def change_name(name): global age #在函数中,用globa ...
- MVC-AOP(面向切面编程)思想-Filter 三种注册方式
在ASP.NET MVC框架中,为我们提供了四种类型的Filter类型包括:IAuthorizationFilter.IActionFilter.IResultFilter.IExceptionFil ...
随机推荐
- 【cogs247】售票系统
[问题描述] 某次列车途经C个城市,城市编号依次为1到C,列车上共有S个座位,铁路局规定售出的车票只能是坐票, 即车上所有的旅客都有座.售票系统是由计算机执行的,每一个售票申请包含三个参数,分别用O. ...
- Semaphore (通常用于限制可以访问某些资源(物理或逻辑的)的线程数目)
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目.例如,下面的类使用信号量控制对内容池的访问: 方法详解: 构造方法摘要 Semaphore(int permits) ...
- centos账户的uid和gid
修改/etc/passwd和/etc/group文件的UID和GID为0,可以获得root权限,不过不推荐~ UID和GID Linux系统如何区别不同的用户呢?可以很自然地想到,使用不同的用户名应该 ...
- underscorejs-reduce学习
2.3 reduce 2.3.1 语法: _.reduce(list, iteratee, [memo], [context]) 2.3.2 说明: reduce方法把list中元素归结为一个单独的数 ...
- Oracle Pl/SQL编程基础
Pl/SQL简介 提高应用程序的运行性能, 提供模块化的程序设计, 自定义标示符, 具有过程语言控制结构, 良好的兼容性, 处理运行错误. Pl/SQL语言基础 sql是关系数据库的基本操作语言. s ...
- highcharts实例教程一:结合php与mysql生成折线图
Highcharts是一款纯javascript和html5编写的图表库,不仅几乎能兼容所有pc浏览器,而且对ios和android手机端的兼容 性也不错,它能够很简单便捷的在Web网站或Web应用中 ...
- Light OJ 1104 第六周F题
F - 概率(经典问题) Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Descri ...
- 周赛F题 POJ 1458(最长公共子序列)
F - F Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Description ...
- java面试(毕业一年后准备换工作)
还记得一年前的今天,在网上投简历,找工作,当时找的工作的工作地点都在成都,其实自己挺想去外面工作几年的,如果毕业后就在成都工作,今后基本不可能去外省了, 所以刚好上海的一家外包公司来成都理工校招,导员 ...
- ExtJs MVC应用架构示例
项目目录结构 (源码)2. app.js Ext.Loader.setConfig({ enabled : true, paths : { 'Ext' : 'extjs', 'App' : 'app' ...