SQL注入漏洞

1.SQL注入漏洞概念

用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据。举例来说在某个具有SQL漏洞的网站中注册后,正常情况下用户需通过用户名和密码来进行登录,但由于SQL漏洞的存在,他人只需知道你的用户名即可登录进你的账号来进行操作。

2.SQL注入示例

背景:数据表为user,其中有一条数据的用户名为"aaa",对应密码为"123"。
登录代码实现:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import jdbcUtils.JDBCUtils;

/**
 * 登录功能的实现
 * @author Silence_L
 *
 */
public class Dao {
	/**
	 * 登录方法
	 * @param username:用户名
	 * @param password:密码
	 * @return
	 */
	public boolean login(String username, String password) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		// 定义一个变量用作返回结果
		boolean flag = false;
		try {
			// 获得连接
			conn = JDBCUtils.getConnection();
			// 获得执行SQL语句的对象
			stmt = conn.createStatement();
			// 编写SQL语句
			String sql = "select * from user where username = '" + username + "' and password = '" + password +"'";
			// 执行SQL
			rs = stmt.executeQuery(sql);
			if(rs.next()) {
				flag = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			JDBCUtils.release(conn, stmt, rs);
		}
		return flag;
	}
}

测试代码:

/**
 * SQL注入漏洞示例
 * @author Silence_L
 *
 */
public class LoginTest {

	public static void main(String[] args) {
		Dao dao = new Dao();
		String username = "aaa";
		String password = "123";
		if(dao.login(username, password)) {
			System.out.println("登录成功");
		} else {
			System.out.println("登录失败");
		}
	}

}

(PS:JDBCUtils中编写了数据库的连接和资源释放两个静态方法)
正常结果(登录成功):
在这里插入图片描述
密码错误结果:
在这里插入图片描述
SQL注入结果1(用户名+’ or ‘1=1):

输入用户名为"aaa’ or ‘1=1",密码错误此时发现结果显示登录成功。
SQL注入结果2(用户名+’ – ):
在这里插入图片描述
输入用户名为"aaa’ – "(–后面必须带空格,不然会抛出异常),密码错误此时登录结果仍然是登录成功。

3.注入漏洞分析

第一种情况:
当输入的用户名为正确用户名+’ or '1=1时,此时对应的SQL语句为:

select * from user where username = 'aaa' or '1=1' and password = '456'

从SQL语句中不难看出在用户名检索条件后加了一个or语句,导致后面的密码判断的and部分没有执行就检索出了对应的结果。

第二种情况:
当输入的用户名为正确用户名+’ – 时,此时对应的SQL语句为:

select * from where username = 'aaa' -- and password = '456'

从代码的高亮显示不难看出“–”后面的内容变成了注释,故判断时只以用户名为判断依据,就造成了只需用户名正确就能登录成功的状况。

4.SQL注入漏洞的解决方法

利用PreparedStatement替代代码中的Statement来解决这个问题。修改后的代码如下所示:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import jdbcUtils.JDBCUtils;

/**
 * 登录功能的实现
 * @author Silence_L
 *
 */
public class Dao {
	/**
	 * 登录方法
	 * @param username:用户名
	 * @param password:密码
	 * @return
	 */
	public boolean login(String username, String password) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		// 定义一个变量用作返回结果
		boolean flag = false;
		try {
			// 获得连接
			conn = JDBCUtils.getConnection();
			// 编写SQL语句
			String sql = "select * from user where username = ? and password = ?";
			// 预编译SQL
			pstmt = conn.prepareStatement(sql);
			// 设置参数
			pstmt.setString(1, username);
			pstmt.setString(2, password);
			// 执行SQL
			rs = pstmt.executeQuery();
			if(rs.next()) {
				flag = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			JDBCUtils.release(conn, pstmt, rs);
		}
		return flag;
	}
}

结果展示:
在这里插入图片描述
在这里插入图片描述
从结果上来看此时两种输入方式都不能登录成功。
分析:
之所以能够解决注入问题,是因为PreparedStatement会先进行预编译,而代码中SQL语句中的问号相当于占位符,之后我们通过函数传参的方式来实现?的内容替代,但是由于设置了SQL语句的格式,此时?处的替代内容即便有SQL中的关键字也不会被识别,而是会当做普通的字符来进行识别,因此能够解决注入问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值