安全编程-安全输入验证

在几乎所有安全的程序中,你的第一道防线就是检查你所接收到的每一条数据。如果你能不让恶意的数据进入你的程序,或者至少不在程序中处理它,你的程序在面对攻击时将更加健壮。在不得不接收输入,但是又不能相信输入的时候,最好的方法就是充分检测输入,并且确认输入的正确性,应当将输入限制在某些可接受的值范围内。

 

输入验证程序可分为2个主要部分:语法检查和语义检查。

语法检查主要检测输入的格式是否正确,其紧接着输入模块执行;

语义检查确定输入是否恰当,与业务密切相关因此通常紧挨着应用程序的逻辑部分。

 

验证各种来源的输入

不仅需要验证用户输入,而且还需要验证所有来自于软件之外的输入。这些输入应当包括下面这些内容,但不仅仅限于这些:

  •  命令行参数
  •  配置文件
  •  从数据库中检索出的数据
  •  环境变量
  •  网络服务
  •  注册表值
  •  系统性能参数
  •  临时文件

 

进行输入验证的最好方法就是根据一系列已知的正确值来验证输入。正确值输入验证法并不尝试检验某些特定的错误。通过已知正确值清单来进行检验称为白名单法。当可能输入的集合比较小的,可以选择使用间接选择来确保不能绕过白名单。

间接选择

列出一个清单,里面包含所有允许用户输入的合法有效数据,只允许用户提供该清单中的索引值。当合法值得范围不多时可以采用此方法。

下面是一个示例,说明使用间接选择防范命令行注入。

public static final String [] ALLOWED_COMMAND_ROUTINES =

    {

        "cmd",        

        "command",    

        "sh",         

        "env",

    };

    

    private static boolean isValidateCommandRoutine(String command)

    {

        Boolean isValidRoutine = false;

        for (int i=0; i<ALLOWED_COMMAND_ROUTINES.length ;i++)

        {

            if (command.equals(ALLOWED_COMMAND_ROUTINES[i]) != -1)

            {

                isValidRoutine = true;

            }

        }

        return isValidRoutine;

    }

    

    public static String[] validateCommandArray(String cmds[])

    {

        Boolean isValidRoutine = isValidateCommandRoutine(cmds[0]);

        if (isValidRoutine)

        {

            String[] validatedCmdArray = new String[cmds.length];

            for (int i=0; i<cmds.length; i++)

            {

                if ( null != cmds[i] && cmds[i].trim().length()>0)

                {

                    validatedCmdArray[i] = removeControlCharacter(cmds[i]);

                }

            }

            return validatedCmdArray;

        }

        return null;

    }

 

白名单法

当合法值的范围太广泛时,不能明确确定。在这种情况下最好的方式就是创建一个可接受输入值的白名单。与间接法不同,输入值可以以任何方式组合而成,从而使有效范围大大扩大。

例如,使用正则表示式验证电话号码

function CheckNum(telvalue){  //输入的电话号码必须为数字用户逗号分隔

          var   reg=/^[0-9,]+$/;

      if(!reg.test(telvalue)){      

        alert("电话号码只能为数字,用逗号分隔");

        return false;

      }

}

 

避免使用黑名单法。因为黑名单法只拒绝已知恶意的数据,在给定的环境下,恶意值的集合通常是难以枚举的,所以黑名单法一般是不完善的。而且随着时间的变迁原有的清单会过时,不利于应用程序的安全。

 

有效的安全输入验证可很好地防范注入问题。代码注入是一种常见的对Web应用程序的攻击和威胁。在OWASP TOP10中多年一直占据第一的位置。

OWASP对注入的定义如下:

注入攻击漏洞,例如SQLOS以及LDAP注入。这些攻击发生在当不可信的数据作为命令或者查询语句的一部分,被发送给解释器的时候。攻击者发送的恶意数据可以欺骗解释器,以执行计划外的命令或者在未被恰当授权时访问数据。


注入可分为很多类型:OS命令注入、XPath注入、LDAP注入、SQL注入、XQuery注入、SSI注入、XML注入等。


如何防止注入漏洞:

1、最佳选择是使用安全的API,完全避免使用解释器或提供参数化界面的API。但要注意有些参数化的API,比如存储过程(stored procedures),如果使用不当,仍然可以引入注入漏洞。

2、如果没法使用一个参数化的API,那么你应该使用解释器具体的escape语法来避免特殊字符。OWASPESAPI就有一些escape例程。

命令行注入

org.owasp.esapi.codecs.UnixCodec

org.owasp.esapi.codecs.WindowsCodec

XPath注入

org.owasp.esapi.tags.EncodeForXPathTag

LDAP注入

org.owasp.esapi.reference.DefaultEncoder

SQL注入

org.owasp.esapi.codecs.MySQLCodec

org.owasp.esapi.codecs.DB2Codec

org.owasp.esapi.codecs.OracleCodec

XML注入

org.owasp.esapi.codecs.XMLEntityCodec

JSON注入

org.owasp.esapi.codecs.HTMLEntityCodec

org.owasp.esapi.codecs.JavaScriptCodec 

3、使用正面的或“白名单”的具有恰当的规范化的输入验证方法同样会有助于防止注入攻击。但由于很多应用在输入中需要特殊字符,这一方法不是完整的防护方法。OWASPESAPI中包含一个白名单输入验证例程的扩展库。

你可能感兴趣的:(OWASP,安全编程)