最好用jdk1.8来搭建该靶场,先在源码中的
src/main/resources/db.sql
找到数据库文件,然后在navicat创建数据库test
,导入该db.sql
,然后把本地mysql数据库密码修改为1234567
,
最后用java -jar javasec-1.11.jar
来启动。启动后,端口在这里看:
默认凭据admin:admin
。
SQL注入
JDBC
安全编码:
【必须】SQL语句默认使用预编译并绑定变量
Web后台系统应默认使用预编译绑定变量的形式创建sql语句,保持查询语句和数据相分离。以从本质上避免SQL注入风险。
【必须】屏蔽异常栈
应用程序出现异常时,禁止将数据库版本、数据库结构、操作系统版本、堆栈跟踪、文件名和路径信息、SQL 查询字符串等对攻击者有用的信息返回给客户端。建议重定向到一个统一、默认的错误提示页面,进行信息过滤。
语句拼接(Statement)
漏洞代码:
// 采用Statement方法拼接SQL语句,导致注入产生
public String vul1(String id) {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);
Statement stmt = conn.createStatement();
// 拼接语句产生SQL注入
String sql = "select * from users where id = '" + id + "'";
ResultSet rs = stmt.executeQuery(sql);
...
}
这里的逻辑很简单没啥好详细解释的,就是常规jdbc连接数据库后做sql查询的一般用法。然后只是单纯拼接sql语句,没有对id参数做过滤。
运行后:
注意到payload是利用报错注入,发现和php的用法是一样的。
安全编码:
// 采用黑名单过滤危险字符,同时也容易误伤(次方案)
public static boolean checkSql(String content) {
String[] black_list = {"'", ";", "--", "+", ",", "%", "=", ">", "*", "(", ")", "and", "or", "exec", "insert", "select", "delete", "update", "count", "drop", "chr", "mid", "master", "truncate", "char", "declare"};
for (String s : black_list) {
if (content.toLowerCase().contains(s)) {
return true;
}
}
return false;
}
注意到除了用黑名单过滤,还用了toLowerCase()
强制转换为小写从而使大小写绕过的payload失效。
运行后:
只要是包含在黑名单内的payload,都返回该统一报错提示页面,保证了一定的安全性。
语句拼接(PrepareStatement)
漏洞代码:
// PrepareStatement会对SQL语句进行预编译,但如果直接采取拼接的方式构造SQL,此时进行预编译也无用。
public String vul2(String id) {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);
String sql = "select * from users where id = " + id;
PreparedStatement st = conn.prepareStatement(sql);
ResultSet rs = st.executeQuery();
}
和上面同理,直接拼接sql语句没对id做过滤,虽然做了预编译,但用错了。
运行后:
安全代码:
// 正确的使用PrepareStatement可以有效避免SQL注入,使用?作为占位符,进行参数化查询
public String safe1(String id) {
String sql = "select * from users where id = ?";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, id);
ResultSet rs = st.executeQuery();
}
Comments 1 条评论
666