SQL盲注

2 篇文章 0 订阅
1 篇文章 0 订阅

前言

在前段时间项目拿去做了一个入网安全测试,结果测出来例如SQL盲注,跨站点脚本攻击(XSS),跨站点伪造(CSRF) 等一系列问题.
今天先对解决SQL盲注 问题做一个小的总结.

问题

SQL盲注,相信大家都不会怎么陌生,如果没听说过得话,那么肯定听说过SQL注入.
SQL盲注 是一种Web 系统的安全漏洞,属于比较严重的那种.SQL注入有很多种方式,
SQL盲注就是SQL注入的其中一种方式.

在安全级别中,SQL盲注是一种威胁程度很高的安全漏洞.
用SQL查询语句去猜解表名、字段、数据等信息,使用外部输入来构造SQL 命令的全部或一部分,
如果在用户输入中没有对SQL语法充分地除去或引用,那么生成的SQL可绕过安全性检查,
或者插入其他用于修改后端数据库的语句,或者执行系统命令。
错误的SQL也会被调用,并返回请求响应,攻击者利用这些漏洞进行系统攻击。

注入实例:

//请求地址
String getUrl="xxx.jsp?user=admin&password=1' or '1'='1 ";

//接收参数
String user=request.getParameter("user");
String password=request.getParameter("password");

//拼装sql
String checkSql="select count(*) from user where username='"+user+"' and password ='"+password+"'";

获取参数合成后的sql变成了
select count(*) from users where userid='admin' and passwd='1' or '1'='1'

这条SQL将会返回所有的记录数。
示例代码:
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取链接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root","admin");

//模拟账号
String user="zhouq";

//模拟密码
String password="1' or '1'='1";

//拼接 statement 需要执行的 sql
StringBuilder sqlByStatement=new StringBuilder("select count(*) from user where ");
sqlByStatement.append(" username='").append(user).append("'");
sqlByStatement.append(" and password='").append(password).append("'");

//准备 PreparedStatement 执行的预编译 sql
String sqlByPrepareStatement="select count(*) from user where username=? and password=?";

Statement statement = conn.createStatement();
ResultSet query = statement.executeQuery(sqlByStatement.toString());

System.out.println("账户:"+ user);
System.out.println("密码:"+ password);
System.out.println("===========华丽的分割线===========");

if(query.next()){
    long count = query.getLong(1);
    System.out.println("Statement 查询结果:" + count);
}

PreparedStatement ps = conn.prepareStatement(sqlByPrepareStatement);

//设置第一个参数
ps.setString(1, user);

//设置第二个参数
ps.setString(2, password);
ResultSet resultSet = ps.executeQuery();

if(resultSet.next()){
    long count = resultSet.getLong(1);
    System.out.println("PrepareStatement 查询结果: " + count);
}

//资源关闭 操作...
//
输出结果:
账户:zhouq
密码:1' or '1'='1
===========华丽的分割线===========
Statement 查询结果:1
PrepareStatement 查询结果: 0

解决方案

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

对于JDBC而言,SQL注入攻击只对 Statement 有效,对PreparedStatement是无效的,这是因为PreparedStatement不允许在插入时改变查询的逻辑结构.
绕过验证,但这种手段只对Statement有效,对PreparedStatement无效.

  • 尽量使用PreparedStatement 执行sql .
    例如上面的 SQL 查询语句.
    在 Statement 中 的sql 语句: select count(*) from user where username='admin' and passwd='1' or '1'='1'.
    然后 statement.executeQuery(sql) 执行 ,
    PreparedStatement 中 的sql 语句: select count(*) from user where username=? and password=? ,然后再对对应的 ? 赋值.
    Statement 是将整个sql 语句作为一个字符串链接到一起执行.
    PreparedStatement 中则 将 1' or '1'='1 做为一个字符串 赋值给第二个 ? ,作为 “密码” 字段对应的值.这样一来 ,sql 注入就不存在了.

  • 使用 ORM 框架. 如 Mybatis
    Mybatis 框架中. #{xx} ,使用的是PreparedStatement ,会有类型转换.也是比较安全的.
    select count(*) from user where username=#{username} and password=#{password}
    最终编译的sql为:
    select count(*) from user where username=? and password=?

结语:

以上的这些,只是对最终sql 的处理.如果想彻底的防止SQL盲注 的系统.
那么我们还需要对用户发过来的请求进行过滤,其中请求中的参数值很有可能包括一些危险的字符,
这些字符就是我们需要去过滤处理的问题了.关于处理危险字符这些问题,又会涉及到 其他的漏洞 比如 XSS ,CSRF 等等.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值