SQL注入攻击,吓死宝宝了

朗沃教育 朗沃L君

SQL注入攻击,是黑客对数据库进行攻击的常用手段之一。那么,什么是SQL注入?SQL注入是怎么发生的?如何防止SQL注入?我们今天就来了解一下。

SQL注入产生的背景

在企业级应用中,存储数据主要是使用数据库来实现。数据库有着强大的数据存储能力和数据处理性能。

对于开发者而言,完成数据库的数据存储和数据处理,主要是利用SQL语句来实现的。不过,SQL语句中的数据是由用户在客户端通过文本框进行数据录入,然后,通过表单提交的方式请求服务器。开发者为了将客户端提交的数据和数据库进行数据的交互。就需要将客户端提交的数据和SQL语句的进行拼接,形成一条完整的能够执行的SQL语句。然后,交给DBMS执行,完成数据的存储以及数据处理。

举个添加的例子,SQL语句应该书写如下:

insert into t_user(userName,sex) values('tom','男');

这条SQL语句执行完成后,可以向数据库添加用户名为”tom”,性别为”男”的记录。但是,在实际应用中,用户名和性别应该是由客户端提供的。这时,开发者应该先得到从客户端提交数据,然后拼接成添加SQL语句,交由DBMS执行。

String name = request.getParameter("userName");

String sex = request.getParameter("sex");

String sql="insert into t_user(userName,sex)values('"+name+"','"+sex+"')";

这时,如果客户端提交的userName值为”john”,性别为”男”。那么拼接后的SQL语句就应该是:

String sql = "insert into t_user(userName,sex) values('john','男')";

这样,DBMS在执行SQL语句后,就会将”john”和”男”添加进数据库。

不过,在这个过程中,存在一些漏洞可以被黑客所攻击。如果客户端提交的数据存在一些非法字符或数据库关键字时,可能会造成SQL语句发生错误,或执行结果不正确的情况。

在上面的示例中,如果客户端提交的userName值为”jo’hn”。性别为”男”。那么拼接后的SQL语句就应该是:

String sql = "insert into t_user(userName,sex) values('jo'hn','男')";

很明显,这条SQL语句不满足添加语句的语法。DBMS在执行时会报SQL语句语法错误。

再来看一个登陆的例子,sql语句应该书写如下:

String name = request.getParameter("userName");

String password = request.getParameter("password");

String sql = "select * from t_user where userName='" + name +

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

这条SQL语句的本意是,查询用户名和密码同时相等的记录。如果客户端提交的userName值为”tom”,密码为”123”。那么拼接后的SQL语句就应该是:

String sql = "select * from t_user where userName='tom' and "

+ "password='123'";

但是,如果客户端提交的userName值为”aaa”。密码为”bbb’ or ‘1’=’1”。那么拼接后的SQL语句就应该是:

String sql = "select * from t_user where userName='aaa' and "

+ "password='bbb' or '1'='1'";

由于’1’=’1’固定为true,所以,这条SQL语句的查询结果,是t_user表中所有记录。这样的话,无论用户名和密码输什么值,都可以有结果返回。从而,开发者会得到”登陆成功”的错误结论。

有些黑客也利用,在数据中加入”--“的方式,注释掉SQL语句中的条件。比如,客户端提交的userName值为”aaa’ or 1=1 -- “。密码为”bbb”。那么拼接后的SQL语句就应该是:

String sql = "select * from t_user where userName='aaa' or 1=1 -- '"

+ " and password='bbb'";

这样,1=1固定为true,而以后的SQL语句会因为注释不会执行。

如果黑客再坏一点,在数据中加入DDL操作,比如:在密码中填入”bbb’;drop table t_user;”,那么SQL语句就变成:

String sql = "select * from t_user where userName='aaa' and "

+ "password='bbb';drop table t_user";

执行SQL语句后,表都没了。

什么是SQL注入?

所谓SQL注入,是将客户机提交或Web表单递交的数据,拼接成SQL语句字符串时。如果客户端提交的数据有非法字符或SQL语句关键字时,会造成执行的SQL语句语法错误,或执行结果不正确的情况。通过SQL注入,黑客可以最终达到欺骗服务器,执行恶意的SQL语句,甚至破坏数据库结构的目的。

SQL注入攻击大多是利用设计上的漏洞,在目标服务器上运行Sql语句的攻击方式。开发者在动态生成Sql语句时,没有对用户输入的数据进行验证,是Sql注入攻击得逞的主要原因。

如何防止SQL注入?

在java中,是使用JDBC和数据库建立连接,并执行SQL语句,和数据库进行数据交互的。

JDBC在执行SQL语句操作时,提供了Statement、PreparedStatement和CallableStatement三种方式来执行SQL语句。其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程。

在三个接口中,Statement是PreparedStatement和CallableStatement的父接口。Statement在执行SQL语句时,对于客户端提交的数据只支持拼接SQL语句的方式。

所以,使用Statement在执行SQL语句,容易引起SQL注入。PreparedStatement在执行参数化查询时,支持占位符方式。

在使用参数化查询的情况下,数据库系统不会将参数的内容,视为SQL指令的一部分来处理。而是在数据库完成SQL指令的编译后,才套用参数运行。因此,就算参数中含有破坏性的指令,也不会被数据库所运行。所以,使用PreparedStatement的参数化查询可以有效的阻止SQL注入。

另外,PreparedStatement相比Statement还有以下几个优势

1、可以预编译SQL语句,多次查询时速度快。

2、防止数据库缓冲区溢出

3、代码的可读性可维护性好

由于有以上优点,所以,在开发JDBC时,PreparedStatement成为访问数据库的语句对象的首选。

总结:

所谓SQL注入,是将客户机提交或Web表单递交的数据,拼接成SQL语句字符串时。如果客户端提交的数据有非法字符或SQL语句关键字时,会造成执行的SQL语句语法错误,或执行结果不正确的情况。通过SQL注入,黑客可以最终达到欺骗服务器,执行恶意的SQL语句,甚至破坏数据库结构的目的。

在JDBC中使用PreparedStatement的参数化查询,数据库系统不会将参数的内容,视为SQL指令的一部分来处理。可以有效防止SQL注入。

开发JDBC时,尽量采用 PreparedStatement执行SQL语句,相比Statement有以下优势:

a、可以防止SQL注入

b、可以预编译SQL语句,多次查询时速度快

c、防止数据库缓冲区溢出

d、代码的可读性可维护性好

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20181010A17WKF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券