1、什么是sql注入?javascript
一、什么是sql注入呢?java
所谓SQL注入,就是经过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,好比先前的不少影视网站泄露VIP会员密码大多就是经过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击.当应用程序使用输入内容来构造动态sql语句以访问数据库时,会发生sql注入攻击。若是代码使用存储过程,而这些存储过程做为包含未筛选的用户输入的字符串来传递,也会发生sql注入。 黑客经过SQL注入攻击能够拿到网站数据库的访问权限,以后他们就能够拿到网站数据库中全部的数据,恶意的黑客能够经过SQL注入功能篡改数据库中的数据甚至会把数据库中的数据毁坏掉。作为网络开发者的你对这种黑客行为恨之入骨,固然也有必要了解一下SQL注入这种功能方式的原理并学会如何经过代码来保护本身的网站数据库web
二、sql注入产生缘由正则表达式
sql注入攻击是利用是指利用设计上的漏洞,在目标服务器上运行Sql语句以及进行其余方式的攻击,动态生成Sql语句时没有对用户输入的数据进行验证是Sql注入攻击得逞的主要缘由。对于java数据库链接JDBC而言,SQL注入攻击只对Statement有效,对PreparedStatement是无效的,这是由于PreparedStatement不容许在不一样的插入时间改变查询的逻辑结构。sql
如验证用户是否存在的SQL语句为:数据库
用户名'and pswd='密码安全
若是在用户名字段中输入: 'or 1=1或是在密码字段中输入:'or 1=1服务器
将绕过验证,但这种手段只对只对Statement有效,对PreparedStatement无效。相对Statement有如下优势:网络
1.防注入攻击
2.屡次运行速度快
3.防止数据库缓冲区溢出
4.代码的可读性可维护性好jsp
这四点使得PreparedStatement成为访问数据库的语句对象的首选,缺点是灵活性不够好,有些场合仍是必须使用Statement。
三、sql注入原理
下面咱们来讲一下sql注入原理,以使读者对sql注入攻击有一个感性的认识,至于其余攻击,原理是一致的。
SQL注射能使攻击者绕过认证机制,彻底控制远程服务器上的数据库。 SQL是结构化查询语言的简称,它是访问数据库的事实标准。目前,大多数Web应用都使用SQL数据库来存放应用程序的数据。几乎全部的Web应用在后台 都使用某种SQL数据库。跟大多数语言同样,SQL语法容许数据库命令和用户数据混杂在一块儿的。若是开发人员不细心的话,用户数据就有可能被解释成命令, 这样的话,远程用户就不只能向Web应用输入数据,并且还能够在数据库上执行任意命令了。
SQL注入式攻击的主要形式有两种。一是直接将代码插入到与SQL命令串联在一块儿并使得其以执行的用户输入变量。上面笔者举的例子就是采用了这种方法。因为其直接与SQL语句捆绑,故也被称为直接注入式攻击法。二是一种间接的攻击方法,它将恶意代码注入要在表中存储或者做为原书据存储的字符串。在存储的字符串中会链接到一个动态的SQL命令中,以执行一些恶意的SQL代码。注入过程的工做方式是提早终止文本字符串,而后追加一个新的命令。如以直接注入式攻击为例。就是在用户输入变量的时候,先用一个分号结束当前的语句。而后再插入一个恶意SQL语句便可。因为插入的命令可能在执行前追加其余字符串,所以攻击者经常用注释标记“—”来终止注入的字符串。执行时,系统会认为此后语句位注释,故后续的文本将被忽略,不背编译与执行。
四、SQL注入攻击的简单示例:
这里咱们举一个比较常见的例子来简要说明一下sql注入的原理。假如咱们有一个users表,里面有两个字段username和password。在咱们的java代码中咱们初学者都习惯用sql拼接的方式进行用户验证。好比:"select id from users where username = '"+username +"' and password = '" + password +"'" 这里的username和password都是咱们存取从web表单得到的数据。下面咱们来看一下一种简单的注入,若是咱们在表单中username的输入框中输入' or 1=1-- ,password的表单中随便输入一些东西,假如这里输入123.此时咱们所要执行的sql语句就变成了select id from users where username = '' or 1=1-- and password = '123',咱们来看一下这个sql,由于1=1是true,后面 and password = '123'被注释掉了。因此这里彻底跳过了sql验证。
2、如何防护sql注入攻击
1.采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值便可。
使用好处:
(1).代码的可读性和可维护性.
(2).PreparedStatement尽最大可能提升性能.
(3).最重要的一点是极大地提升了安全性.
原理:sql注入只对sql语句的准备(编译)过程有破坏做用,而PreparedStatement已经准备好了,执行阶段只是把输入串做为数据处理,而再也不对sql语句进行解析,准备,所以也就避免了sql注入问题.
2.使用正则表达式过滤传入的参数
正则表达式:
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
等等…..
其实能够简单的使用replace方法也能够实现上诉功能:
1 public static String TransactSQLInjection(String str) 2 { 3 return str.replaceAll(".*([';]+|(--)+).*", " "); 4 }
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 inj_stra[] = split(inj_str,"|"); 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[] inj_stra=inj_str.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; }