安全编程-安全输入验证
2014-10-17 17:19
190 查看
在几乎所有安全的程序中,你的第一道防线就是检查你所接收到的每一条数据。如果你能不让恶意的数据进入你的程序,或者至少不在程序中处理它,你的程序在面对攻击时将更加健壮。在不得不接收输入,但是又不能相信输入的时候,最好的方法就是充分检测输入,并且确认输入的正确性,应当将输入限制在某些可接受的值范围内。
输入验证程序可分为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对注入的定义如下:
注入攻击漏洞,例如SQL,OS以及LDAP注入。这些攻击发生在当不可信的数据作为命令或者查询语句的一部分,被发送给解释器的时候。攻击者发送的恶意数据可以欺骗解释器,以执行计划外的命令或者在未被恰当授权时访问数据。
注入可分为很多类型:OS命令注入、XPath注入、LDAP注入、SQL注入、XQuery注入、SSI注入、XML注入等。
如何防止注入漏洞:
1、最佳选择是使用安全的API,完全避免使用解释器或提供参数化界面的API。但要注意有些参数化的API,比如存储过程(stored procedures),如果使用不当,仍然可以引入注入漏洞。
2、如果没法使用一个参数化的API,那么你应该使用解释器具体的escape语法来避免特殊字符。OWASP的ESAPI就有一些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、使用正面的或“白名单”的具有恰当的规范化的输入验证方法同样会有助于防止注入攻击。但由于很多应用在输入中需要特殊字符,这一方法不是完整的防护方法。OWASP的ESAPI中包含一个白名单输入验证例程的扩展库。
输入验证程序可分为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对注入的定义如下:
注入攻击漏洞,例如SQL,OS以及LDAP注入。这些攻击发生在当不可信的数据作为命令或者查询语句的一部分,被发送给解释器的时候。攻击者发送的恶意数据可以欺骗解释器,以执行计划外的命令或者在未被恰当授权时访问数据。
注入可分为很多类型:OS命令注入、XPath注入、LDAP注入、SQL注入、XQuery注入、SSI注入、XML注入等。
如何防止注入漏洞:
1、最佳选择是使用安全的API,完全避免使用解释器或提供参数化界面的API。但要注意有些参数化的API,比如存储过程(stored procedures),如果使用不当,仍然可以引入注入漏洞。
2、如果没法使用一个参数化的API,那么你应该使用解释器具体的escape语法来避免特殊字符。OWASP的ESAPI就有一些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、使用正面的或“白名单”的具有恰当的规范化的输入验证方法同样会有助于防止注入攻击。但由于很多应用在输入中需要特殊字符,这一方法不是完整的防护方法。OWASP的ESAPI中包含一个白名单输入验证例程的扩展库。
相关文章推荐
- 安全编程: 验证输入
- 安全编程: 验证输入
- 安全编程: 验证输入--接收用户数据的最佳实践
- 安全编程: 验证输入
- VC++网络安全编程范例(8)-摘要签名和验证编程实现
- VC++网络安全编程范例(1)--数字证书有效期验证--学习笔记
- 安全编程: 警惕输入
- 对用户输入的数据进行安全验证(Safe-Handling User Input)
- .NET数据库编程求索之路--10.使用EF实现(划分输入验证层)
- PHP安全编程:过滤用户输入
- 安全编程: 警惕输入--找出并保护程序的入口
- PHP安全编程之过滤用户输入
- 如果做到安全的系统之验证用户输入.
- C Primer Plus 第8章 字符输入/输出和验证输入 编程练习
- PHP安全编程:过滤用户输入
- 请求验证过程检测到有潜在危险的客户端输入值,对请求的处理已经中止。该值可能指示存在危及应用程序安全的尝试,如跨站点脚本攻击。若要允许页面重写应用程序请求验证设置
- WEB编程之验证Web 窗体页中的用户输入 @Lennon
- 对用户的输入的数据进行安全验证
- 挑战编程技能之验证输入
- 第7章 数据的安全传输和身份验证 ——SSL和HTTPS编程