四、时刻牢记SQL注入 一般的编程书籍在教初学者的时候都不注意让他们从入门时就培养安全编程的习惯。著名的《JSP编程思想与实践》就是这样向初学者示范编写带数据库的登录系统的(数据库为MySQL): Statement stmt = conn.createStatement(); String checkUser = "select * from login where username = '" + userName + "' and userpassword = '" + userPassword + "'"; ResultSet rs = stmt.executeQuery(checkUser); if(rs.next()) response.sendRedirect("SuccessLogin.jsp"); else response.sendRedirect("FailureLogin.jsp"); 这样使得尽信书的人长期使用这样先天“带洞”的登录代码。如果数据库里存在一个名叫“jack”的用户,那么在不知道密码的情况下至少有下面几种方法可以登录: 用户名:jack 密码:' or 'a'='a 用户名:jack 密码:' or 1=1/* 用户名:jack' or 1=1/* 密码:(任意) lybbs(凌云论坛)ver 2.9.Server在LogInOut.java中是这样对登录提交的数据进行检查的: if(s.equals("") ││ s1.equals("")) throw new UserException("用户名或密码不能空。"); if(s.indexOf("'") != -1 ││ s.indexOf("\"") != -1 ││ s.indexOf(",") != -1 ││ s.indexOf("\\") != -1) throw new UserException("用户名不能包括 ' \" \\ , 等非法字符。"); if(s1.indexOf("'") != -1 ││ s1.indexOf("\"") != -1 ││ s1.indexOf("*") != -1 ││ s1.indexOf("\\") != -1) throw new UserException("密码不能包括 ' \" \\ * 等非法字符。"); if(s.startsWith(" ") ││ s1.startsWith(" ")) throw new UserException("用户名或密码中不能用空格。"); 但是我不清楚为什么他只对密码而不对用户名过滤星号。另外,正斜杠似乎也应该被列到“黑名单”中。我还是认为用正则表达式只允许输入指定范围内的字符来得干脆。 这里要提醒一句:不要以为可以凭借某些数据库系统天生的“安全性”就可以有效地抵御所有的攻击。pinkeyes的那篇《PHP注入实例》就给那些依赖PHP的配置文件中的“magic_quotes_gpc = On”的人上了一课。
|