在(一),(二)前两部分文章中,我们介绍了攻击者如何通过SQL注入攻击来利用Web应用程序的漏洞以及SQL注入攻击的方法。本文我们将介绍抵御该攻击的措施。 防御措施:保证应用程序编码的安全 安全的编码技术可以清除造成SQL注入攻击的漏洞。下面说的是Web应用程序安全编码的三个基本方法。
方法一:输入验证 在Web应用程序这一层防止SQL注入最常见的方法是使用输入验证。无论是何种语言或平台,这种方法都很有用。其实质就是在验证用户输入的大小和类型前,不对其采取行动。如果你期望用户输入的是数字,就不要接受非数字的东西。
例如,下面的URL: wangzhan.com/user……
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
在(一),(二)前两部分文章中,我们介绍了攻击者如何通过SQL注入攻击来利用Web应用程序的漏洞以及SQL注入攻击的方法。本文我们将介绍抵御该攻击的措施。
防御措施:保证应用程序编码的安全
安全的编码技术可以清除造成SQL注入攻击的漏洞。下面说的是Web应用程序安全编码的三个基本方法。
方法一:输入验证
在Web应用程序这一层防止SQL注入最常见的方法是使用输入验证。无论是何种语言或平台,这种方法都很有用。其实质就是在验证用户输入的大小和类型前,不对其采取行动。如果你期望用户输入的是数字,就不要接受非数字的东西。
例如,下面的URL:
wangzhan.com/userdetail.asp?userid=9899
很明显,在这个GET请求中,我们期望输入一个整数。一个简单的类型检查会告诉我们这是不是一个合法的字符,从而确保应用程序不会处理非数字值的输入。
if (is_numeric($userid)){}
此外,如果用户的ID总是四个字符的长度,我们就可以进一步采取措施,除了使用常规的表达式来执行整型检查,还可以强化边界检查。
if (preg_match(‘d{4}’, $string)) {}
在对待如何验证用户输入值的这个问题上,我们仅受到自己创造力的限制。这里的关键是验证由用户发送并由系统使用的每一个值。
执行类型检查的另外一种方法是通过ASCII字符。用户名一般是由字母和数字组成的,所以我们不希望看到类似“@”、“;”之类的字符。因而,我们可以解析用户名变量,看看是否存在着不属于48-57,65-90,97-122的任何ASCII字符。在这个范围之外的任何ASCII字符对于用户名变量来说,都是不合法的,应当拒绝接受。这就是所谓白名单的一个例子。
知道白名单和黑名单的区别非常重要。白名单仅接受已知为安全的值或字符,如字母和数字。而黑名单则会阻止或不接受已知为恶意的字符。
方法二:规避技术
到目前为止,类型检查和边界检查似乎很容易,但并非在检查所有的数据类型时都会这么简单。许多情况下,我们还会使用VARCHAR数据类型(VARCHAR是一种比CHAR更加灵活的数据类型,同样用于表示字符数据,但是VARCHAR可以保存可变长度的字符串。)此类型有可能包含危险字符。这在备注字段和其它的长表单文本字段中很常见。
在这种情况下,我们可以利用一种称为规避的技术来确保变量的内容绝对不会被解析为SQL语句的一部分。
请看下面这个例子中的请求:
wangzhan.com/comment.asp?msg=I’m zhangsan.
在这个例子中,有一个撇号(’),这是一种常被认为是恶意字符的字符(请参考上一篇文章提到的撇号),我们并不希望排除它,因为此处它的用法是合法的,我们也不希望拒绝这个消息。
例如,在PHP中,我们可以使用mysql_real_escape_string函数:
mysql_real_escape_string($GET[‘msg’]);
这就不会导致安全问题,而是安全地解决了撇号问题,使其不能用于任何MySQL查询中:
msg=“Hello I’m zhangsan”
同样地,在微软的.NET架构中,设计者常用REPLACE来保证字符串的安全。在下面的例子中,REPLACE函数将撇号(’)放在引号中,使其成为一种安全字符:
sql = replace(str, “’“, “’“)
方法三:参数化查询
防止SQL注入的第三种方法是一种称为参数化查询的技术。这种方法非常有效,因为它可以非常严密地控制SQL语句的组成结构。此方法在将对SQL语句的任何重要变更交给SQL服务器处理之前就拒绝其操作。
下面的Java例子中,我们简单地将参数添加到已经构建的静态查询中。首先,我们使用问号作为变量建立了真实的SELECT语句:
String query = “SELECT account_balance FROM user_data WHERE user_name = ? “;
下一步,我们调用prepareStatement函数:
PreparedStatement pstmt = connection.prepareStatement( query );
然后,在查询中我们将字符串“custname”指派给变量:
pstmt.setString( 1, custname);
最后,我们执行查询,并将结果存储在一个变量中:
ResultSet results = pstmt.executeQuery( );
通过使用这种方法,我们能够确保在附加的恶意查询或参数被发送给数据库之前,不会被添加到查询中。注意,应当像前面所讨论的那样来验证“custname”变量,因为它是不受信任的用户输入。
在下一篇文章中,我们将讨论另外一种策略:使用存储SQL过程。
相关推荐
-
John Pescatore:规避技术助力应对高级针对性攻击
高级有针对性攻击的快速发展正在推动企业更加关注于快速事件检测和响应,而不是防御,是这样吗?
-
John Pescatore:规避技术助力应对高级针对性攻击
高级有针对性攻击的快速发展正在推动企业更加关注于快速事件检测和响应,而不是防御,是这样吗?
-
如何斩断SQL注入式攻击的疯狂魔掌?
近年来,SQL注入式攻击一直如幽灵般困扰着众多企业。从八月中旬以来,新一轮的大规模SQL注入式攻击袭掠了大量的网站,连苹果公司的网站也未能幸免。
-
什么工具有助于验证网站上的表单输入?
你可能知道,输入验证能确保程序在干净和可用的数据上操作。有一些常用的工具能定位容易受输入验证攻击的网页。