MBG 逆向工程代码能不能防御 SQL 注入攻击

结论

先说结论,不反射或修改生成的代码,且排序从句不依赖前端数据,就可以防御

验证

直接进入逆向工程生成的代码中检查

那自然是从 MyBatis Generator 生成的 XML 映射文件看起,众所周知,MyBatis 中参数占位符 “#{}” 是可以抵御 SQL 注入的,而字符串拼接 “${}” 则会引入风险;考虑以下生成的 XML 片段,重点关注条件语句和排序从句的构造方式:

<select id="selectByExample" parameterType="com.macro.mall.model.PmsPriceDetailExample" resultMap="BaseResultMap">
  select
  ...
  <if test="_parameter != null">
    <include refid="Example_Where_Clause" />
  </if>
  <if test="orderByClause != null">
    order by ${orderByClause} <!-- 可能的注入点 -->
  </if>
</select>
<sql id="Example_Where_Clause">
  <where>
	...
    <if test="criteria.valid">
      <when test="criterion.noValue">
        and ${criterion.condition} <!-- 可能的注入点 -->
      </when>
      <when test="criterion.singleValue">
        and ${criterion.condition} #{criterion.value} <!-- 后面的值填入安全使用了参数占位符 -->
      </when>
    </if>
	...
  </where>
</sql>

可以看到,两种占位方式都有使用,毕竟字符串拼接才能动态满足条件、排序设置的要求,但这也并不意味着使用 “${}” 的地方就都是危险的,我们还要进 Java 代码看一眼

先看接口定义,找出映射文件中的 condition 和 orderByClause 是从哪里来的:

List<PmsPriceDetail> selectByExample(xxxxExample example);

那它俩自然是来自于 xxxxExample 了,进类定义继续找:

public class xxxxExample {
  protected String orderByClause;
  protected boolean distinct;
  protected List<Criteria> oredCriteria;
	...
  public static class Criterion {
    private String condition;
    ...
  }
}

出现了,分别是 Example 和其静态内部类的属性,那么 condition 的值又是在哪设的呢?

以方法 andIdEqualTo 为例:

public Criteria andIdEqualTo(Long value) {
  addCriterion("id =", value, "id");
  return (Criteria) this;
}
...
protected void addCriterion(String condition, Object value, String property) {
  if (value == null) {
      throw new RuntimeException("Value for " + property + " cannot be null");
  }
  criteria.add(new Criterion(condition, value));
}
...
public static class Criterion {
	...
	protected Criterion(String condition, Object value) {
	  this(condition, value, null);
	}
	...
  protected Criterion(String condition, Object value, String typeHandler) {
    super();
    this.condition = condition;
    this.value = value;
    this.typeHandler = typeHandler;
    if (value instanceof List<?>) {
      this.listValue = true;
    } else {
      this.singleValue = true;
    }
  }
}

破案!condition 的值来自于 xxxxExample 中的固定调用,与输入参数完全无关,可以放心了

此外,可以看到带 condition 传参的 addCriterion 方法是 protected 的,这里不建议将此方法改为 public 或通过反射调用,会有注入风险

最后,再看 orderByClause 的值是在哪设的:

public void setOrderByClause(String orderByClause) {
  this.orderByClause = orderByClause;
}

所以说设置排序从句确实是将传参拼接进去了,那么在业务层调用方法设置顺序时,就一定不要使用来自前端的参数,最好是定个枚举来用,这里就不细说了

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值