SQL注入攻击,吓死本宝宝了

2023-05-07 03:47:55

 

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

SQL注入产生的背景

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

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

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

insert into t_user(user_name,sex) values(tom,男);

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

String name = request.getParameter("userName"); String sex = request.getParameter("sex"); String sql="insert into t_user(user_name,sex)values("+name+","+sex+")";

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

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

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

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

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

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

很明显,这条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语句就变成:

tring 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语句的方式。
String sql = "select * from t_user where userName=" + name + " and password=" + password + "";

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

String sql = "select * from t_user where userName=? and password=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1,name); ps.setString(2,password);

在使用参数化查询的情况下,数据库系统不会将参数的内容,视为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、代码的可读性可维护性好


以上就是关于《SQL注入攻击,吓死本宝宝了》的全部内容,本文网址:https://www.7ca.cn/baike/24768.shtml,如对您有帮助可以分享给好友,谢谢。
标签:
声明

排行榜