無標題文檔

不要轻信 PHP_SELF

开门见山,考虑下面的代码( 原文连接 有详细的解释)

<html>
    <body>
        <?php
            if (isset($_REQUEST['submitted']) && $_REQUEST['submitted'] == '1') {
                echo "Form submitted!";
            }
        ?>
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>">
            <input type="hidden" name="submitted" value="1" />
            <input type="submit" value="Submit!" />
        </form>
    </body>
</html>

看似准确无误的代码,但是暗藏着危险。让我们将其保存为 foo.php ,然后放到 PHP 环境中使用

foo.php/%22%3E%3Cscript%3Ealert('xss')%3C/script%3E%3Cfoo

访问,会发现弹出个 Javascript 的 alert -- 这很明显又是个 XSS 的注入漏洞 。究其原因,发现是在

echo $_SERVER['PHP_SELF'];

这条语句上直接输出了未过滤的值。追根数源,我们看下 PHP 手册的描述

'PHP_SELF'

The filename of the currently executing script, relative to the document root. 
For instance, $_SERVER['PHP_SELF'] in a script at the address 
http://example.com/test.php/foo.bar would be /test.php/foo.bar. The __FILE__ 
constant contains the full path and filename of the current (i.e. included) file.
If PHP is running as a command-line processor this variable contains the script 
name since PHP 4.3.0. Previously it was not available. 

原因很明确了,原来是 $_SERVER['PHP_SELF'] 虽然「看起来」是服务器提供的环境
变量,但这的确和 $_POST$_GET 一样,是可以被用户更改的。

其它类似的变量有很多,比如 $_COOKIE 等(如果用户想「把玩」他们的 cookie,那我们也是没有办法)。解决方案很简单,使用 strip_tagshtmlentities 等此类函数过滤或者转义。

echo htmlentities($_SERVER['PHP_SELF']); 

-- Split --

上述的例子让我们需要时刻保持谨慎 coding 的心态。Chris Shiflett 在他的 Blog 总结的相当直白 ,防止 XSS 的两个基本的安全思想就是

Filter input
Escape output

我将上面翻译成 「_过滤输入,转义输出_」。详细的内容,可以参考他 Blog 的 这篇文章 ,此处略。

在 Explorer6 下调试 CSS(草译)

原文连接在这里 ,主要介绍原作者的针对 Explorer6 调试 CSS 的一些经验。不过在我个人看来,这也是一般性的 CSS 调试方法。

防患于未然

坦白的讲,我每天都会话很多时间用于调试 Explorer6 的 CSS 问题上。下面是一些小 Tips 可以确保 Explorer6 最大限度的返回你期望的效果。不幸的是,并不是每个人都知道它们(译注:作者有些「危言耸听」)。

重置默认样式

重置默认样式可以最大限度的避免浏览器差异,最简单的样式重置通常可以这样写

* {
    margin: 0;
    padding: 0;
}

如果你觉得这样「太过于简单」,可以参考 YUI ResetEric Meyer's Reset

不要在同一元素上同时声明 margin/padding 的宽度

由于 Explorer6 糟糕的 盒模型 ,你必须要万分小心。如果你需要将一元素设置了宽度,注意避免再将其上设定margin、padding(左边或者右边)。我会在其上再包裹一层元素,比如 <p>、<ul>、<table>、<hr> 这样的标签。

在大多数情况下,设计师会统一同一种元素的样式,比如段落的内间距(padding)统一为 8px 到 20px(通常为 10px)

p {
    padding: 0 10px;
}

这是个非常好的定义。

另外:我一直使用像素(pixels)作为 margin 和 padding 的单位,因为如果使用 em,那么可能在使用不同的字体造成不同的宽度差异。

校验 XHTML、HTML

我已经好几次遇到这样的问题,在 Firefox 和 Safari 显示完好的页面,却在 Explorer6 下显得惨不忍睹。如果 Explorer7 也出现了这样的问题,那可能是遗失了「<」或者「>」之故。为了些可预见性的问题,其他浏览器都会注意这个问题,唯独 Explorer 。

我经常使用 Firefox 的 HTML validator 插件 验证页面代码。

保持清除浮动

总会有页面要将某个元素浮动起来,如果是定宽的那么还好办。如果是不定宽度的,那么要清除下浮动 -- 毕竟其他元素不一定都是浮动的。总之,时刻记得清除浮动是个好的习惯(译注: 也可以参看我以前的文章 )。

调试的技巧

虽然有多年针对 Explorer6 的 CSS 调试经验,一些常见的问题我知道如何去解决,但真的碰到很头痛的问题时,那时我通常会这样解决

  1. 打开电脑,载入 Explorer6 (译注:废话 -_-!)
  2. 确保安装了 IE Accessibility 工具条
  3. 点击工具条上的「编辑 CSS」
  4. 然后我开始「变魔术」

寻找错误

设定背景色

我经常会在指定的大块元素上设定个背景色

#content {
    background-color: red;
}

#sidebar {
    background-color:blue;
}

这能让我知道是哪块元素出了问题(译注:我喜欢用「red」高亮,因为好打而且显眼)。

隐藏元素

然后开始逐级的隐藏该块元素中的内容,首先是最大的块

#sidebar {
   display: none;
}

如果问题消失了,那么再逐级在块中寻找出问题的元素,比如

#sidebar .sub-item {
    display: none;
}

或者

#sidebar .sub-item .sub-sub-item {
    display: none;
}

使用这一方法,通常就能精确的定位哪个元素造成的问题(按照经验通常是 <div> 或者是 <p>)。

寻找解决方案

Explorer6 是头「烈马」,它会按照自己的规则去渲染 CSS 。当找到对应的元素后,下面有些经验式的解决方案可以参考一下(保持原作、顺便偷懒就不翻译了)

#sidebar .sub-item .sub-subitem {
    /* try setting this if it’s not already set - it sometimes works wonders */
    position: relative;

    /* display: inline often fixes the double margin float bug and */
    display: inline;
             
    /* Sometimes this just fixes problems - no idea why */
    display: inline-block;

    /* margin can be a killer so take it off completely see if the problem goes away */
    margin: 0;

    /* same as margin */
    padding: 0;

    /* Sometimes IE6 hates background colours not being declared */
    background-color: transparent;

    /* can sometimes stop columns too wide from breaking a layout */
    overflow: hidden;

    /* Sometimes forces hasLayout and fixes things */
    zoom: 1;
}

我经常会碰到改变它的 margin 和 display 就能解决问题。然后我会使用 Google 搜索网上是否有相应的 Bug 记录。

解决问题

当我找到解决该问题的办法以后,通常我会将其放到名为 ie6.css 文件中,然后只让 Explorer6 载入该 CSS 。当然,要确定该样式会覆盖原先定义的样式。

译注:当然也可以使用 CSS Hacks ,但不推荐这样做,原因之一是要「 保持 CSS 简单 」。

// 鲜果认领 BANGD5F9111B31CF304E38747370XIANGUO

常见的 XSS 注入攻击方式 Part.2

接上一期 ,这里主要考虑 CSS 注入的方式。CSS 注入主要为背景图注入和针对 Exploer 的 CSS Expression 注入。

考虑没有完全将样式过滤的情况,下面的代码即有可能成为攻击代码

<xss style="behavior: url(xss.htc);">

上面的是针对 Exploer 的 htc 注入,htc 可以认为是个脚本。

<div style="background-image: xss.jpg">

谁会知道 xss.jpg 是什么内容呢?不过很多站点统计代码也是使用了这一原理。

<div style="width: expression(alert('xss'));">

<img style="xss:expr/*xss*/ession(alert('xss'))">

exp/*<A style='noxss:noxss("*//*");xss:ex/*xss*//*/*/pression(alert("xss"))'>

针对 Exploer 的 Expression 要保持「淡定」,最好的做法就是过滤 style 属性。

如果没有将注释完全过滤充分,则又会在 Exploer 出现典型的注入漏洞

<!--[if gte IE 4]>
    <script>alert('xss');</script>
<![endif]-->

安全性问题,这个时候我反而感谢 Exploer 提供那么多的「机会」。

-- Split --

那么如何预防 XSS 注入?主要还是需要在用户数据过滤方面得考虑周全,在这里不完全总结下几个 Tips

  1. 假定所有的用户输入数据都是「邪恶」的
  2. 弱类型的脚本语言必须保证类型和期望的一致
  3. 考虑周全的正则表达式
  4. strip_tags、htmlspecialchars 这类函数很好用
  5. 外部的 Javascript 不一定就是可靠的
  6. 引号过滤必须要重点注意
  7. 除去不必要的 HTML 注释
  8. Exploer 求你放过我吧……

我的照片

嗨!我叫「明城」,八零后、码农、宁波佬,现居杭州。除了这里,同时也欢迎您关注我的 GitHubTwitterInstagram 等。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 要知道作为码农取名是件很难的事情,所以不想在取名这事情上太费心思。

作为八零后,自认为还仅存点点可能不怎么被理解的幽默感,以及对平淡生活的追求和向往。 为了避免不必要的麻烦,声明本站所输出的内容以及观点仅代表个人,不代表自己所服务公司或组织的任何立场。

如果您想联系我,可以发我邮件 `echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d`

分类

搜索

文章