Blog / 阅读

【Java编程】JDBC注入攻击-Statement 与 PreparedStatement

by admin on 2014-05-14 13:14:41 in ,



通过SQL注入攻击比较Statement和PreparedStatement。当然这两者还有很多其他方面的不同,在之后的blog中会继续更新。
【Statement查询】
1、在DBHelper.java中新增一个通过username和password查询user的方法。
[java] view plaincopy
public static void queryByUser(String username,String password) {  
    Connection conn = DBConnection.getConnection();  
    Statement stmt = null;  
    ResultSet rs = null;  
    try {  
        stmt = conn.createStatement();  
        rs = stmt.executeQuery("select * from user where username = '" + username+"' and password='"+password+"'");  
        while (rs.next()) {  
            User user = new User();  
            user.setId(rs.getInt("id"));  
            user.setUsername(rs.getString("username"));  
            user.setPassword(rs.getString("password"));  
            user.setGender(rs.getBoolean("gender"));  
            user.setRegtime(rs.getDate("regtime"));  
            System.out.println(user.toString());  
        }  
    } catch (SQLException e) {  
        e.printStackTrace();  
    }finally {  
        DBConnection.closeResultSet(rs);  
        DBConnection.closeStatement(stmt);  
        DBConnection.closeConnection(conn);  
    }  
}  
2、在DBHelperTest.java中新增一个测试方法进行测试
[java] view plaincopy
public void queryByUserTest(){  
    DBHelper.queryByUser("jack", "jack");  
}  
Java端测试结果:
User [id=2, username=jack, password=jack, gender=true, regtime=2014-05-14]
测试结果表明:通过一个有效的用户名和密码,成功获取到了该用户的所有信息。
3、 通过MySQL日志信息,跟踪查询sql语句。具体方法参考 MySQL如何跟踪sql语句。
打开mysql.log日志,跟踪查看最新的日志,如下所示:
[sql] view plaincopy
140514 10:16:13    15 Query SET character_set_results = NULL  
           15 Query SHOW VARIABLES  
           15 Query SHOW WARNINGS  
           15 Query SHOW COLLATION  
           15 Query SET autocommit=1  
           15 Query select * from user where username = 'jack' and password='jack'  
           15 Quit    
日志信息表明:数据库端执行了正常的查询语句。
4、在DBHelperTest.java中新增一个注入攻击测试,用户名输入:hack(任意字符串),密码输入:' or '1'='1
[java] view plaincopy
public void queryByUserInjectTest(){  
    DBHelper.queryByUser("hack", "' or '1'='1");  
}  
Java端测试结果:
User [id=1, username=andy, password=andy, gender=true, regtime=2014-05-13]
User [id=2, username=jack, password=jack, gender=true, regtime=2014-05-14]
User [id=3, username=rose, password=rose, gender=false, regtime=2014-05-13]
测试结果表明:通过注入攻击,一个非法的用户可以获取到user表中的所有用户信息,太可怕了!
5、通过MySQL日志信息,跟踪查询sql语句,分析数据端到底发生了什么事情。
[sql] view plaincopy
140514 10:23:14    16 Connect   root@localhost on db_bbs  
           16 Query SET NAMES latin1  
           16 Query SET character_set_results = NULL  
           16 Query SHOW VARIABLES  
           16 Query SHOW WARNINGS  
           16 Query SHOW COLLATION  
           16 Query SET autocommit=1  
           16 Query select * from user where username = 'hack' and password='' or '1'='1'  
           16 Quit    
数据库端执行了一条语句:
select * from user where username = 'hack' and password='' or '1'='1'
因为where条件恒为真,相当于执行了:
select * from user 
通过这条语句获取到了所有的用户信息。
【PreparedStatement查询】
1、在DBHelper.java中新增一个通过username和password查询user的方法。
[java] view plaincopy
public static void queryPrepareByUser(String username,String password) {  
        Connection conn = DBConnection.getConnection();  
        PreparedStatement ps = null;  
        ResultSet rs = null;  
        try {  
            ps = conn.prepareStatement("select * from user where username = ? and password = ?");  
            ps.setString(1,username);// 设置占位符参数  
            ps.setString(2, password);  
            rs = ps.executeQuery();  
            while (rs.next()) {  
                User user = new User();  
                user.setId(rs.getInt("id"));  
                user.setUsername(rs.getString("username"));  
                user.setPassword(rs.getString("password"));  
                user.setGender(rs.getBoolean("gender"));  
                user.setRegtime(rs.getDate("regtime"));  
                System.out.println(user.toString());  
            }  
        } catch (SQLException e) {  
            e.printStackTrace();  
        } finally {  
            DBConnection.closeResultSet(rs);  
            DBConnection.closeStatement(ps);  
            DBConnection.closeConnection(conn);  
        }  
    }  
2、在DBHelperTest.java中新增一个测试方法进行测试
[java] view plaincopy
public void queryByPreparedUserTest(){  
        DBHelper.queryPrepareByUser("jack", "jack");  
    }  
Java端测试结果:
User [id=2, username=jack, password=jack, gender=true, regtime=2014-05-14]
测试结果表明:通过一个合法的用户名和密码,得到了该用户的所有信息。
3、 通过MySQL日志信息,跟踪查询sql语句。
[sql] view plaincopy
140514 10:37:04    17 Connect   root@localhost on db_bbs  
           17 Query SET NAMES latin1  
           17 Query SET character_set_results = NULL  
           17 Query SHOW VARIABLES  
           17 Query SHOW WARNINGS  
           17 Query SHOW COLLATION  
           17 Query SET autocommit=1  
           17 Prepare   select * from user where username = ? and password = ?  
           17 Execute   select * from user where username = 'jack' and password = 'jack'  
           17 Close stmt      
           17 Quit    
日志信息表明:数据库端首先执行了预编译,并执行了正常的查询语句。
4、在DBHelperTest.java中新增一个注入攻击测试:
[java] view plaincopy
public void queryByPreparedUserInjectTest(){  
    DBHelper.queryPrepareByUser("hack", "' or '1'='1");  
}  
Java端测试结果:
没有打印出任何消息,即没有获取到用户的信息,难道注入攻击无效!
5、通过MySQL日志信息,跟踪查询sql语句,为什么注入攻击无效了?
[sql] view plaincopy
140514 10:42:42    19 Query SET character_set_results = NULL  
           19 Query SHOW VARIABLES  
           19 Query SHOW WARNINGS  
           19 Query SHOW COLLATION  
           19 Query SET autocommit=1  
           19 Prepare   select * from user where username = ? and password = ?  
           19 Execute   select * from user where username = 'hack' and password = '\' or \'1\'=\'1'  
           19 Close stmt      
           19 Quit    
原来是执行了:select * from user where username = 'hack' and password = '\' or \'1\'=\'1'


写评论

相关文章

上一篇:CentOS 64位修复openssl严重漏洞办法

下一篇:PHP一句话后门大全

评论

写评论

* 必填.

分享

栏目

赞助商


热门文章

Tag 云