java安全编码指南之:输入注入injection

简介注入问题是安全中一个非常常见的问题 , 今天我们来探讨一下java中的SQL注入和XML注入的防范 。
SQL注入什么是SQL注入呢?
SQL注入的意思是 , 用户输入了某些参数 , 最终导致SQL的执行偏离了程序设计者的本意 , 从而导致越权或者其他类型的错误 。
也就是说因为用户输入的原因 , 导致SQL的涵义发送了变化 。
拿我们最常用的登录的SQL语句来说 , 我们可能会写下面的SQL语句:
select * from user where username='' and password=''我们需要用户传入username和password 。
怎么对这个SQL语句进行注入呢?
很简单 , 当用户的username输入是下面的情况时:
somebody' or '1'='1那么整个SQL语句将会变成:
select * from user where username='somebody' or '1'='1' and password=''如果somebody是一个有效的用户 , 那么or后面的语言完全不会执行 , 最终导致不校验密码就返回了用户的信息 。
同样的 , 恶意攻击者可以给password输入下面的内容可以得到同样的结果:
' or '1'='1整个SQL解析为:
select * from user where username='somebody' and password='' or '1'='1'这条语句将会返回所有的用户信息 , 这样即使不知道确定存在的用户名也可以通过SQL语句的判断 。
这就是SQL注入 。
java中的SQL注入java中最常用的就是通过JDBC来操作数据库 , 我们使用JDBC创建好连接之后 , 就可以执行SQL语句了 。
下面我们看一个java中使用JDBC SQL注入的例子 。
先创建一个通用的JDBC连接:
public Connection getConnection() throws ClassNotFoundException, SQLException {Connection con = null;Class.forName("com.mysql.jdbc.Driver");System.out.println("数据库驱动加载成功");con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql?characterEncoding=UTF-8", "root", "");System.out.println("数据库连接成功");return con;}然后再自己拼装SQL语句然后调用:
public void jdbcWithInjection(String username,char[] password) throws SQLException, ClassNotFoundException {Connection connection = getConnection();if (connection == null) {// Handle error}try {String pwd = encodePassword(password);String sqlString = "SELECT * FROM user WHERE username = '"+ username +"' AND password = '" + pwd + "'";Statement stmt = connection.createStatement();ResultSet rs = stmt.executeQuery(sqlString);if (!rs.next()) {throw new SecurityException("User name or password incorrect");}} finally {try {connection.close();} catch (SQLException x) {}}}上面的例子中 , 只有username会发生注入 , password不会 , 因为我们使用了encodePassword方法对password进行了转换:
public String encodePassword(char[] password){return Base64.getEncoder().encodeToString(new String(password).getBytes());}使用PreparedStatement为了防止SQL注入 , 我们一般推荐的是使用PreparedStatement , java.sql.PreparedStatement可对输入参数进行转义 , 从而防止SQL注入 。
注意 , 一定要正确的使用PreparedStatement , 如果是不正确的使用 , 同样会造成SQL注入的结果 。
下面看一个不正确使用的例子:
String sqlString = "SELECT * FROM user WHERE username = '"+ username +"' AND password = '" + pwd + "'";PreparedStatement stmt = connection.prepareStatement(sqlString);ResultSet rs = stmt.executeQuery();


推荐阅读