Ebean框架常见SQL注入场景
字数 1445 2025-08-07 00:34:58

Ebean框架SQL注入安全指南

1. Ebean框架概述

Ebean是一个ORM框架,几乎支持所有JPA功能同时兼顾Mybatis的灵活性,具有以下特点:

  • 支持类型约束的安全SQL语句构建
  • 兼容多种数据库
  • 提供实用的增强功能
  • 对SQL注入有一定防护机制

1.1 基本使用方法

1.1.1 实体类操作

实体类继承Model类,自带增删改方法:

Author author = new Author(null, "Lorin", "Lorin");
author.save();  // 新增记录

1.1.2 查询接口

高版本已弃用Ebean/EbeanServer,迁移到:

  • io.ebean.Database
  • io.bean.DB

1.1.3 Q实体增强类

Ebean会为实体类生成对应的Q类(如Author → QAuthor),功能更强大且操作有返回值:

QAuthor().id.eq(1).findOne();  // 查询id=1的记录

1.2 参数绑定方式

1.2.1 位置参数和命名参数

支持?:param两种方式:

// 使用?位置参数
Ebean.createSqlQuery(sql).setParameter(1, name).findList();

// 使用:param命名参数
Ebean.createSqlQuery(sql).setParameter("paramName", value).findList();

1.2.2 表达式处理

Ebean表达式已进行预编译处理:

server.find(Content.class).where().eq("name", sort).findList();

2. 常见SQL注入场景

2.1 OrderBy排序注入

风险点:OrderBy无法预编译,直接拼接存在注入风险

危险接口:

  • io.ebean.OrderBy
    • asc(String propertyName)
    • desc(String propertyName)
  • io.ebean.Query
    • order(String var1)
  • io.ebean.ExpressionList
    • orderBy(String var1)

危险示例

server.find(Content.class).order(sort).findList();  // sort参数直接拼接

攻击示例
攻击者可通过构造恶意sort参数进行报错注入获取数据库信息(如获取SA用户)

2.2 执行任意SQL、函数和存储过程

Raw表达式

虽然支持预编译,但直接拼接仍存在风险:

.raw("add_days(orderDate, 10) < ?", someDate)  // 安全用法
.raw("add_days(orderDate, 10) < " + someDate)  // 危险用法

rawOrEmpty()方法同理需要注意

2.3 执行自定义SQL

2.3.1 直接获取Connection执行SQL

通过事务获取Connection后直接执行SQL存在风险:

try (Transaction transaction = server.beginTransaction()) {
    Connection connection = transaction.getConnection();
    Statement stmt = connection.prepareStatement(sql);  // 如果sql包含用户输入且未过滤
    transaction.commit();
} catch (SQLException e) {
    e.printStackTrace();
}

2.3.2 常见危险API

以下API如果直接拼接SQL且未过滤,存在注入风险:

  • createSqlQuery(String sql)
  • sqlQuery(String var1)
  • sqlUpdate(String var1)
  • createCallableSql(String var1)
  • createSqlUpdate(String sql)
  • findNative(Class<T> var1, String var2)

安全示例

String sql = "select id,name from customer where name like ?";
Customer customer = DB.findNative(Customer.class, sql)
                    .setParameter("Jo%")
                    .findOne();

2.3.3 RawSqlBuilder

直接拼接用户输入存在风险:

String sql = "SELECT v.id, c.company, c.postcode \n" +
             "FROM venue v \n" +
             "JOIN contact c ON (c.id = v.id) \n" +
             "WHERE REPLACE(c.postcode,LIKE '%" + q + "%' \n" +
             "OR c.company LIKE '%" + query + "%'";

RawSql rawSql = RawSqlBuilder.unparsed(sql)  // 直接拼接用户输入query
    .columnMapping("v.id", "id")
    .columnMapping("c.company", "contact.company")
    .columnMapping("c.postcode", "contact.postcode")
    .create();

2.4 动态列名注入

直接使用用户输入作为列名存在风险:

Content.find.query().select(sort).findSingleAttributeList();  // sort直接拼接

3. 安全防护建议

3.1 参数化查询

始终使用参数化查询:

  • 使用?位置参数
  • 使用:param命名参数

3.2 特殊场景防护

对于OrderBy排序:

  1. 白名单验证:

    • 设置表名/列名白名单
    • 输入不在白名单内则使用默认值
  2. 间接引用:

    String safeSort;
    switch(userInput) {
        case "1": safeSort = "name"; break;
        case "2": safeSort = "date"; break;
        default: safeSort = "id";
    }
    

对于动态SQL:

  1. 使用SDK进行输入检查
  2. 避免直接拼接用户输入
  3. 对必要拼接内容进行严格过滤

3.3 其他建议

  • 最小权限原则:数据库账户使用最小必要权限
  • 日志监控:记录所有SQL操作日志
  • 定期安全审计:检查所有SQL构建点

4. 总结

Ebean框架虽然提供了一定的SQL注入防护,但在以下场景仍需特别注意:

  1. OrderBy排序场景
  2. 原始SQL执行场景
  3. 动态列名/表名场景
  4. 自定义函数/存储过程调用场景

安全开发的关键在于:

  • 始终使用参数化查询
  • 对必须拼接的场景进行严格过滤
  • 采用白名单或间接引用机制
  • 定期进行代码安全审计
Ebean框架SQL注入安全指南 1. Ebean框架概述 Ebean是一个ORM框架,几乎支持所有JPA功能同时兼顾Mybatis的灵活性,具有以下特点: 支持类型约束的安全SQL语句构建 兼容多种数据库 提供实用的增强功能 对SQL注入有一定防护机制 1.1 基本使用方法 1.1.1 实体类操作 实体类继承Model类,自带增删改方法: 1.1.2 查询接口 高版本已弃用Ebean/EbeanServer,迁移到: io.ebean.Database io.bean.DB 1.1.3 Q实体增强类 Ebean会为实体类生成对应的Q类(如Author → QAuthor),功能更强大且操作有返回值: 1.2 参数绑定方式 1.2.1 位置参数和命名参数 支持 ? 和 :param 两种方式: 1.2.2 表达式处理 Ebean表达式已进行预编译处理: 2. 常见SQL注入场景 2.1 OrderBy排序注入 风险点 :OrderBy无法预编译,直接拼接存在注入风险 危险接口: io.ebean.OrderBy asc(String propertyName) desc(String propertyName) io.ebean.Query order(String var1) io.ebean.ExpressionList orderBy(String var1) 危险示例 : 攻击示例 : 攻击者可通过构造恶意sort参数进行报错注入获取数据库信息(如获取SA用户) 2.2 执行任意SQL、函数和存储过程 Raw表达式 虽然支持预编译,但直接拼接仍存在风险: rawOrEmpty() 方法同理需要注意 2.3 执行自定义SQL 2.3.1 直接获取Connection执行SQL 通过事务获取Connection后直接执行SQL存在风险: 2.3.2 常见危险API 以下API如果直接拼接SQL且未过滤,存在注入风险: createSqlQuery(String sql) sqlQuery(String var1) sqlUpdate(String var1) createCallableSql(String var1) createSqlUpdate(String sql) findNative(Class<T> var1, String var2) 安全示例 : 2.3.3 RawSqlBuilder 直接拼接用户输入存在风险: 2.4 动态列名注入 直接使用用户输入作为列名存在风险: 3. 安全防护建议 3.1 参数化查询 始终使用参数化查询: 使用 ? 位置参数 使用 :param 命名参数 3.2 特殊场景防护 对于OrderBy排序: 白名单验证: 设置表名/列名白名单 输入不在白名单内则使用默认值 间接引用: 对于动态SQL: 使用SDK进行输入检查 避免直接拼接用户输入 对必要拼接内容进行严格过滤 3.3 其他建议 最小权限原则:数据库账户使用最小必要权限 日志监控:记录所有SQL操作日志 定期安全审计:检查所有SQL构建点 4. 总结 Ebean框架虽然提供了一定的SQL注入防护,但在以下场景仍需特别注意: OrderBy排序场景 原始SQL执行场景 动态列名/表名场景 自定义函数/存储过程调用场景 安全开发的关键在于: 始终使用参数化查询 对必须拼接的场景进行严格过滤 采用白名单或间接引用机制 定期进行代码安全审计