zoukankan      html  css  js  c++  java
  • java每日一学--数据校验20131008

     数据校验

    规则1.1 禁止直接使用外部输入来拼接SQL语句以防止SQL注入

    说明:如果对于外部输入的数据未经处理,直接用于拼接SQL语句,攻击者可以通过构造特殊形式的输入来改变程序中原本要执行的SQL逻辑,形成SQL注入攻击,导致系统功能异常、信息泄露、数据被非法修改等安全问题。
    错误示例:

    public void doPrivilegedAction(String username, char[] password) throws SQLException 
        { 
            /* … */ 
            try 
            { 
                String pwd = hashPassword(password); 
                String sqlString = "SELECT * FROM db_user WHERE username = '" 
                        + username + "' AND password = '" + pwd + "'"; 
                Statement stmt = connection.createStatement(); 
                ResultSet rs = stmt.executeQuery(sqlString); 
                // Authenticate … 
            } 
            /* … */ 
        } 
    

      上面的代码使用用户输入来拼接SQL语句,但又没有对用户的输入做校验,存在SQL注入风险。当用户为username输入值:jack' OR '1' = '1
    SQL语句变成了:SELECT * FROM db_user WHERE username='jack' OR '1'='1'
    AND

    password=<PASSWORD>
    如果jack是有效用户,这样便绕开了对口令的验证。

    推荐做法1校验输入长度,并且使用PreparedStatement来防范SQL注入。

    public void doPrivilegedAction(String username, char[] password) 
                throws SQLException 
        { 
            /* … */ 
            try 
            { 
                String pwd = hashPassword(password); 
                // Ensure that the length of user name is legitimate 
                if ((username.length()) > 8) 
                { 
                    // Handle error 
                } 
                String sqlString = "select * from db_user where username=? and password=?"; 
                PreparedStatement stmt = connection.prepareStatement(sqlString); 
                stmt.setString(1, username); 
                stmt.setString(2, pwd); 
                ResultSet rs = stmt.executeQuery(); 
                // Authenticate … 
            } 
            /* … */ 
        } 
    

      使用PreparedStatement,输入的参数无法改变原始的SQL语义。上例中,即使攻击者插入类似 jack or 1=1的字符串,也只会将此字符串
    当做username来查询。
    推荐做法2使用存储过程

    public void doPrivilegedAction(String username, 
    char[] password) 
                throws 
    SQLException 
        { 
            /* … */ 
            try 
            { 
                
    String pwd = hashPassword(password); 
                // Ensure that the length of user name is 
    legitimate 
                
    if ((username.length()) > 
    8) 
                
    { 
                    
    // Handle error 
    
                } 
                
    String sqlString = "select * from db_user where 
    username=? and password=?"; 
    
                CallableStatement cs = connection.prepareCall("{call sp_getUser(?,?)}"); 
                
    cs.setString(1, username); 
                
    cs.setString(2, pwd); 
                
    ResultSet rs = cs.executeQuery(); 
                // Authenticate … 
    
            } 
            /* … */ 
      
      } 
    

    使用存储过程的效果和使用PreparedStatement类似,其区别是存储过程需要先将SQL语句定义在数据库中。但需要注意的是,存储过程中也可能

    存在注入问题,因此应该尽量避免在存储过程内使用动态的SQL语句。
    推荐做法3对外部输入进行转义

    public void doPrivilegedAction(String username, char[] password) 
                throws SQLException 
        { 
            /* … */ 
            try 
            { 
                String pwd = hashPassword(password); 
                Codec oe = new OracleEncoder(); 
                String susername = oe.encode(username); 
                String spwd = oe.encode(pwd); 
                String sqlString = "SELECT * FROM db_user WHERE username = '" 
                        + susername + "' AND password = '" + spwd + "'"; 
                Statement stmt = connection.createStatement(); 
                ResultSet rs = stmt.executeQuery(sqlString); 
                // Authenticate … 
            } 
            /* … */ 
        } 
    

      对于PreparedStatement无法适用或者存储过程内部也存在动态构造SQL语句的情形,则可以考虑对外部输入做转义。每个DBMS都有一个字符转义机制
    来告知DBMS输入的是数据而不是代码,如果将所有用户的输入都进行转义,那么DBMS就不会混淆数据和代码,也就不会出现SQL注入了。针对每种数据
    的转义机制实现,可以使用现有的API工具,比如OWASP ESAPIescaping
    routines
    ,也可以使用自己的实现。

      

  • 相关阅读:
    Java的 Annotation 新特性
    Java 枚举
    Java 泛型
    Linux kali信息探测以及 Nmap 初体验
    静态导入 ()
    Java foreach循环
    Java 可变参数
    炫酷的CSS3响应式表单
    关于CSS选择器连续性的问题
    简述ECMAScript6新增特性
  • 原文地址:https://www.cnblogs.com/tjw-nau/p/3357003.html
Copyright © 2011-2022 走看看