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 脚本的所有变量。

下面是工作方式及其重要性的示例:

 1 <?php
 2
 3 // See if the user has the secret cookie.
 4 if (!empty($_COOKIE[‘secret‘])) {
 5    $authorized = true;
 6 }
 7
 8 // Now let‘s go through a list of press releases and show them.
 9 $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开启时,任何使用未初始化变量的行为几乎就意味着安全漏洞。

时间: 2024-10-07 23:31:50

PHP安全编程:register_globals的安全性的相关文章

并发编程初探-线程安全性

在Java并发编程中,对于线程安全是非常重要的,也是必须要考虑的一个问题.可以这么说,只要涉及到网络的,都必须考虑线程安全问题.好了,开始噼里啪啦地开始敲代码之前,我觉得有必要了解一些文绉绉的理论知识,因为这些理论知识是我们敲出来的代码是否是线程安全的一个依据. 当多个线程访问某个状态变量并且其中有一个线程执行写入操作的时候,必须考虑采用同步机制来协同这些线程对变量的访问,Java中的主要同步机制是关键字synchronized,它提供了一种独占的加锁方式,但"同步"这个术语还包括类型的变量,显

并发编程之线程安全性

一.什么是线程安全性 并发编程中要编写线程安全的代码,则必须对可变的共享状态的访问操作进行管理. 对象的状态就是存储在实例或者静态变量中的数据,同时其状态也包含其关联对象的字段,比如字典集合既包含自己的状态, 也包含KeyValuePair. 共享即可以多个线程同时访问变量,可变即变量在其声明周期内可以发生变化. 代码线程安全性关注的是防止对数据进行不可控的并发访问. 是否以多线程的方式访问对象,决定了此对象是否需要线程安全性.线程安全性强调的是对对象的访问方式,而不是对象 要实现的功能.要实现

并发编程2-线程安全性

在构建稳健的并发程序时,除了正确的使用线程和锁外.如何对状态访问进行管理是编码的核心.特别是对共享的(shared)和可变的(Mutable)状态的访问."共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周期内可以发生变化.我们讨论线程安全性更侧重于如何防止在数据上发生不受控的并发访问. 一个对象是否需要是线程安全的,取决于它是否被多个线程访问.这是程序中访问对象的方式,而不是对象要实现的功能.我们可以通过同步机制来协同对对象可变状态的访问

《PHP安全编程系列》系列分享专栏

PHP安全编程系列收藏夹收藏了有关PHP安全编程方面的知识,对PHP安全编程提供学习参考 <PHP安全编程系列>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read/201738.html 文章 discuz的php防止sql注入函数 php防止xss攻击的方法 PHP安全编程:register_globals的安全性 PHP安全编程:对输出要进行转义 PHP安全编程:过滤用户输入 PHP安全编程:可用性与数据跟踪 PHP安全编程:网站安全设计

【读书笔记《Android游戏编程之从零开始》】20.游戏开发基础(游戏数据存储)

对于数据的存储,Android 提供了4种保存方式. (1)SharedPreference 此方法适用于简单数据的保持,文如其名,属于配置性质的保存,不适合比较大的情况,默认存放在手机内存里 (2)FileInputStream/FileOutputStream 此方式比较适合游戏的保存和使用,流文件数据存储可以保持较大的数据,而且通过此方式不仅能把数据存储在手机内存中,也能将数据保存到手机额SDcard中. (3)SQLite 此方式也适合游戏的保存和使用,不仅可以保存较大的数据,而且可以将

Java线程安全性中的对象发布和逸出

发布(Publish)和逸出(Escape)这两个概念倒是第一次听说,不过它在实际当中却十分常见,这和Java并发编程的线程安全性就很大的关系. 什么是发布?简单来说就是提供一个对象的引用给作用域之外的代码.比如return一个对象,或者作为参数传递到其他类的方法中. 什么是逸出?如果一个类还没有构造结束就已经提供给了外部代码一个对象引用即发布了该对象,此时叫做对象逸出,对象的逸出会破坏线程的安全性. 概念我们知道了,可我们要关注什么地方呢?我们要关注的时候就是逸出问题,在不该发布该对象的地方就

Atitit.并发编程原理与概论 attilax总结

1. 并发一般涉及如下几个方面:2 2. 线程安全性 ( 2.2 原子性 2.3 加锁机制2 2.1. 线程封闭3.3.1Ad-hoc线程封闭 3.3.2 栈封闭 3.3.3ThreadLocal类2 3. 异步2 4. 同步与锁关键字2 5. 5.2 并发容器与并发集合2 6. Future模式 2 7. 5.3 阻塞队列和生产者-消费者模式(5.3.2 串行线程封闭 5.3.3 双端队列与工作密取 2 8. 5.4 阻塞方法与中断方法 2 9. 5.5 同步工具类 5.5.1 闭锁 5.5.

Linux实验3,shell编程

/etc/passwd用途:该目录存储的是操作系统用户信息,该文件为所有用户可见.由6个分号组成7个信息, 分别为,用户名,密码(已经加密),UID(用户标识),GID组标识,用户全名或本地账号,开始目录,登录使用的shell就是对登录命令进行解析的工具 /etc/shadow:共有9位,分别是:账号名称,密码,最近更动密码的日期,密码需要重新变更的天数,密码需要变更期限前的警告期限,密码过期的恕限时间,账号失效日期,保留 /etc/group:组名,口令,组标识号,组内用户列表 /etc/gs

整理一些PHP开发安全问题

整理一些PHP开发安全问题 php给了开发者极大的灵活性,但是这也为安全问题带来了潜在的隐患,近期需要总结一下以往的问题,在这里借翻译一篇文章同时加上自己开发的一些感触总结一下. 简介 当开发一个互联网服务的时候,必须时刻牢记安全观念,并在开发的代码中体现.PHP脚本语言对安全问题并不关心,特别是对大多数没有经验的开发者来说.每当你讲任何涉及到钱财事务等交易问题时,需要特别注意安全问题的考虑,例如开发一个论坛或者是一个购物车等. 安全保护一般性要点 不相信表单 对于一般的Javascript前台