-
概述
顾名思义,SQL注入就是将SQL语句被注入到应用程序中。攻击者可以利用SQL注入达到越权获取或修改数据甚至执行任何系统命令的目的。SQL注入是广泛存在的危险性极高的应用程序漏洞。
-
SQL注入的示例
下面的代码用于完成登录验证,但未对用户输入进行充分的有效性检查和元字符的转义,从而带来了SQL注入弱点:
conn = pool.getConnection( ); String sql = "select * from user where username='" + username +"' and password='" + password + "'"; stmt = conn.createStatement(); rs = stmt.executeQuery(sql); if (rs.next()) { loggedIn = true; out.println("Successfully logged in"); } else { out.println("Username and/or password not recognized"); } |
攻击者可以输入含有SQL元字符的用户名改变原有SQL语句的功能/意图。如通过输入下面的用户名
admin' OR '1'='1 |
和空格口令,程序中生成的SQL语句变为
select * from user where username='admin' OR '1'='1' and password=' ' |
因为上面的SQL查询语句永远返回用户名为admin的记录,所以攻击者不需要提供正确的口令就能够登录。通过同样的方法可以使这段程序执行任何SQL语句。
-
SQL注入的防范
避免SQL注入的关键在于避免使用字符串动态拼接SQL,而是借助参数化变量生产SQL。具体的在java开发中使用PreparedStatement,如
String selectStatement = "SELECT * FROM User WHERE userId = ? "; PreparedStatement prepStmt = con.prepareStatement(selectStatement); prepStmt.setString(1, userId); ResultSet rs = prepStmt.executeQuery(); |
但要注意虽使用PreparedStatement,而未使用参数化的错误做法,如下:
String strUserName = request.getParameter("Txt_UserName"); PreparedStatement prepStmt = con.prepareStatement("SELECT * FROM user WHERE userId = '+strUserName+'"); |