SQL注入是最高危的漏洞之一,它和命令执行漏洞一样是直接危害应用本身,可能导致数据库内容直接泄露或者被删除等.
如何出现
以Java和MySQL为例子,假设用户输入账号和密码进行登录,调用执行SQL的方法如下.
public boolean login(String name,String passwd){ String sql = "select count(1) from t_user where name = '"+name+"' and passwd = '"+passwd+"'"; try{ ResultSet resultSet = connection.createStatement().executeQuery(sql); if(resultSet.next()){ int i = resultSet.getInt(1); if(i > 0){ return true; } } } catch (Exception e) { e.printStackTrace(); } return false; }
实际上所执行的SQL是代入2个值之后直接拼接出来.那么就有了如下场景
// 正常场景 name = GrayMan password = 123456 select count(1) from t_user where name = 'GrayMan' and password = '123456' ; // 注入场景 name = GrayMan' or 1=1 -- password = [123456] select count(1) from t_user where name = 'GrayMan' or 1=1 --' and password = '123456' ;
注入场景中所执行的是 select count(1) from t_user
where name = ‘GrayMan’ or 1=1;后面的password段是被注释掉的.那么它是永远成立的.那么就是在知道用户名的情况下是可以登入到任何一个账户的.倘若是其他场景下,是一些其他SQL
// SQL模板 select * from t_user where name = '' and password = ''; //查询出所有的用户名称 name = GrayMan' union select * from t_user;-- ' select * from t_user where name = 'GrayMan' union select * from t_user;-- ' and password = '' ; // 执行删除库表语句 name = GrayMan' ; drop table t_profile;-- ' select * from t_user where name = 'GrayMan' ; drop table t_profile;-- ' and password = '' ; // 查询操作系统文件 name= GrayMan' union select load_file('/etc/passwd');-- select * from t_user where name = 'GrayMan' union select 1,load_file('/etc/passwd');-- ' and password = '' ;
上面一个例子即能查询出系统中所有的用户,也能删除应用库,甚至如果有权限的话,直接把整个数据库删除掉也是很容易的.最后一个能读出系统的用户密码文件,当然是需要经过处理的.
如何防范
- 不要使用SQL拼接然后再去执行,尽量使用预编译语句,且进行参数绑定. 文章开头的例子可修改为
public boolean login(String name,String password){ String sql = "select count(1) from t_user where name = ? and password = ?"; try{ PreparedStatement ps = connection.prepareStatement(sql); ps.setString(1, name); ps.setString(2, password); ResultSet resultSet = ps.executeQuery(); if(resultSet.next()){ int i = resultSet.getInt(1); if(i > 0){ return true; } } } catch (Exception e) { e.printStackTrace(); } return false; }
- 如果非不得已需要使用到拼接,一定要做SQL拼接的地方对用户输入的参数进行敏感字符的转义.
- 使用框架的时候一定要确认什么样的情况下是参数绑定,什么情况下是直接拼接SQL ,例如MyBatis 中是用 【$】 和 【#】 来引用变量的区别.
- 应用所使用的数据库账号与数据库管理相关的账号独立,限制好对该账号的权限,比如DDL权限,防止应用存在SQL注入漏洞后带来灾难性的后果.
- 存储的重要数据要脱敏,加密,防篡改.比如账户的金额流水虽然金额是明文存储,但是要有token可以反推数据是否被篡改.
本文来源于:SQL注入漏洞-变化吧
特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。
- 赞助本站
- 微信扫一扫
-
- 加入Q群
- QQ扫一扫
-
评论