在PHP中将utf-8字符列入白名单的最有效方法是什么?

时间:2011-02-22 04:55:55

标签: php regex security utf-8 whitelist

我的目标是通过为从客户端收到的任何和所有POST数据创建允许字符的严格白名单来保护我的网站免受攻击。

当保持ASCII字符时,这是一块蛋糕。类似的东西:

if(preg_match('/[^aA-zZ0-9]/', $stringToTest))
{
   // Battle stations!!
}

但是,我需要能够允许任何和所有utf-8字符,尤其是日语,中文和韩语等亚洲字符集。但我不想排除任何有古怪字符的人,比如阿拉伯语或俄语,或其他什么。一个世界,一个爱! ;)

我如何允许人们输入他们母语的字符,同时排除邪恶脚本中使用的恶意,如*,?,尖括号等?

4 个答案:

答案 0 :(得分:4)

\w将为您提供单词字符(字母,数字和下划线),这可能是您在\s之后的空格。

e.g。

if(preg_match('/[\w\s]/', $stringToTest))
{
   // Battle stations!!
}

regular-expressions.info是这个内容的绝佳参考 - herehere是几个相关页面:)

编辑:需要更多说明,抱歉!

这是我通常用于CJK的内容:

function get_CJK_ranges() {

    return array(
                "[\x{2E80}-\x{2EFF}]",      # CJK Radicals Supplement
                "[\x{2F00}-\x{2FDF}]",      # Kangxi Radicals
                "[\x{2FF0}-\x{2FFF}]",      # Ideographic Description Characters
                "[\x{3000}-\x{303F}]",      # CJK Symbols and Punctuation
                "[\x{3040}-\x{309F}]",      # Hiragana
                "[\x{30A0}-\x{30FF}]",      # Katakana
                "[\x{3100}-\x{312F}]",      # Bopomofo
                "[\x{3130}-\x{318F}]",      # Hangul Compatibility Jamo
                "[\x{3190}-\x{319F}]",      # Kanbun
                "[\x{31A0}-\x{31BF}]",      # Bopomofo Extended
                "[\x{31F0}-\x{31FF}]",      # Katakana Phonetic Extensions
                "[\x{3200}-\x{32FF}]",      # Enclosed CJK Letters and Months
                "[\x{3300}-\x{33FF}]",      # CJK Compatibility
                "[\x{3400}-\x{4DBF}]",      # CJK Unified Ideographs Extension A
                "[\x{4DC0}-\x{4DFF}]",      # Yijing Hexagram Symbols
                "[\x{4E00}-\x{9FFF}]",      # CJK Unified Ideographs
                "[\x{A000}-\x{A48F}]",      # Yi Syllables
                "[\x{A490}-\x{A4CF}]",      # Yi Radicals
                "[\x{AC00}-\x{D7AF}]",      # Hangul Syllables
                "[\x{F900}-\x{FAFF}]",      # CJK Compatibility Ideographs
                "[\x{FE30}-\x{FE4F}]",      # CJK Compatibility Forms
                "[\x{1D300}-\x{1D35F}]",    # Tai Xuan Jing Symbols
                "[\x{20000}-\x{2A6DF}]",    # CJK Unified Ideographs Extension B
                "[\x{2F800}-\x{2FA1F}]"     # CJK Compatibility Ideographs Supplement
    );

}

function contains_CJK($string) {
    $regex = '/'.implode('|',get_CJK_ranges()).'/u';
    return preg_match($regex,$string);
}

要获得逃避和其他黑帽子的问题,请使用:

/[^\p{Punctuation}]/(== /[^\p{P}]/

/[^\32-\151]/(== /[^!-~]/

another good link

答案 1 :(得分:2)

对于某些事情你可以进行base64编码,但是我必须删除一些功能,因为这样做是不可行的,因为保持所有字符看起来更重要,而且现在肯定不值得再花时间了。

...

在说过我遇到过这个问题之后,如果你想要一个通用的功能,那么这个问题似乎就会变成效率,但这不是一个大问题(中文,俄文和希腊文可能有单独的网页等)

http://www.php.net/manual/en/regexp.reference.unicode.php

答案 2 :(得分:0)

尝试反转测试 - 使用黑名单而不是白名单。 e.g。

if(preg_match('/[\*\?<>]/', $stringToTest))
{
    // Battle stations!!
}

正则表达式可能不太正确,但你明白了。

答案 3 :(得分:0)

我怀疑你可以用这种方式保护任何东西 您只会为公平用户提出复杂的问题,但不要阻止恶意用户。

我会退出一个不允许我输入问号或引号或电子邮件的网站。
简单的点肯定是“邪恶剧本中使用的恶意”之一。但任何没有它的消息都会显得很难看。

虽然SQL注入只能使用字母字符来完成。

我认为这种“保护”没有任何意义。