Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1202845
  • 博文数量: 272
  • 博客积分: 3899
  • 博客等级: 中校
  • 技术积分: 4734
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-15 14:53
文章分类

全部博文(272)

文章存档

2012年(272)

分类: Python/Ruby

2012-06-26 11:24:12

写WEB应用经常会用到各种各样的编码,其中HtmlEncode又和防范XSS关系很大,如果正确的使用了编码,就会让脚本跑不起来了。

Apache Common LangStringEscapeUtil里,提供了许多escape的函数

参考如下 example(来自java2s):

import org.apache.commons.lang.StringEscapeUtils;

public class StringUtilsEscapeExampleV1 {

  public static void main(String args[]) {
    String unescapedJava = "Are you for real?";
    System.err.println(
      StringEscapeUtils.escapeJava(unescapedJava));

    String unescapedJavaScript = "What's in a name?";
    System.err.println(
      StringEscapeUtils.escapeJavaScript(unescapedJavaScript));

    String unescapedSql = "Mc'Williams";
    System.err.println(
      StringEscapeUtils.escapeSql(unescapedSql));

    String unescapedXML = "";
    System.err.println(
      StringEscapeUtils.escapeXml(unescapedXML));

    String unescapedHTML = "";
    System.err.println(
      StringEscapeUtils.escapeHtml(unescapedHTML));

  }
}

编码的规范有很多,以上只是一种用的比较多的应用。

在W3C中,有两种不同的Character Encoding 方式



一种是

Numeric character references

编码方式如下:
  • å (in decimal) represents the letter "a" with a small circle above it (used, for example, in Norwegian).
  • å (in hexadecimal) represents the same character.
  • å (in hexadecimal) represents the same character as well.
  • И (in decimal) represents the Cyrillic capital letter "I".
  • 水 (in hexadecimal) represents the Chinese character for water.


另一种是:

Character entity references

编码方式如下:
  • "<" represents the < sign.
  • ">" represents the > sign.
  • "&" represents the & sign.
  • "" represents the " mark.
效果实际上是一样的,且都有一张非常长的表来完整编码许多字符。



我写了一个test case如下:

numeric link
entities link




可以看到实际上在浏览器中都能正常解析出来。


从安全的角度考虑,我们可能需要更加严格的HtmlEncode

可以参考OWASP上的一个项目:

这个项目支持多种不同语言进行字符编码。

使用了白名单的思想。比如:
function HtmlEncode($str, $default)
{
    if($str == null || $str.length == 0)
    {
        $str = ($default == null ? '' : $default);
    }
    
    $out = '';
    $len = $str.length;
    
    // Allow: a-z A-Z 0-9 SPACE , .
    // Allow (dec): 97-122 65-90 48-57 32 44 46

    
    for($cnt = 0; $cnt < $len; $cnt++)
    {
        $c = $str.charCodeAt($cnt);
        if( ($c >= 97 && $c <= 122) ||
            ($c >= 65 && $c <= 90 ) ||
            ($c >= 48 && $c <= 57 ) ||
            $c == 32 || $c == 44 || $c == 46 )
        {
            $out += $str.charAt($cnt);
        }
        else
        {
            $out += '&#' + $c + ';';
        }
    }
    
    return $out;
}

仅仅允许字母、数字、空格、英文逗号、点。

其他的所有全部encoding。

为什么需要这么严格?因为今天正好碰到了这样一个case,

类似如下的写法:

$var)" >test

其中$var 是输出的变量且用户可以控制,那么仅仅编码常见的单引号、双引号、尖括号等是没用的,攻击者可以如下构造一个XSS:

);alert(/XSS/);()" >test

所以为了抵御未知攻击,我们应该尽量使用白名单的方式。

上面列出的OWASP的encoding项目,还针对不同的编码方式实现了不同的编码,比如在JS中的编码就和htmlencode不同。
阅读(1605) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~