曾经在做平台登录模块时,遇到SQL注入漏洞,具体情况如下:
Connection ct = null;
String DBURL = "jdbc:mysql://localhost:3306/sqdb1";
String DBUSER = "root";
String DBPASS = "";
Statement sm=null;
ResultSet rs =null;
response.setContentType("text/html;charset=gbk");
PrintWriter out = response.getWriter();
try{
String u = request.getParameter("username");
String p = request.getParameter("passwd");
Class.forName("com.mysql.jdbc.Driver");
ct = DriverManager.getConnection(DBURL,DBUSER,DBPASS);
sm=ct.createStatement();
//注入漏洞
//rs= sm.executeQuery("select * from users where username='"+u+"' and passwd='"+p+"'");
rs= sm.executeQuery("select passwd from users where username='"+u+"'");
if(rs.next()){
//用户名存在
String dbPasswd=rs.getString(1);
if(dbPasswd.equals(p)){
HttpSession hs = request.getSession(true);
//修改session存在时间
hs.setMaxInactiveInterval(20);
hs.setAttribute("pass", "ok");
response.sendRedirect("welcome?uname="+u);
}
}else{
response.sendRedirect("Login");
}
}catch(Exception e){
e.printStackTrace();
}finally{
try {
if (ct != null) {
ct.close();
}
if (sm != null) {
sm.close();
}
if (rs != null) {
rs.close();
}
} catch (Exception e2) {
// TODO: handle exception
}
}
若使用注释中的SQL语句rs进行用户名密码的匹配,会出现一个很大的问题:
当我用户名随意输入,密码的输入的是: 1‘ or 1=’1
此时rs中的sql语句就变成了:
select * from users where username=‘1’ and passwd='1' or 1='1'
注意到上面这条语句,一定会返回从表中查询到的记录,因为最后一个条件必然成立。
这就是所谓的SQL注入漏洞。
解决方案我已经给出,就是上面的代码。