SQL注入
SQL注入是因为程序未能正确对用户的输入进行检查,将用户的输入以拼接的方式带入SQL语句,导致了SQL注入的产生。攻击者可通过SQL注入直接获取数据库信息,造成信息泄漏。
JDBC
JDBC有两个方法执行SQL语句,分别是PrepareStatement和Statement。但是推荐使用PrepareStatement,因为PrepareStatement事先对语句进行预处理,能够很好地防护SQL注入攻击;而Statement没有进行预处理,因此不能防止SQL注入。
漏洞示例代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcTest {
public static void main(String[] args) {
String db_url="";
String db_user="";
String db_pass="";
String id="";
try {
Connection connection = DriverManager.getConnection(db_url, db_user, db_pass);
//要执行的sql语句
String sql = "select * from users where id = '" + id + "'";
//由于对要查询的sql语句使用的是Statement来进行处理,而不是预处理,因此在执行sql语句的时候就存在sql注入漏洞。
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
String user = resultSet.getString("user");
String pass = resultSet.getString("pass");
System.out.println("账号是:"+user+"\t密码是:"+pass);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
漏洞修复代码(错误的示范)
即使使用到了PrepareStatement来对SQL语句进行处理,但是如果没有使用?
作为占位符,而是直接采取拼接的方式构造SQL,此时进行预编译也无用。
import java.sql.*;
public class JdbcTest {
public static void main(String[] args) {
String db_url="";
String db_user="";
String db_pass="";
String id="";
try {
Connection connection = DriverManager.getConnection(db_url, db_user, db_pass);
//这里对sql语句没有采用?作为占位符,因此也是存在sql注入漏洞的
String sql = "select * from users where id = '" + id + "'";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery(sql);
while (resultSet.next()){
String user = resultSet.getString("user");
String pass = resultSet.getString("pass");
System.out.println("账号是:"+user+"\t密码是:"+pass);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
漏洞修复代码1
将要查询的数据换为?
进行占位即可
import java.sql.*;
public class JdbcTest {
public static void main(String[] args) {
String db_url="";
String db_user="";
String db_pass="";
String id="";
try {
Connection connection = DriverManager.getConnection(db_url, db_user, db_pass);
//将要查询的数据换为?进行占位即可
String sql = "select * from users where id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery(sql);
while (resultSet.next()){
String user = resultSet.getString("user");
String pass = resultSet.getString("pass");
System.out.println("账号是:"+user+"\t密码是:"+pass);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
漏洞修复代码2
使用安全框架API进行漏洞的修复,该框架是owasp提供的一套API级别的web应用解决方案,可靠性很强。
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.codecs.Codec;
import org.owasp.esapi.codecs.OracleCodec;
import java.sql.*;
public class JdbcTest {
public static void main(String[] args) {
String db_url="";
String db_user="";
String db_pass="";
String id="";
try {
Connection connection = DriverManager.getConnection(db_url, db_user, db_pass);
Codec<Character> oracleCodec = new OracleCodec();
String sql = "select * from users where id = '"+ ESAPI.encoder().encodeForSQL(oracleCodec,id)+"'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
String user = resultSet.getString("user");
String pass = resultSet.getString("pass");
System.out.println("账号是:"+user+"\t密码是:"+pass);
}
}catch (Exception e){
e.printStackTrace();
}
}
}