专栏名称: 合天网安实验室
为广大信息安全爱好者提供有价值的文章推送服务!
目录
相关文章推荐
创伙伴  ·  欢迎你也加入创伙伴知识星球 ·  8 小时前  
独角兽智库  ·  AI算力、机器人、AI眼镜、汽车、消费电子板 ... ·  3 天前  
创伙伴  ·  欢迎你也加入创伙伴知识星球 ·  3 天前  
51好读  ›  专栏  ›  合天网安实验室

Ebean框架常见SQL注入场景

合天网安实验室  · 公众号  ·  · 2024-07-15 16:27

正文

Ebean是一个ORM框架,利用其可以快速构建有类型约束的安全的SQL语句。本文主要介绍该框架常见的SQL注入场景。給代码安全审计提供一定的思路。

0x01 关于Ebean

Ebean ORM框架,可以说几乎支持所有的JPA的功能同时也兼顾了Mybatis的灵活性,并且还有一些较实用的增加功能。同时兼容多种数据库,可以很方便的实现对应的sql操作,在一定程度上对SQL注入也有一定的防护。

1.1 Ebean基本使用方法

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

例如新增记录:

Author author = new Author(null, "Lorin", "Lorin");
author.save();

1.1.2 Ebean/EbeanServer&DB/database

可以使用Ebean或 EbeanServer 来创建和执行查询。高版本已经弃用,会迁移到io.ebean.Database/io.bean.DB:

1.1.3 Q实体增强类

Ebean可以对对应的entity生成出”Q实体类“,比如Author就会生成出QAuthor类,相比于普通实体类,QAuthor类的功能更强大,而且相比于普通实体类,QAuthor类的增删改有返回值,可以用来判断操作是否成功,普通实体类的增删改没有返回值。

例如查询id=1的内容:

QAuthor().id.eq(1).findOne();

1.2 常见参数绑定方式

1.2.1 ?和:param

跟其他框架类似,均支持?和:param的方式进行参数绑定。

类似SqlQuery可以直接执行自定义SQL,可以通过setParameter()方法进行参数绑定(多参数时可以使用setParameters()方法)。

Ebean.createSqlQuery(sql).setParameter(1,name).findList();

查看具体的SQL日志,name参数已经进行预编译处理:

使用:param同理。

1.2.2 表达式自身处理

Ebean提供的表达式已经进行了相应的预编译处理,使用也比较方便,例如这里的eq,查询对应name的用户信息:

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

查看对应的日志已经进行了参数绑定:

0x02 常见SQL注入场景

2.1 OrderBy排序

因为OrderBy场景下是没办法进行预编译处理的,跟所有常见的orm框架一样,如果没有做相应的处理的话是存在SQL注入风险的。

常见的接口有:

  • io.ebean.OrderBy

    • Query asc(String propertyName)

    • Query desc(String propertyName)

  • io.ebean.Query

    • Query order(String var1);

  • io.ebean.ExpressionList;

    • Query orderBy(String var1);

举个例子,例如下面的SQL,通过用户传入的sort参数进行排序,因为是直接SQL拼接的,会存在SQL注入风险:

server.find(Content.class).order(sort).findList();

这里尝试报错注入,成功获取到数据库用户SA(数据库是H2 database)

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

在查询where子句中经常需要包含执行任意SQL、函数和存储过程的需求。因为这里存在大量的自定义sql场景,如果直接拼接的话会存在SQL注入的风险,所以在审计时可以重点关注,下面列举一些常见的function:

  • Raw expressions
    Raw表达式允许在查询的where子句中使用对应数据库的函数或表达式。例如:```java
    .raw("add_days(orderDate, 10) < ?", someDate)


    这里使用?进行预编译处理了,如果直接进行SQL拼接的话会存在注入风险。

rawOrEmpty()同理。

2.3 执行自定义SQL

由于实际业务比较复杂,常规的function并不能很好的完成业务需要,同样的Ebean也提供了很多自定义SQL的方法:

2.3.1 获取java.sql.Connection对象执行原始SQL

java.sql.Connection对象可以从事务中返回,此时就可以直接调用对应的方法执行任意的sql,同样的如果使用不当存在sql拼接的话也会存在SQL注入的风险:

try (Transaction transaction = server.beginTransaction()) {

Connection connection = transaction.getConnection();
// use raw JDBC
Statement stmt = connection .prepareStatement(sql);
......
transaction.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
}

2.3.2 Ebean常见API

通过下面的api可以直接生成对应的sql进行执行,如果相关的参数没有经过过滤或者类似?和:param预编译处理, 直接进行拼接 的话,是存在SQL注入风险的。

  • createSqlQuery(String sql)

  • sqlQuery(String var1);

  • sqlUpdate(String var1);

  • createCallableSql(String var1);

  • createSqlUpdate(String sql)

  • findNative(Class\ var1,String var2)

  • ......

例如如下例子,这里通过?进行预编译处理,然后再通过setParameter进行赋值,避免了SQL注入的风险:

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

如果直接使用字符串拼接的话(尤其是类似orderby排序、动态表名等场景),如果没有经过相关的过滤,会存在SQL注入的风险,在审计时可以重点关注下。

2.3.2 RawSqlBuilder

一般来说可以通过RawSql显式指定要执行的SQL语句,并将列显式映射到对应的属性。但是使用不当也会出现SQL注入的风险。

例如如下例子,通过用户输入的query进行sql拼接,会存在sql注入的风险:

public






请到「今天看啥」查看全文