<pre name="code" class="java">import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*
SQL注入攻击演示
*/
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
new Demo1().select();
}
public void select() throws ClassNotFoundException, SQLException{
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/jdbc";
String user="root";
String password="root";
Connection connection=DriverManager.getConnection(url, user, password);
/*
利用字符串拼接时单引号成对出现的规律,
与MySQL关系型运算符and的优先级高于or,
与MySQL查询语句的格式综合形成的漏洞,
在输入的密码上做手脚->
*/
String id="1001"; //输入账户ID
String pw="2' or '1'='1"; //输入密码。巧妙地在查询语句之后增加了一段
String sqlCode="select * from t_login where userId="+id+" and password='"+pw+"'";
//sqlCode结果:select * from t_login where userId='1001' and password='2' or '1'='1';
// -> (true/false and false) or true -> true
//等同于:select * from t_login where true; --输出所有语句
//-------------------------------------
Statement st=connection.createStatement();//可以改进的代码...
ResultSet rs= st.executeQuery(sqlCode);
//-------------------------------------
//简单输出
if(rs.first()){
do{
System.out.print(rs.getInt(1) +"\t");
System.out.print(rs.getString(2) +"\t");
System.out.println();
}while(rs.next());
}else{
System.out.println("登录信息不正确,登陆失败!");
}
/*
当用户ID和密码正确输入时的结果:返回表中该用户的账户ID与密码
1001 123456
当受到注入攻击输出结果:输出了该表中所有用户的账户密码信息。
1001 123456
1002 233333
1003 888888
1004 666666
*/
rs.close();
st.close();
connection.close();
}
}
防止注入攻击的改进方法:使用PreparedStatement
将上述被//------标记的两行代码替换为如下代码:
PreparedStatement st=connection.prepareStatement("select * from t_login where userid=? and password=?");
st.setString(1, id);
st.setString(2, pw);
ResultSet rs=st.executeQuery();//注意:换方法了,没有传参
当受到注入攻击输出结果:登录信息不正确,登陆失败!