Sophie

Sophie

distrib > Mandriva > 2008.1 > x86_64 > by-pkgid > 05cd670d8a02b2b4a0ffb1756f2e8308 > files > 11034

php-manual-zh-5.2.4-1mdv2008.1.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML
><HEAD
><TITLE
>使用 Register Globals</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
REL="HOME"
TITLE="PHP 手册"
HREF="index.html"><LINK
REL="UP"
TITLE="安全"
HREF="security.html"><LINK
REL="PREVIOUS"
TITLE="错误报告"
HREF="security.errors.html"><LINK
REL="NEXT"
TITLE="用户提交的数据"
HREF="security.variables.html"><META
HTTP-EQUIV="Content-type"
CONTENT="text/html; charset=UTF-8"></HEAD
><BODY
CLASS="chapter"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>PHP 手册</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="security.errors.html"
ACCESSKEY="P"
>上一页</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="security.variables.html"
ACCESSKEY="N"
>下一页</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="chapter"
><H1
><A
NAME="security.globals"
>章 29. 使用 Register Globals</A
></H1
><P
>&#13;    可能 PHP 中最具争议的变化就是从 PHP <A
HREF="http://www.php.net/releases/4_2_0.php"
TARGET="_top"
>4.2.0</A
>
    版开始配置文件中 <A
HREF="ini.core.html#ini.register-globals"
>register_globals</A
>
    的默认值从 on 改为 off 了。对此选项的依赖是如此普遍以至于很多人根本不知道它的存在而以为
    PHP 本来就是这么工作的。本节会解释用这个指令如何写出不安全的代码,但要知道这个指令本身没有不安全的地方,误用才会。
   </P
><P
>&#13;    当 register_globals 打开以后,各种变量都被注入代码,例如来自 HTML
    表单的请求变量。再加上 PHP 在使用变量之前是无需进行初始化的,这就使得更容易写出不安全的代码。这是个很艰难的抉择,但
    PHP 社区还是决定默认关闭此选项。当打开时,人们使用变量时确实不知道变量是哪里来的,只能想当然。但是
    register_globals 的关闭改变了这种代码内部变量和客户端发送的变量混杂在一起的糟糕情况。下面举一个错误使用 register_globals 的例子:
   </P
><P
>&#13;    <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6751"
></A
><P
><B
>例 29-1. 错误使用 register_globals = on 的例子</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#FF8000">// 当用户合法的时候,赋值 $authorized = true<br /></font><font color="#007700">if (</font><font color="#0000BB">authenticated_user</font><font color="#007700">()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#0000BB">$authorized </font><font color="#007700">= </font><font color="#0000BB">true</font><font color="#007700">;<br />}<br /><br /></font><font color="#FF8000">// 由于并没有事先把 $authorized 初始化为 false,<br />// 当 register_globals 打开时,可能通过GET auth.php?authorized=1 来定义该变量值<br />// 所以任何人都可以绕过身份验证<br /></font><font color="#007700">if (</font><font color="#0000BB">$authorized</font><font color="#007700">) {<br />&nbsp;&nbsp;&nbsp;&nbsp;include </font><font color="#DD0000">"/highly/sensitive/data.php"</font><font color="#007700">;<br />}<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
   </P
><P
>&#13;    当 register_globals = on 的时候,上面的代码就会有危险了。如果是
    off,<CODE
CLASS="varname"
>$authorized</CODE
> 就不能通过如 URL
    请求等方式来改变,这样就好多了,尽管初始化变量是一个良好的编程习惯。比如说,如果在上面的代码执行之前加入
    <TT
CLASS="literal"
>$authorized = false</TT
> 的话,无论 register_globals 是 on 还是
    off 都可以,因为用户状态被初始化为未经认证。
   </P
><P
>&#13;    另一个例子是关于<A
HREF="ref.session.html"
>会话</A
>的。当 register_globals = on
    的时候,<CODE
CLASS="varname"
>$username</CODE
> 也可以用在下面的代码中,但要意识到
    <CODE
CLASS="varname"
>$username</CODE
> 也可能会从其它途径进来,比如说通过 URL 的 GET。
   </P
><P
>&#13;    <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6762"
></A
><P
><B
>例 29-2. 使用会话时同时兼容 register_globals on 和 off 的例子</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#FF8000">// 我们不知道 $username 的来源,但很清楚 $_SESSION 是<br />// 来源于会话数据<br /></font><font color="#007700">if (isset(</font><font color="#0000BB">$_SESSION</font><font color="#007700">[</font><font color="#DD0000">'username'</font><font color="#007700">])) {<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;echo </font><font color="#DD0000">"Hello &lt;b&gt;</font><font color="#007700">{</font><font color="#DD0000">$_SESSION</font><font color="#007700">[</font><font color="#DD0000">'username'</font><font color="#007700">]}</font><font color="#DD0000">&lt;/b&gt;"</font><font color="#007700">;<br /><br />} else {<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;echo </font><font color="#DD0000">"Hello &lt;b&gt;Guest&lt;/b&gt;&lt;br /&gt;"</font><font color="#007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;echo </font><font color="#DD0000">"Would you like to login?"</font><font color="#007700">;<br /><br />}<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
   </P
><P
>&#13;    采取相应的预防措施以便在伪造变量输入的时候给予警告是完全有可能的。如果事先确切知道变量是哪里来的,就可以检查所提交的数据是否是从不正当的表单提交而来。不过这不能保证变量未被伪造,这需要攻击者去猜测应该怎样去伪造。如果不在乎请求数据来源的话,可以使用
    <CODE
CLASS="varname"
>$_REQUEST</CODE
> 数组,它包括了 GET、POST 和 COOKIE
    的所有数据。详情可参见本手册的<A
HREF="language.variables.external.html"
>来自 PHP 之外的变量</A
>。
   </P
><P
>&#13;    <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6769"
></A
><P
><B
>例 29-3. 探测有害变量</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /></font><font color="#007700">if (isset(</font><font color="#0000BB">$_COOKIE</font><font color="#007700">[</font><font color="#DD0000">'MAGIC_COOKIE'</font><font color="#007700">])) {<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#FF8000">// MAGIC_COOKIE 来自 cookie<br />&nbsp;&nbsp;&nbsp;&nbsp;// 这样做是确保是来自 cookie 的数据<br /><br /></font><font color="#007700">} elseif (isset(</font><font color="#0000BB">$_GET</font><font color="#007700">[</font><font color="#DD0000">'MAGIC_COOKIE'</font><font color="#007700">]) || isset(</font><font color="#0000BB">$_POST</font><font color="#007700">[</font><font color="#DD0000">'MAGIC_COOKIE'</font><font color="#007700">])) {<br /><br />&nbsp;&nbsp;&nbsp;</font><font color="#0000BB">mail</font><font color="#007700">(</font><font color="#DD0000">"admin@example.com"</font><font color="#007700">, </font><font color="#DD0000">"Possible breakin attempt"</font><font color="#007700">, </font><font color="#0000BB">$_SERVER</font><font color="#007700">[</font><font color="#DD0000">'REMOTE_ADDR'</font><font color="#007700">]);<br />&nbsp;&nbsp;&nbsp;echo </font><font color="#DD0000">"Security violation, admin has been alerted."</font><font color="#007700">;<br />&nbsp;&nbsp;&nbsp;exit;<br /><br />} else {<br /><br />&nbsp;&nbsp;&nbsp;</font><font color="#FF8000">// 这一次请求中并没有设置 MAGIC_COOKIE 变量<br /><br /></font><font color="#007700">}<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
   </P
><P
>&#13;    当然,单纯地关闭 register_globals
    并不代表所有的代码都安全了。对于每一段提交上来的数据,都要对其进行具体的检查。永远要验证用户数据和对变量进行初始化!把
    <A
HREF="function.error-reporting.html"
><B
CLASS="function"
>error_reporting()</B
></A
> 设为
    <TT
CLASS="constant"
><B
>E_NOTICE</B
></TT
> 级别可以检查未初始化的变量。
   </P
><P
>&#13;    更多关于模拟 register_globals 为 on 或 off 的信息,请见此
    <A
HREF="faq.misc.html#faq.misc.registerglobals"
>FAQ</A
>。
   </P
><DIV
CLASS="note"
><BLOCKQUOTE
CLASS="note"
><P
><B
>Superglobals 可用性说明: </B
>自 PHP 4.1.0 起,可以使用超全局数组变量例如
<CODE
CLASS="varname"
>$_GET</CODE
>,<CODE
CLASS="varname"
>$_POST</CODE
>
和 <CODE
CLASS="varname"
>$_SERVER</CODE
> 等等。更多信息请阅读手册中的 <A
HREF="language.variables.predefined.html"
>superglobals</A
>。</P
></BLOCKQUOTE
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="security.errors.html"
ACCESSKEY="P"
>上一页</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>起始页</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="security.variables.html"
ACCESSKEY="N"
>下一页</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>错误报告</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="security.html"
ACCESSKEY="U"
>上一级</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>用户提交的数据</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>