Hello-java-Sec靶场

cvestone 发布于 2024-08-20 490 次阅读 716 字 预计阅读时间: 3 分钟


最好用jdk1.8来搭建该靶场,先在源码中的src/main/resources/db.sql找到数据库文件,然后在navicat创建数据库test,导入该db.sql,然后把本地mysql数据库密码修改为1234567
最后用java -jar javasec-1.11.jar 来启动。启动后,端口在这里看:

2024-08-20-08-51-47
默认凭据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参数做过滤。

运行后:
2024-08-20-09-11-38
注意到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失效。
运行后:
2024-08-20-09-16-38
2024-08-20-09-18-12
只要是包含在黑名单内的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做过滤,虽然做了预编译,但用错了。
运行后:
2024-08-20-09-26-31
安全代码:

// 正确的使用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();
}
                    
  • alipay_img
  • wechat_img
此作者没有提供个人介绍
最后更新于 2024-08-20