c语言sscanf函数的用法是什么
315
2022-11-15
MyBatis Generator生成的$ sql是否存在注入风险详解
目录代理商sql注入问题排查准备测试demoentityProduct.javaProductExample.java控制层ProductController.javaservice层ProductService.javaProductServiceImpl.javamapperProductController.javaProductController.xml测试测试1:正常逻辑测试测试2:测试不存在的表字段测试3:like注入测试1测试3:like注入测试2结论附录
代理商sql注入问题排查
经全面排查,代理商中sql层使用'$'获取对象的只有一种类型,代码格式如下:
and ${criterion.condition}
and ${criterion.condition} #{criterion.value}
and ${criterion.condition} #{criterion.value} and
#{criterion.secondValue}
and ${criterion.condition}
open="(" close=")" separator=","> #{listItem}
open="(" close=")" separator=",">
#{listItem}
接下来我们在测试demo中复现下情况:
准备测试demo
entity
Product.java
普通实体类,对应数据库中product表,表结构见附录:
package com.zhrb.springcloud.entity;
import lombok.Data;
import lombok.ToString;
/**
* @ClassName Product
* @Description TODO
* @Author Administrator
* @Date 2019/9/3 14:26
* @Version
*/ @Data @ToString public class Product {
//主键
private Long pid;
//产品名称
private String productName;
// 来自哪个数据库,因为微服务架构可以一个服务对应一个数据库,同一个信息被存储到不同数据库
private String dbSource;
}
ProductExample.java
同代理商环境一样的动态条件类:
package com.zhrb.springcloud.entity;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName ProductExample
* @Description TODO
* @Author Administrator
* @Date 2019/9/20 9:07
* @Version
*/ public class ProductExample {
/**
* This field was generated by MyBatis Generator. * This field corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected String orderByClause;
/**
* This field was generated by MyBatis Generator. * This field corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected boolean distinct;
/**
* This field was generated by MyBatis Generator. * This field corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected List
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public ProductExample() {
oredCriteria = new ArrayList
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public String getOrderByClause() {
return orderByClauseLqZHAp;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public boolean isDistinct() {
return distinct;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public List
return oredCriteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
/**
* This class was generated by MyBatis Generator. * This class corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected abstract static class GeneratedCriteria {
protected List
protected GeneratedCriteria() {
super();
criteria = new ArrayList
}
public boolean isValid() {
return criteria.size() > 0;
}
public List
return criteria;
}
public List
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
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));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("PID is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("PID is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("PID =", value, "pid");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("PID <>", value, "pid");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("PID >", value, "pid");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("PID >=", value, "pid");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("PID <", value, "pid");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("PID <=", value, "pid");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("PID like", value, "pid");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("PID not like", value, "pid");
return (Criteria) this;
}
public Criteria andIdIn(List
addCriterion("PID in", values, "pid");
return (Criteria) this;
}
public Criteria andIdNotIn(List
addCriterion("PID not in", values, "pid");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("PID between", value1, value2, "pid");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("PID not between", value1, value2, "pid");
return (Criteria) this;
}
}
/**
* This class was generated by MyBatis Generator. * This class corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated do_not_delete_during_merge
*/ public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
/**
* This class was generated by MyBatis Generator. * This class corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
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;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}
控制层ProductController.java
package com.zhrb.springcloud.controller;
import com.zhrb.springcloud.entity.Product;
import com.zhrb.springcloud.entity.ProductExample;
import com.zhrb.springcloud.service.ProductService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
import java.util.List;
/**
* @ClassName ProductController
* @Description TODO
* @Author zhrb
* @Date 2019/9/3 15:18
* @Version
*/ @RestController @RequestMapping("/product")
@MapperScan("com.zhrb.springcloud.mapper")
@Api(value = "/product",description = "商品管理 程序员小圈圈",position = 1)
public class ProductController {
@Autowired
private ProductService productService;
@ApiOperation(value="测试是否预编译", notes="测试是否预编译")
@GetMapping(value = "/testList")
public List
ProductExample example = new ProductExample();
example.createCriteria().andIdLike("1' or '1=1");
List
for (Product p :productList){
p.setProductName(p.getProductName()+"本条数据来自8001");
}
return productList;
}
}
service层
ProductService.java
package com.zhrb.springcloud.service;
import com.zhrb.springcloud.entity.Product;
import com.zhrb.springcloud.entity.ProductExample;
import java.util.List;
/**
* @ClassName ProductService
* @Description TODO
* @Author Administrator
* @Date 2019/9/3 15:15
* @Version
*/ public interface ProductService {
List
}
ProductServiceImpl.java
package com.zhrb.springcloud.service.impl;
import com.zhrb.springcloud.entity.Product;
import com.zhrb.springcloud.entity.ProductExample;
import com.zhrb.springcloud.mapper.ProductMapper;
import com.zhrb.springcloud.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @ClassName ProductServiceImpl
* @Description TODO
* @Author Administrator
* @Date 2019/9/3 15:16
* @Version
*/ @Service public class ProductServiceImpl implements ProductService{
@Autowired
private ProductMapper productMapper;
@Override
public List
return productMapper.testList(example);
}
}
mapper
ProductController.java
package com.zhrb.springcloud.mapper;
import com.zhrb.springcloud.entity.Product;
import com.zhrb.springcloud.entity.ProductExample;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @ClassName ProductMapper
* @Description TODO
* @Author Administrator
* @Date 2019/9/3 14:55
* @Version
*/
@Mapper
public interface ProductMapper {
List
}
ProductController.xml
select
pid, product_name, db_source
from product
order by ${orderByClause}
and ${criterion.condition}
and ${criterion.condition} #{criterion.value}
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
and ${criterion.condition}
#{listItem}
测试
测试1:正常逻辑测试
首先按照正常代码逻辑测试,校验代码是否成功,测试结果截图如下:
可以看到调用成功,证明代码逻辑没问题,接下来进行异常测试:
测试2:测试不存在的表字段
修改ProductExample.java如下(数据库中字段为pid,无id,故先将pid改为id测试不存在字段编译过程):
package com.zhrb.springcloud.entity;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName ProductExample
* @Description TODO
* @Author Administrator
* @Date 2019/9/20 9:07
* @Version
*/ public class ProductExample {
/**
* This field was generated by MyBatis Generator. * This field corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected String orderByClause;
/**
* This field was generated by MyBatis Generator. * This field corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected boolean distinct;
/**
* This field was generated by MyBatis Generator. * This field corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected List
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public ProductExample() {
oredCriteria = new ArrayList
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public String getOrderByClause() {
return orderByClause;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public boolean isDistinct() {
return distinct;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public List
return oredCriteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
/**
* This method was generated by MyBatis Generator. * This method corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
/**
* This class was generated by MyBatis Generator. * This class corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
protected abstract static class GeneratedCriteria {
protected List
protected GeneratedCriteria() {
super();
criteria = new ArrayList
}
public boolean isValid() {
return criteria.size() > 0;
}
public List
return criteria;
}
public List
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
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));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value)http:// {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
}
/**
* This class was generated by MyBatis Generator. * This class corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated do_not_delete_during_merge
*/ public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
/**
* This class was generated by MyBatis Generator. * This class corresponds to the database table CPT_DLS_CONFIG * * @mbggenerated
*/
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
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;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}
测试结果如下:
可以看到,编译出错,证明此时虽然用的是$取值,也经过了预编译,继续看下面。
测试3:like注入测试1
代码及结果截图如下:
从上面的图可以得知:
此种注入,在封装Criteria时把传入的参数整体当做一个对象然后传递下去,本次测试如上图1,打了两个断点,但是没执行到第二个断点处即中断执行,后台日志报错,证明此种注入sql有误无法正常执行。
测试3:like注入测试2
代码及结果截图如下:
like注入测试1中我们debug可以看到参数似乎拼接方式有误,那么本次注入即正常注入方式,debug看参数,如果将
andIdLike 值设置为:‘1' or ‘1=1'
数据上执行的sql理论上是:
SELECT * from product WHERE pid LIKE '1' or '1=1';
在数据库中执行此条sql结果如下:
但是demo执行查询结果为空,并且控制台报错,证明此种注入亦不能注入成功。
结论
经以上demo测试,此种$获取值不会受到sql注入的影响,常规sql注入失败。
附录
数据库表结构:
/*
Navicat mysql Data Transfer
Source Server : BWG-104.225.147.76
Source Server Version : 50644
Source Host : 104.225.147.76:3306
Source Database : springcloud_db01
Target Server Type : MYSQL
Target Server Version : 50644
File Encoding : 65001
Date: 2019-09-20 10:23:41
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for product
-- ----------------------------
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
`pid` bigint(20) NOT NULL AUTO_INCREMENT,
`product_name` varchar(50) DEFAULT NULL,
`db_source` varchar(50) DEFAULT NULL,
PRIMARY KEY (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of product
-- ----------------------------
INSERT INTO `product` VALUES ('1', '手机', 'springcloud_db01');
INSERT INTO `product` VALUES ('2', '冰箱', 'springcloud_db01');
INSERT INTO `product` VALUES ('3', '电脑', 'springcloud_db01');
INSERT INTO `product` VALUES ('4', '洗衣机', 'springcloud_db01');
INSERT INTO `product` VALUES ('5', '电视', 'springcloud_db01');
INSERT INTO `product` VALUES ('6', '音响', 'springcloud_db01');
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~