前沿
在现有的框架中sql防注入已经做得很好了,我们需要做的就是尽量不要使用sql拼接调用
java sql注入原因以及预防方案(易理解)
1. SQL注入
1.1 原理
SQL注入是通过客户端的输入把SQL命令注入到一个应用的数据库中,从而执行恶意的SQL语句。
1.2 演示
1.2.1 案例1
有一个登录框,需要 输入用户名和密码 ,然后我们的密码输入 'or '123' = '123 这样的。我们在查询用户名和密码是否正确的时候,本来执行的sql语句是:select * from user where username = '' and password = ''. 这样的sql语句,现在我们输入密码是如上这样的,然后我们会通过参数进行拼接,拼接后的sql语句就是:
select * from user where username = '' and password = ' ' or '123' = '123 ';这样的了,那么会有一个or语句,只要这两个有一个是正确的话,就条件成立,因此 123 = 123 是成立的。因此验证就会被跳过。这只是一个简单的例子,
1.2.2 案例2
密码比如是这样的:'; drop table user;, 这样的话,那么sql命令就变成了:
select * from user where username = '' and password = ''; drop table user;', 那么这个时候我们会把user表直接删除了。
1.3 防范
1.3.1 前端
前端表单进行参数格式控制;
1.3.2 后端
注意: 永远也不要把未经检查的用户输入的值直接传给数据库
- package cn.javanode.thread;
- import java.util.regex.Pattern;
- /**
- * @author xgt(小光头)
- * @version 1.0
- * @date 2021-1-8 11:48
- */
- public class CheckSqlDemo {
- /**正则表达式**/
- private static String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
- + "(\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
- private static Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
- private static boolean isValid(String str) {
- if (sqlPattern.matcher(str).find())
- {
- System.out.println("未能通过过滤器:str=" + str);
- return false;
- }
- return true;
- }
- public static void main(String[] args) {
- System.out.println(isValid("tongji_user_add"));
- }
- }
补充
PreparedStatement是如何防止SQL注入的?
1. 拼接参数(sql注入)
- Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
- PreparedStatement preparedStatement = connection.prepareStatement(sql);
- String param = "'test' or 1=1";
- String sql = "select file from file where name = " + param; // 拼接SQL参数
- ResultSet resultSet = preparedStatement.executeQuery();
- System.out.println(resultSet.next());
输出结果为 true ,DB中执行的SQL为
- -- 永真条件1=1成为了查询条件的一部分,可以返回所有数据,造成了SQL注入问题
- select file from file where name = 'test' or 1=1
2. setString (防注入)
- Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
- PreparedStatement preparedStatement = connection.prepareStatement(sql);
- preparedStatement.setString(1,account);//设置参数
- preparedStatement.setString(2,password);
- ResultSet resultSet = preparedStatement.executeQuery();//执行查询sql,获取结果集
输出结果为 false ,DB中执行的SQL为
- select file from file where name = '\'test\' or 1=1'
我们可以看到输出的 SQL是把整个参数用引号包起来,并把参数中的引号作为转义字符,从而避免了参数也作为条件的一部分
3. 源码分析
结论
- //完整代码
- public void setString(int parameterIndex, String x) throws SQLException {
- synchronized (checkClosed().getConnectionMutex()) {
- // if the passed string is null, then set this column to null
- if (x == null) {
- setNull(parameterIndex, Types.CHAR);
- } else {
- checkClosed();
- int stringLength = x.length();
- if (this.connection.isNoBackslashEscapesSet()) {
- // Scan for any nasty chars
- // 判断是否需要转义
- boolean needsHexEscape = isEscapeNeededForString(x, stringLength);
- if (!needsHexEscape) {
- byte[] parameterAsBytes = null;
- StringBuilder quotedString = new StringBuilder(x.length() + 2);
- quotedString.append('\'');
- quotedString.append(x);
- quotedString.append('\'');
- if (!this.isLoadDataQuery) {
- parameterAsBytes = StringUtils.getBytes(quotedString.toString(), this.charConverter, this.charEncoding,
- this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor());
- } else {
- // Send with platform character encoding
- parameterAsBytes = StringUtils.getBytes(quotedString.toString());
- }
- setInternal(parameterIndex, parameterAsBytes);
- } else {
- byte[] parameterAsBytes = null;
- if (!this.isLoadDataQuery) {
- parameterAsBytes = StringUtils.getBytes(x, this.charConverter, this.charEncoding, this.connection.getServerCharset(),
- this.connection.parserKnowsUnicode(), getExceptionInterceptor());
- } else {
- // Send with platform character encoding
- parameterAsBytes = StringUtils.getBytes(x);
- }
- setBytes(parameterIndex, parameterAsBytes);
- }
- return;
- }
2020年对于云计算行业来说是突破性的一年,因为公共云供应商增加了收入,而疫情...
很长时间没有更新原创文章了,但是还一直在思考和沉淀当中,后面公众号会更频繁...
最近,DevOps的采用导致了企业计算的重大转变。除无服务器计算,动态配置和即付...
定义 this是函数运行时自动生成的内部对象,即调用函数的那个对象。(不一定很准...
在TOP云(zuntop.com)科技租赁过服务器的站长都知道独立服务器在价格上比VPS主...
查看表结构,sbtest1有主键、k_1二级索引、i_c二级索引 CREATE TABLE `sbtest1` ...
本文转载自网络,原文链接:https://mp.weixin.qq.com/s/vlOUg46B5bcmToX-fjavJQ...
9月17日,2020云栖大会上,阿里云正式发布工业大脑3.0。 阿里云智能资深产品专家...
中国最?好的一朵云飘进了华瑞银行。阿里云将进一步助力华瑞银行All in Cloud。 -...
一、PostgreSQL行业位置 一 行业位置 首先我们看一看RDS PostgreSQL在整个行业当...