在表单的输入过滤和验证中列入黑名单与白名单

时间:2010-08-24 18:14:26

标签: filter validation whitelist blacklist

这是清理来自用户的输入的首选方法吗?

谢谢你!

7 个答案:

答案 0 :(得分:3)

最好的方法是使用存储过程或参数化查询。白名单是一种额外的技术,可以在它们到达服务器之前阻止任何注入,但不应该用作主要防御。黑名单通常是一个坏主意,因为通常无法过滤掉所有恶意输入。

顺便说一下,这个答案正在考虑你的意思是在防止sql注入方面进行消毒。

答案 1 :(得分:3)

只要可行,

WL就是针对BL的最佳做法

原因很简单:您无法合理安全地列举不允许的内容,攻击者总能找到一种您没有想到的方式。如果可以的话,可以说肯定是什么,它更简单,更安全!

答案 2 :(得分:2)

我认为白名单是理想的方法,但我从未遇到真正的白名单HTML表单验证。例如,这是一个symfony 1.x表单,其中包含documentation

的验证
class ContactForm extends sfForm  
{  
  protected static $subjects = array('Subject A', 'Subject B', 'Subject C');  

  public function configure()  
  {  
    $this->setWidgets(array(  
      'name'    => new sfWidgetFormInput(),  
      'email'   => new sfWidgetFormInput(),  
      'subject' => new sfWidgetFormSelect(array('choices' => self::$subjects)),  
      'message' => new sfWidgetFormTextarea(),  
    ));  
    $this->widgetSchema->setNameFormat('contact[%s]');  

    $this->setValidators(array(  
      'name'    => new sfValidatorString(array('required' => false)),  
      'email'   => new sfValidatorEmail(),  
      'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))),  
      'message' => new sfValidatorString(array('min_length' => 4)),  
    ));  
  }  
} 

您看不到的内容,即它接受没有验证设置的新输入,并且不检查表单中未注册的输入的存在。所以这是一个黑名单输入验证。通过白名单,您将首先定义一个输入验证器,然后才将输入字段绑定到该验证器。通过像这样的黑名单方法,很容易忘记在输入中添加验证器,并且没有它就可以完美地工作,所以你不会注意到漏洞,只有在为时已晚......

假设的白名单方法看起来像这样:

class ContactController {
    /**
    * @input("name", type = "string", singleLine = true, required = false)
    * @input("email", type = "email")
    * @input("subject", type = "string", alternatives = ['Subject A', 'Subject B', 'Subject C'])
    * @input("message", type = "string", range = [4,])
    */
    public function post(Inputs $inputs){
        //automatically validates inputs
        //throws error when an input is not on the list
        //throws error when an input has invalid value
    }
}

/**
* @controller(ContactController)
* @method(post)
*/
class ContactForm extends sfFormX {

  public function configure(InputsMeta $inputs)  
  {
    //automatically binds the form to the input list of the @controller.@method
    //throws error when the @controller.@method.@input is not defined for a widget
    $this->addWidgets(
      new sfWidgetFormInput($inputs->name),  
      new sfWidgetFormInput($inputs->email),  
      new sfWidgetFormSelect($inputs->subject),  
      new sfWidgetFormTextarea($inputs->message)
    );
    $this->widgetSchema->setNameFormat('contact[%s]');  
  }  
}

答案 3 :(得分:1)

就个人而言,我会衡量允许或不允许的角色的数量并从那里开始。如果允许的字符数多于不允许的字符数,则为黑名单。其他白名单。我不相信有任何“标准”表明你应该以某种方式做到这一点。

顺便说一下,这个答案是假设您想要将输入限制在表单字段中,例如电话号码或姓名:) @posterBelow

答案 4 :(得分:1)

让我用更多的问题和答案解释你的问题。

  1. 黑名单VS白名单限制

    我。黑名单XSS和SQL注入处理根据负输入列表验证所需的输入。基本上,人们会编制一个包含所有负面或不良条件的列表,并验证收到的输入不是坏的或负面的条件之一。

    II。白名单XSS和SQL注入处理根据可能的正确输入列表验证所需的输入。为此,我们将编译所有正/好输入值/条件的列表,并验证收到的输入是否是正确条件之一。

  2. 哪一个更好?

    我。攻击者将使用任何可能的方法来访问您的应用程序。这包括尝试所有类型的负面或不良条件,各种编码方法以及将恶意输入数据附加到有效数据。你认为你能想到可能发生的每一种可能的不良排列吗?

    II。白名单是验证输入的最佳方式。你会确切地知道什么是期望的,并且没有接受任何不良类型。通常,创建白名单的最佳方法是使用正则表达式。使用正则表达式是抽象白名单的好方法,而不是手动列出每个可能的正确值。

    建立一个好的正则表达式。仅仅因为你使用正则表达式并不意味着不接受错误的输入。确保测试正则表达式,并且正则表达式无法接受无效输入。

答案 5 :(得分:1)

作为一般规则,最好使用白名单验证,因为它更容易接受您知道应该去那里的字符,例如,如果您有一个用户输入他/她的电话号码的字段,您可以只进行正则表达式检查收到的值只是数字,丢弃其他所有内容,只存储数字。请注意,您还应该继续验证结果数字。黑名单验证较弱,因为技术娴熟的攻击者可以逃避验证功能或发送您的功能未预期的值,来自OWASP“使用黑名单清理”:

  

消除或翻译字符(例如HTML实体或删除引号)以使输入“安全”。与黑名单一样,这种方法需要维护并且通常是不完整的。由于大多数字段都具有特定的语法,因此简单,快速和更安全地简单地验证单个正确的肯定测试,而不是尝试包括针对所有当前和未来攻击的复杂和缓慢的清理例程。

意识到这种验证只是防御攻击的第一道防线。对于XSS,你应该总是“逃离”你的输出,这样你就可以打印任何所需的字符,但它们被转义意味着它们被改为HTML实体,因此浏览器知道它的数据,而不是解析器应该解释的东西,从而有效地关闭所有XSS攻击。对于SQL注入在存储之前转义所有数据,尝试永远不要使用动态查询,因为它们是最容易利用的查询类型。尝试使用参数化存储过程。还要记住使用与连接相关的连接。如果连接只需要读取数据,请创建仅具有“读取”权限的数据库帐户,这主要取决于用户的角色。有关详细信息,请查看从中提取此信息的链接:

Data Validation OWASP

Guide to SQL Injection OWASP

答案 6 :(得分:0)

答案通常是,这取决于。

对于具有明确定义参数的输入(比如相当于下拉菜单),我会将这些选项列入白名单,并忽略任何不属于这些选项的内容。

对于自由文本输入,它要困难得多。我订阅了一个思想学校,你应该尽可能地过滤它,以便尽可能安全(转义HTML等)。其他一些建议是明确禁止任何无效输入 - 但是,虽然这可以防止攻击,但它也可能影响真正用户的可用性。

我认为这只是找到适合你的混合物的一个例子。我想不出任何一种适用于所有可能性的解决方案。主要取决于您的用户群。