理解PHP及其安全问题的入门知识

安全|问题

  有时候,您的业务可能涉及到 PHP 应用程序的安全性。当您遇到审计任务时,您知道如何执行查找吗?本系列将带您进入 PHP,并帮您在一定程序上了解它,让您在进行安全审计时知道查找什么。第 1 部分向您介绍 register_globals 设置。
  
  入门知识
  
  我在此假定您对 PHP 的语法有一个大致的了解,至少能够编写“Hello World”之类的程序。如果您不具备基础知识,则请首先学习 PHP 手册和某些基本的 PHP 教程(参阅 参考资料)。很多出版商都有关于 PHP 的好书。建议初学者一开始先看看入门书籍或食谱形式的书籍。
  
  在生产环境的准确副本上执行审计。您不需要复制硬件,但是需要确保软件版本尽量和实际的完全一样。PHP 配置必须精确匹配,这一点在 php.ini 文件中、在 .htaccess 文件的 Apache 指令中或在 httpd.conf 中已经指定。您需要准备一个单独的环境,因为您将显示和记录可能包含敏感的密码及其他信息的错误。此外,您将尝试中断站点的安全性,这一点是您在活动应用程序中极力避免的。
  
  第一步是将 PHP 的 error_reporting 设置更改为 E_ALL。设置更改后,每当使用未初始化的变量、进行错误的文件访问及发生其他(大多数)无害错误时,PHP 都会报告一条警告消息,但也存在这是一个潜在攻击矢量的可能性。这些错误一般情况下只是表明编程草率,所以如果这是您的代码,您把它们清除掉即可。
  
  该设置如下所示:
  
  error_reporting = E_ALL
  
  如果您不知道 php.ini 文件在哪里,则可以通过创建包含以下文本的 .php 脚本来查找:
  
  <?php
  
  phpinfo();
  
  输出的上面部分有一行列出了 PHP 查找 php.ini 的位置:
  
  
图 1. PHP 查找 php.ini 的位置

  
[[The No.1 Picture.]]

  值可能会有些变化,但 /usr/local/lib/php.ini 是大多数 UNIX? 系统上的公共位置,C:\php\php.ini 或 C:\WINDOWS\php.ini 是大多数 Microsoft? Windows? 系统上的公共位置。如果该文件不存在,则创建一个并在文件中键入上面的 error_reporting 行即可。修改 php.ini 文件后,需要重启 Web 服务器,PHP 才能启用新设置。
  
  如果您以前没有创建 phpinfo() 页面,则可以现在创建。第二个主要部分的标签是“配置”,它包含许多关于如何设置 PHP 的有用信息。该部分包括三列:设置名称、本地值 和 xmaster 值。主值是通过 php.ini 指令为您机器上的所有 PHP 脚本全局设置的值。本地值是对当前脚本生效的值。对它有影响的有:.htaccess 设置、httpd.conf 的 <Location> 或 <Directory> 部分中的设置和 PHP 脚本中的 ini_set 调用。在运行时,只有某些设置是可更改的。请参阅 参考资料中的 PHP 手册以获取详细信息。
  
  还需要自定义的另外两种设置是 display_errors 和 log_errors。您至少需要启用这两种设置中的一种,或者两种都启用。log_errors 通知 PHP 将注意、警告或错误记录在文件中,display_errors 将这些被记录下来的注意、警告和错误显示在屏幕上。它们不互相排斥。至少启用它们中的一个,可以有效地发现可能导致安全漏洞的编程错误。
  
  应该查找哪些种类的安全问题?
  
  值得庆幸的是,导致安全漏洞的很多编程错误在 PHP 中不可能存在。堆栈和缓冲溢出是 C 和 C++ 环境中两个常见的问题。因为 PHP 可以为您管理记忆,所以 PHP 代码不会导致堆栈和缓冲溢出。
  
  然而,PHP 本身也是使用 C 语言编写的,有时记忆问题深至 PHP 的核面。因此,您需要时时关注安全公报和更新。PHP 在其 Web 站点(参见 参考资料)公布新 PHP 版本并说明是否包含安全修补程序。
  
  PHP 应用程序中的大多数问题与使用用户提供的数据有关,在使用它和对它执行操作前未曾预先验证和消毒。您可能听说过称为 cross-site scripting (XSS) 的漏洞。XSS 通过提供程序不期望的输入,然后利用程序对无赖输入的处理方式发动进攻。编写良好的程序可以避免这些假定。在机场安全方面,PHP 程序用于检查旅客的行李。
  
  其他问题是一些细微的逻辑错误。例如,检查一系列参数,看看是否批准某个用户访问某种资源、是否把括弧放错位置以至于某些用户进入了他们原本不该到的地方。我们希望您的应用程序组织良好并具有这种集中式逻辑。
  
  识别用户输入
  
  最棘手的一件事情是如何从外部源(如某个用户、别的 Web 站点或某些其他资源)和已经验证的数据中区分出不受信任的输入。有人提出了“不相信一切”的观点,即不管来自何处,对于所有函数都要验证其数据。这一做法会牵涉到以下几件事情:第一,验证在不同的上下文中意味着不同的事情;第二,在应用程序的所有级别上快速执行验证是一件枯燥乏味和易于出错的事情;第三,您是在审计应用程序而不是在从头重新编写它。您需要通过现有代码来跟踪用户输入,而不能用验证函数包装您看到的每个变量。
  
  不期望的用户输入
  
  用户输入从何而来?第一个源是 GET、POST 和 COOKIE 数据。一般称为 GPC 数据。此数据的可识别程序依赖于一个有争议的 php.ini 设置:register_globals。在 PHP V4.3.0 以后,register_globals 默认情况下被设置为 Off。但是几年前,在 PHP 中,register_globals 的默认值是打开的,所以存在很多需要它的代码。
  
  register_globals 本身并非安全风险。但是,它为跟踪用户输入和确保应用程序安全增加了难度。为什么会这样?因为如果打开 register_globals,在全局名称空间和 $_GET、$_POST 或 $_COOKIE 数组中,将创建 GET、POST 和 COOKIE 传递到 PHP 脚本的所有变量。
  
  下面是工作方式及其重要性的示例:
  
  清单 1. COOKIE 的安全性
  
  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 }
  
  您应该注意几件事。第一,依靠 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 检查更改为以下形式即可:
  
  清单 2. 使用 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 }
  
  ...
  
  这时,当用户将 ?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 要求声明 变量有所不同。结果,当我们的第一个版本的脚本运行时,出现的错误消息是:
  
  Notice: Undefined variable: authorized in C:\var\www\articles\press.php
  on line 15

时间: 2024-08-31 22:52:53

理解PHP及其安全问题的入门知识的相关文章

JSP网站开发之HTML入门知识及常用标记符 (一)

        最近发生的事情很多,其中一件很重要的事情就是:学生生涯的结束,教学生涯的开始.我准备下个月写一篇总结研究生生涯的文章,包括自己放弃互联网选择回家教书.找工作经历.项目和毕业设计的各种感想.很荣幸XB七月初就给了我第一次大学教学的经历,很享受很珍惜也很感触.尤其是看到学生"秀璋,你好!"的跑马灯欢迎界面.发表"终于会编程了,感觉自己好牛逼"的说说.递给我餐巾纸.和你们打球等等.         言归正传,因为学生是大二升大三的,但是却没有学过网页相关知

《Arduino家居安全系统构建实战》——第1章 家居安全系统的入门知识

第1章 家居安全系统的入门知识 Arduino家居安全系统构建实战在这一章中,我们将会介绍如下的内容: 什么是家居安全基础设施它是如何工作的部署这样一个系统都需要些什么在当前条件下为安全系统所做的准备有线安全系统和无线安全系统传统系统与现代化家居安全系统为了紧紧跟随硬件的发展趋势,本书介绍了随处可见且价格极为低廉的平台--Arduino.今时今日,我们可以在各种各样的公共场所如中小学校.高等院校.小型企业或者公共机构见到这个小电路板的身影. Arduino平台因其众多的优势而著名,例如低廉的成本

代码-求指导jQuery入门知识

问题描述 求指导jQuery入门知识 脚本代码 $(document).ready(function () { function checkFields() { alert($("#name").attr("value")); alert($("#email").attr("value")); return ($("#name").attr("value") && $(&

分享一下淘宝客的入门知识

摘要: 很多朋友在做 淘宝客 的时候不知道如何入手?很多朋友在做 淘宝客 的开始不知道怎样操作,主要是不知道如何下手,但是自己又非常想在这个平台里面实现自己的额外收入.那么我们 很多朋友在做淘宝客的时候不知道如何入手?很多朋友在做淘宝客的开始不知道怎样操作,主要是不知道如何下手,但是自己又非常想在这个平台里面实现自己的额外收入.那么我们应该从什么地方开始做淘宝客呢?下面我来跟大家分享一下淘宝客的入门知识: 一.注册账号.注册账号就是你在淘宝联盟(阿里妈妈)里面注册一个一个账号,然后进入阿里妈妈的

xml-android开发小程序,入门知识

问题描述 android开发小程序,入门知识 这是一个简单的安卓浏览器,但是安装到手机后无法搜索.代码如下: <?xml version="1.0" encoding="utf-8"?> android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" >

理解JavaScript的变量的入门教程_基础知识

变量是用于存储信息的容器:   x=5; length=66.10; 还记得在学校里学过的代数吗? 当您回忆在学校学过的代数课程时,想到的很可能是:x=5, y=6, z=x+y 等等.   还记得吗,一个字母可以保存一个值(比如 5),并且可以使用上面的信息计算出 z 的值是 11.   您一定没有忘记,对吧.   这些字母称为变量,变量可用于保存值 (x=5) 或表达式 (z=x+y). JavaScript 变量 正如代数一样,JavaScript 变量用于保存值或表达式.   可以给变量

[python+nltk] 自然语言处理简单介绍和NLTK坏境配置及入门知识(一)

        本文主要是总结最近学习的论文.书籍相关知识,主要是Natural Language Pracessing(自然语言处理,简称NLP)和Python挖掘维基百科Infobox等内容的知识.         此篇文章主要参考书籍<Natural Language Processing with Python>Python自然语言处理,希望对大家有所帮助.书籍下载地址:         官方网页版书籍:http://www.nltk.org/book/         CSDN下载地

深入理解JS正则表达式---分组_基础知识

深入理解JS正则表达式---分组 之前写了一篇关于正则新手入门的文章,本以为对正则表达式相对比较了解 但是今天我又遇到了一个坑,可能是自己不够细心的原因吧,今天就着重和大家分享一下javascript正则表达式中的分组.如果你对JS正则表达式不够理解 可以点击这里了解更多. 分组在正则中用的还是比较广的,我所理解的分组 就是一对括号() ,每一对括号 就代表了一个分组,分组可以分为: •捕获性分组 •非捕获性分组 捕获性分组 捕获性分组会在 比如 match exec这样的函数中以第二项,第三项

C语言中变量与其内存地址对应的入门知识简单讲解_C 语言

先来理解理解内存空间吧.请看下图: 如上图所示,内存只不过是一个存放数据的空间,就好像我的看电影时的电影院中的座位一样.电影院中的每个座位都要编号,而我们的内存要存放各种各样的数据,当然我们要知道我们的这些数据存放在什么位置吧.所以内存也要象座位一样进行编号了,这就是我们所说的内存编址.座位可以是遵循"一个座位对应一个号码"的原则,从"第1号"开始编号.而内存则是按一个字节接着一个字节的次序进行编址,如上图所示.每个字节都有个编号,我们称之为内存地址.好了,我说了这