IT科技

Java最新SQL注入原因以及预防方案(易理解)

时间:2010-12-5 17:23:32  作者:域名   来源:应用开发  查看:  评论:0
内容摘要:前沿在现有的框架中sql防注入已经做得很好了,我们需要做的就是尽量不要使用sql拼接调用java sql注入原因以及预防方案(易理解)1. SQL注入1.1 原理SQL注入是通过客户端的输入把SQL命

 前沿

在现有的最新L注框架中sql防注入已经做得很好了,我们需要做的入原就是尽量不要使用sql拼接调用

java sql注入原因以及预防方案(易理解)

1. SQL注入

1.1 原理

SQL注入是通过客户端的输入把SQL命令注入到一个应用的数据库中,从而执行恶意的因及预防易理SQL语句。

1.2 演示

1.2.1 案例1

有一个登录框,最新L注需要 输入用户名和密码 ,入原然后我们的因及预防易理密码输入 or 123 = 123 这样的。我们在查询用户名和密码是最新L注否正确的时候,本来执行的入原sql语句是:select * from user where username = and password = . 这样的sql语句,现在我们输入密码是因及预防易理如上这样的,然后我们会通过参数进行拼接,最新L注拼接后的入原sql语句就是:

select * from user where username = and password = or 123 = 123 ;这样的了,那么会有一个or语句,因及预防易理只要这两个有一个是最新L注正确的源码库话,就条件成立,入原因此 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 后端

我们可以使用预编译语句(PreparedStatement,这 样的话即使我们使用sql语句伪造成参数,到了服务端的时候,这个伪造sql语句的参数也只是简单的字符,并不能起到攻击的作用。 使用正则表达式过滤传入的参数

注意: 永远也不要把未经检查的用户输入的值直接传给数据库

java中的验证字符串是否包含sql的判断 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. 源码分析

结论 

preparedStatement.setString 会判断当前参数的符号是否需要转义,是的话加的转义符 如果不需要,则直接加上引号

//完整代码 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;                }

 【编辑推荐】

一文教你探测虚拟环境是物理机、虚拟机还是容器? 比较9款代码质量工具,看看哪款更好用 推荐十个好用的程序员摸鱼网站,现在就给我玩起来! 2021年网络安全趋势:更高的预算,源码下载重点终端和云安全 为什么码农不应该在面试中同意进行编程测试
copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap