如何有效防范SQL注入

发布于 2017-07-10 13:12:14

我们作为中小企业没有专门的安全人员,如何进行网站防护或安全自检?

查看更多

关注者
0
被浏览
3.7k
8 个回答
龟速船长
龟速船长 2017-01-16
贫困潦倒的php开发

建议如下:
1、使用安全的API
2、对输入的特殊字符进行Escape转义处理
3、使用白名单来规范化输入验证方法
4、对客户端输入进行控制,不允许输入SQL注入相关的特殊字符
5、服务器端在提交数据库进行SQL查询之前,对特殊字符进行过滤、转义、替换、删除。

疯狂的苹果吃吃吃啊,哈哈哈哈
富可敌国的前端开发

建议如下:
1、使用安全的API

2、对输入的特殊字符进行Escape转义处理

3、使用白名单来规范化输入验证方法

4、对客户端输入进行控制,不允许输入SQL注入相关的特殊字符
5、服务器端在提交数据库进行SQL查询之前,对特殊字符进行过滤、转义、替换、删除。

企鹅三兄弟
企鹅三兄弟 2017-01-30
小白一个

1.PreparedStatement 2.使用正则表达式过滤传入的参数 3.字符串过滤 4.jsp中调用该函数检查是否包函非法字符

进击的蜜蜂
进击的蜜蜂 2017-08-23
嗡嗡嗡

根本上杜绝的方案太多太简单了,SQL注入这种攻击手段说白了和直接把门踹开偷东西一样Low,这么多年一爆再爆我也很震精。不过想想其实都是一群小白拿着几十年前的小白写的东西改改用才会这样的。有人非说我没回答问题,OK,根本的手段就是参数化查询或者做词法分析。@pansz 的答案的确是说到了一个关键,也就是如果支持文本式的指令,那这事儿是没有办法杜绝的,只能在外面套上一个壳,也就是词法分析。但是现代数据库却不是只提供了SQL文本查询,参数化查询也是标准API之一,当然还有存储过程,这些高级的API都可以有效的杜绝SQL注入这种问题。在MySQL都支持存储过程的今天,还有这么多注入漏洞实在是让人费解。不使用支持SQL的数据库过于偏颇了,几乎所有的关系型数据库都支持SQL查询,但也提供了安全的查询方式。

bestzzz
bestzzz 2017-05-23
暂时没什么可以说的

一、SQL注入简介

SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。

二、SQL注入攻击的总体思路

1.寻找到SQL注入的位置

2.判断服务器类型和后台数据库类型

3.针对不通的服务器和数据库特点进行SQL注入攻击

三、SQL注入攻击实例

比如在一个登录界面,要求输入用户名和密码:

可以这样输入实现免帐号登录:

用户名: ‘or 1 = 1 –

密 码:

点登陆,如若没有做特殊处理,那么这个非法用户就很得意的登陆进去了.(当然现在的有些语言的数据库API已经处理了这些问题)

这是为什么呢? 下面我们分析一下:

从理论上说,后台认证程序中会有如下的SQL语句:

String sql = "select * from user_table where username=

' "+userName+" ' and password=' "+password+" '";

当输入了上面的用户名和密码,上面的SQL语句变成:

SELECT * FROM user_table WHERE username=

'’or 1 = 1 -- and password='’

分析SQL语句:

条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;

然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。

这还是比较温柔的,如果是执行

SELECT * FROM user_table WHERE

username='' ;DROP DATABASE (DB Name) --' and password=''

….其后果可想而知…

四、应对方法

下面我针对JSP,说一下应对方法:

1.(简单又有效的方法)PreparedStatement

采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。

使用好处:

(1).代码的可读性和可维护性.

(2).PreparedStatement尽最大可能提高性能.

(3).最重要的一点是极大地提高了安全性.

原理:

sql注入只对sql语句的准备(编译)过程有破坏作用

而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理,

而不再对sql语句进行解析,准备,因此也就避免了sql注入问题.

2.使用正则表达式过滤传入的参数

要引入的包:

import java.util.regex.*;

正则表达式:

private String CHECKSQL = “^(.+)\sand\s(.+)|(.+)\sor(.+)\s$”;

判断是否匹配:

Pattern.matches(CHECKSQL,targerStr);

下面是具体的正则表达式:

检测SQL meta-characters的正则表达式 :

/(\%27)|(\’)|(--)|(\%23)|(#)/ix

修正检测SQL meta-characters的正则表达式 :/((\%3D)|(=))[^\n]*((\%27)|(\’)|(--)|(\%3B)|(:))/i

典型的SQL 注入攻击的正则表达式 :/\w*((\%27)|(\’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix

检测SQL注入,UNION查询关键字的正则表达式 :/((\%27)|(\’))union/ix(\%27)|(\’)

检测MS SQL Server SQL注入攻击的正则表达式:

/exec(\s|+)+(s|x)p\w+/ix

等等…..

3.字符串过滤

比较通用的一个方法:

(||之间的参数可以根据自己程序的需要添加)

public static boolean sql_inj(String str){

String inj_str = "'|and|exec|insert|select|delete|update|

count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";

String injstra[] = split(injstr,"|");

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

if (str.indexOf(inj_stra[i])>=0){

return true;

}

}

return false;

}

4.jsp中调用该函数检查是否包函非法字符

防止SQL从URL注入:

sql_inj.java代码:

package sql_inj;

import java.net.*;

import java.io.*;

import java.sql.*;

import java.text.*;

import java.lang.String;

public class sql_inj{

public static boolean sql_inj(String str){

String inj_str = "'|and|exec|insert|select|delete|update|

count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";

//这里的东西还可以自己添加

String[] injstra=injstr.split("\|");

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

if (str.indexOf(inj_stra[i])>=0){

return true;

}

}

return false;

}

}

5.JSP页面判断代码:

使用javascript在客户端进行不安全字符屏蔽

功能介绍:检查是否含有”‘”,”\”,”/”

参数说明:要检查的字符串

返回值:0:是1:不是

函数名是

function check(a){

return 1;

fibdn = new Array (”‘” ,”\”,”/”);

i=fibdn.length;

j=a.length;

for (ii=0; ii<i; ii++)

{ for (jj=0; jj<j; jj++)

{ temp1=a.charAt(jj);

temp2=fibdn[ii];

if (tem’; p1==temp2)

{ return 0; }

}

}

return 1;

}

===================================

总的说来,防范一般的SQL注入只要在代码规范上下点功夫就可以了。

凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以 ,切记不要用拼接字符串的方法就可以了。

Ctrlc
Ctrlc 2017-08-23
暂时没什么可以说的

SQL注入本质上是数据和语句的混淆。

在数据被拼入SQL模版变成SQL片段的时候,正是防止SQL注入漏洞产生的最佳时机,这时候什么是数据什么是语句分得最清楚,只要使用强类型转化就可以避免数据和语句的混淆,而无需特征匹配或语法分析。一但失去这个时机,红豆和绿豆混在一起,再想摘出来就难了,难免会被绕过。

参数化只是捕捉这个时机并有效处理的最佳手段而已,这里“最佳”是包含了有效性、成本、可控等若干方面的考量。看到很多人粗暴的将其理解为“参数化能防SQL注入”,然后举各种反例,也挺无奈的。

相关讨论中,很多人混淆了“抵御SQL注入攻击”和“防止SQL注入漏洞的产生”两个概念,没有做过企业级安全支持的人——无论他是其他领域多NB的专家,还是对安全一知半解的工程师——也很难真正理解后者的真实含义和必要性,而将其看作数据库系统本身的弱点加以防御,从而陷入特征匹配的攻防纠缠中。

还有很多人混淆了“我如何防止SQL注入漏洞的产生”和“我如何避免公司里的工程师产生SQL注入漏洞”。刺客和军官本身就是两个职业,在高深的武艺、精良的装备之外,还有很多诸如组织形式、流程、士气、主要矛盾主要方面这样的问题。作为一个公司级别的解决方案,如果在数据库层面没法保证让程序员撒花的写代码也能避免SQL注入攻击的话,那你就不得不去好好面对“我如何避免公司里的工程师产生SQL注入漏洞”的问题。工程师不可能都是安全方面的专家,你也不可能让工程师写代码的时候始终崩着弦去考虑如何避免OWASP TOP 10这类问题,在这个前提下怎么解决问题,似乎安全框架+编码规范+白盒检查成了最好的选择。

SQL注入的危害性使得企业不得不追求彻底防御,不能接受潜在的绕过风险。而彻底防御又只能在生成SQL片段的时机实现,控制这个时机的是开发工程师而不是数据库,因此这是个系统问题和管理问题,而不是技术问题,至少不是纯粹的技术问题,特别不是SQL注入检测技术的问题。

回到问题本身,SQL注入问题既不能“靠用户(开发者也是用户)的自觉去避免”,也不能完全脱离用户(开发者也是用户)而指望数据库层面去避免。对于那些不了解SQL注入漏洞细节或不关心SQL注入漏洞或没精力去关心SQL注入漏洞的工程师,你要给他们一条尽可能简单可行透明的方案来避免SQL注入漏洞,告诉他这样写就可以了,这就是安全框架;然后告诉他或者让他的老大告诉他你必须这样写,这就是安全编码规范;然后你有手段在他没有这样写的时候能够检查出来(这比检查出漏洞要容易)并推动他改正,这就是白盒检查。

我们现在的互联网产品SQL注入漏洞仍然层出不穷,并不是这套思路有问题,相反恰恰是这套思路没有完善。

一方面是框架方案本身不完善,以SQL注入漏洞为例,参数化是防SQL注入框架级方案的重要部分,但仅靠参数化没法很好满足开发过程中一些常见需求,如逗号分割的id列表问题、排序标记的问题等等(其实这些问题真要用参数化的方案解决也可以),使得开发更愿意在这些地方使用非参数化或伪参数化的方法(比如拼接SQL片段后再把整个片段当作参数扔进去exec)。这些问题在参数化的基础上,再加以改进,仍然守着拼接SQL片段时进行强类型转换的思路,仍然是能很好解决的,也就是继续完善参数化方案的问题,而不是看上去那样“参数化解决不了问题”。

另一方面,安全编码规范的制定、培训、流程建设和实施保证上也做得远远不到位,开发leader们更希望后面的数据库或者前面的安全防御上能有手段去解决SQL注入问题,对于安全工程师来说,设置并维护几个特征串、语法分析场景也远比做那些安全框架、编码规范、白盒扫描来得要轻松实在,彼此在心照不宣中度过今天,自然不能指望明天能彻底踏实。

Echo
Echo 2017-07-23
暂时没什么可以说的

1、PreparedStatement 2、使用正则表达式过滤传入的参数 3、JSP中调用该函数检查是否包函非法字符 4、JSP页面判断代码 5、字符串过滤

撰写答案

请登录后再发布答案,点击登录

分享
好友

手机
浏览

扫码手机浏览