目录
一、什么是SQL注入?
SQL注入即是指 web应用程序中数据库层的安全漏洞,因为没有对用户输入数据的合法性没有判断或过滤,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的 SQL语句 ,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
二、SQL注入的原理
SQL注入主要有以下4点:
1)恶意拼接查询
SQL语句可以对数据进行增删改查,且使用分号来分隔不同命令。例如:
select * from t_user where id = $id
其中id是传入的参数,如果传入参数的值为"123;delete from t_user",那么最终执行的查询为:
select * from t_user where id = 123;delete from t_user
如果执行以上语句,则会删除表中的所有数据
2)利用注释执行非法命令
SQL语句中可以插入注释,例如
select conut(*) as 'num' from score where id =$id
如果version包含了恶意的字符串" '1' or 3 and sleep(500) ",那么最终查询的语句会变为
select conut(*) as 'num' from score where id ='1' or 3 and sleep(500)
以上恶意查询只是想耗尽系统资源,sleep(500) 将导致 SQL 语句一直运行,保持休眠。如果其中添加了修改、删除数据的恶意指令,那么将会造成更大的破坏。
3)传入非法参数
SQL 语句中传入的字符串参数是用单引号引起来的,如果字符串本身包含单引号而没有被处理,那么可能会篡改原本 SQL 语句的作用。 例如:
select * from t_user where name = $name
如果 name 传入参数值为 R'rong,那么最终的查询语句会变为:
select * from t_user where name = 'R'rong'
一般情况下,以上语句会执行出错,这样的语句风险还比较小。如果携带了更多更复杂的语句,可能会恶意产生 SQL 语句,并且以一种不正当的方式运行。
4)添加额外条件
在 SQL 语句中添加一些额外条件,以此来改变执行行为。条件一般为真值表达式。例如:
update t_user set pwd='$pwd' where id=$id
如果 user_id 被传入恶意的字符串“1 or true”,那么最终的 SQL 语句会变为:
update t_user set pwd='123' where id='1' OR true
如果执行以上语句,将更改所有用户的密码为123
三、SQL注入实例--传入非法参数
简单的模仿黑客不需要输入用户名密码进行的登录操作。
以下实例我使用本机端口的jdbc数据库,用户名和密码均是root。
1.拼接SQL语句方法
如果使用的是拼接SQL语句方法进行登录操作,输入任意的用户名+' or '1'='1密码,都可以直接登录成功。
Scanner sc = new Scanner(System.in);
System.out.println("请输入登录的用户名:");
String name = sc.nextLine();
System.out.println("请输入登录的密码:");
String pwd = sc.nextLine();
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC", "root", "root");
PreparedStatement preparedStatement = connection.prepareStatement("select * from t_user where name='" + name + "' and pwd='" + pwd + "'");
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
System.out.println("登录成功!");
} else {
System.out.println("登录失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
2.SQL传参方法
如果使用的是SQL传参方法进行登录操作,输入任意的用户名+' or '1'='1密码,不能登录成功。
Scanner sc = new Scanner(System.in);
System.out.println("请输入登录的用户名:");
String name = sc.nextLine();
System.out.println("请输入登录的密码:");
String pwd = sc.nextLine();
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC", "root", "root");
PreparedStatement preparedStatement = connection.prepareStatement("select * from t_user where name= ? and pwd=? +");
preparedStatement.setString(1,name);
preparedStatement.setString(2,pwd);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
System.out.println("登录成功!");
} else {
System.out.println("登录失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
3. 库操作
当我们将如图代码输入:
select * from t_user where name='addaxgguhuc' and pwd= '' or '1'='1';
不论我们是否知道用户名和密码,都可以直接查出数据库中的信息。