|
' v/ ?$ H4 `" Q
SQL注入攻击,是黑客对数据库进行攻击的常用手段之一那么,什么是SQL注入?SQL注入是怎么发生的?如何防止SQL注入?我们今天就来了解一下SQL注入产生的背景在企业级应用中,存储数据主要是使用数据库来实现。
% o/ `8 e( b8 _, [ 数据库有着强大的数据存储能力和数据处理性能对于开发者而言,完成数据库的数据存储和数据处理,主要是利用SQL语句来实现的不过,SQL语句中的数据是由用户在客户端通过文本框进行数据录入,然后,通过表单提交的方式请求服务器。 0 l% k8 O2 q( @, X3 y- e- J6 d
开发者为了将客户端提交的数据和数据库进行数据的交互就需要将客户端提交的数据和SQL语句的进行拼接,形成一条完整的能够执行的SQL语句然后,交给DBMS执行,完成数据的存储以及数据处理举个添加的例子,SQL语句应该书写如下:
9 O w- X3 _* y& w d insert into t_user(user_name,sex) values(tom,男);这条SQL语句执行完成后,可以向数据库添加用户名为”tom”,性别为”男”的记录但是,在实际应用中,用户名和性别应该是由客户端提供的。
3 Y/ M8 I7 o6 z7 U, L, d 这时,开发者应该先得到从客户端提交数据,然后拼接成添加SQL语句,交由DBMS执行String name = request.getParameter("userName");* o* g% s. |% ]- T
String sex = request.getParameter("sex");
0 g- B" F/ v! ~+ M String sql="insert into t_user(user_name,sex)values("+name+","+sex+")"; * V& k* i* W' _
这时,如果客户端提交的name值为”john”,性别为”男”那么拼接后的SQL语句就应该是:String sql = "insert into t_user(userName,sex) values(john,男)";。
- G/ }/ i! o8 o/ J$ ~* l 这样,DBMS在执行SQL语句后,就会将”john”和”男”添加进数据库不过,在这个过程中,存在一些漏洞可以被黑客所攻击如果客户端提交的数据存在一些非法字符或数据库关键字时,可能会造成SQL语句发生错误,或执行结果不正确的情况。 8 i" T: H0 H2 _& m( K X
在上面的示例中,如果客户端提交的name值为”jo’hn”性别为”男”那么拼接后的SQL语句就应该是:String sql = "insert into t_user(userName,sex) values(john,男)";。 9 N$ D9 ]. y2 E. D, l: J
很明显,这条SQL语句不满足添加语句的语法DBMS在执行时会报SQL语句语法错误再来看一个登陆的例子,sql语句应该书写如下:String name = request.getParameter("userName");! Q7 K: @, ^, }8 ~& o; q5 n9 t+ s
String password = request.getParameter("password");
. H: e6 i2 X9 a( ?- h String sql = "select * from t_user where userName=" + name +
- ^6 L3 j/ f6 s( S4 W% x" v " and password="+password+"";。 & a" b2 W' K1 C w5 f/ j, S
这条SQL语句的本意是,查询用户名和密码同时相等的记录如果客户端提交的userName值为”tom”,密码为”123”那么拼接后的SQL语句就应该是:String sql = "select * from t_user where userName=tom and "
! x9 e/ _- W( d- [7 o + "password=123";。 5 ] [' z/ P0 U) }0 [2 q8 K
但是,如果客户端提交的userName值为”aaa”密码为”bbb’ or ‘1’=’1”那么拼接后的SQL语句就应该是:String sql = "select * from t_user where userName=aaa and "
6 E) V: S8 G1 S% E4 n + "password=bbb or 1=1";。 : D) U4 l7 q) P4 p8 ~& K( n
由于’1’=’1’固定为true,所以,这条SQL语句的查询结果,是t_user表中所有记录这样的话,无论用户名和密码输什么值,都可以有结果返回从而,开发者会得到”登陆成功”的错误结论有些黑客也利用,在数据中加入”--“的方式,注释掉SQL语句中的条件。 - b; `0 p3 g0 {& D! x9 I
比如,客户端提交的userName值为”aaa’ or 1=1 -- “密码为”bbb”那么拼接后的SQL语句就应该是:String sql = "select * from t_user where userName=aaa or 1=1 -- "
% h0 o6 }+ p# N0 ` + " and password=bbb";
1 g0 e. e( ^8 Q3 y 这样,1=1固定为true,而以后的SQL语句会因为注释不会执行如果黑客再坏一点,在数据中加入DDL操作,比如:在密码中填入”bbb’;drop table t_user;”,那么SQL语句就变成:tring sql = "select * from t_user where userName=aaa and "
3 ]6 h/ X) f" B$ S: N# k + "password=bbb;drop table t_user"; " E+ p! }$ u6 g, E
执行SQL语句后,表都没了什么是SQL注入?所谓SQL注入,是将客户机提交或Web表单递交的数据,拼接成SQL语句字符串时如果客户端提交的数据有非法字符或SQL语句关键字时,会造成执行的SQL语句语法错误,或执行结果不正确的情况。 5 H4 H5 |. b/ ^$ J, t
通过SQL注入,黑客可以最终达到欺骗服务器,执行恶意的SQL语句,甚至破坏数据库结构的目的SQL注入攻击大多是利用设计上的漏洞,在目标服务器上运行Sql语句的攻击方式开发者在动态生成Sql语句时,没有对用户输入的数据进行验证,是Sql注入攻击得逞的主要原因。 ' o0 o* h# }* @! K( H9 q
如何防止SQL注入?在java中,是使用JDBC和数据库建立连接,并执行SQL语句,和数据库进行数据交互的JDBC在执行SQL语句操作时,提供了Statement、PreparedStatement和CallableStatement三种方式来执行SQL语句。
, Q) m6 \. Y9 m \ 其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程在三个接口中,Statement是PreparedStatement和CallableStatement的父接口。
7 Z' V6 X% N" l Statement在执行SQL语句时,对于客户端提交的数据只支持拼接SQL语句的方式String sql = "select * from t_user where userName=" + name +- d* D5 [. w) l1 D8 Z* s, ^# J
" and password=" + password + ""; 6 t% {8 m6 g- `5 u8 U
所以,使用Statement在执行SQL语句,容易引起SQL注入PreparedStatement在执行参数化查询时,支持占位符方式String sql = "select * from t_user where userName=? and password=?";! v! j/ M' v8 a9 I
PreparedStatement ps = conn.prepareStatement(sql);: j* r; l8 t1 t* m" T, g8 I0 j
ps.setString(1,name);$ }& h# m( Z( n# [+ m9 B
ps.setString(2,password);。
: s n- Y9 C' T 在使用参数化查询的情况下,数据库系统不会将参数的内容,视为SQL指令的一部分来处理而是在数据库完成SQL指令的编译后,才套用参数运行因此,就算参数中含有破坏性的指令,也不会被数据库所运行所以,使用PreparedStatement的参数化查询可以有效的阻止SQL注入。 9 T3 z# I! x2 d! Q( R. t* @
另外,PreparedStatement相比Statement还有以下几个优势1、可以预编译SQL语句,多次查询时速度快2、防止数据库缓冲区溢出3、代码的可读性可维护性好由于有以上优点,所以,在开发JDBC时,PreparedStatement成为访问数据库的语句对象的首选。
& Y6 `4 n. ~! B& T" Z7 R 总结:所谓SQL注入,是将客户机提交或Web表单递交的数据,拼接成SQL语句字符串时如果客户端提交的数据有非法字符或SQL语句关键字时,会造成执行的SQL语句语法错误,或执行结果不正确的情况通过SQL注入,黑客可以最终达到欺骗服务器,执行恶意的SQL语句,甚至破坏数据库结构的目的。
2 m* G) y' t9 {& ?' \9 }7 Q- z 在JDBC中使用PreparedStatement的参数化查询,数据库系统不会将参数的内容,视为SQL指令的一部分来处理可以有效防止SQL注入开发JDBC时,尽量采用 PreparedStatement执行SQL语句,相比Statement有以下优势:。 5 U) b3 u9 G" g0 d
a、可以防止SQL注入b、可以预编译SQL语句,多次查询时速度快c、防止数据库缓冲区溢出d、代码的可读性可维护性好 ! H1 E; v3 G) t1 w4 a
8 T/ {. Q( d: Q+ j: t: G! R/ A) m) Q$ T& T5 n/ ^
C1 ~6 o' m' K: _5 g% r
0 u: D n7 J+ ~$ Y$ H/ ]' f; _ |