当前使用版本(必填,否则不予处理)

3.4.0

该问题是如何引起的?(确定最新版也有问题再提!!!)

order by存在sql注入问题

重现步骤(如果有就写完整)

QueryWrapper wrapper = new QueryWrapper<>(); wrapper.orderBy(true, true, "id;delete from test;");

报错信息

表被清空了

Comment From: hnxljd

文档好像说过这个问题,还有 last 也是直接拼接的。所以orderby 我们用了白名单

Comment From: oday-xiexin

需要对orderby 的内容做黑/白名单过滤

Comment From: qmdx

https://github.com/baomidou/mybatis-plus/commit/5e6b1f4f35a4ec4a0f1db27031acadfb48bc5757

Comment From: WhiteBookMan1994

当前使用版本(必填,否则不予处理)

3.4.0

该问题是如何引起的?(确定最新版也有问题再提!!!)

order by存在sql注入问题

重现步骤(如果有就写完整)

QueryWrapper wrapper = new QueryWrapper<>(); wrapper.orderBy(true, true, "id;delete from test;");

报错信息

表被清空了

为什么我用3.4.0版本测试,没有复现呢?会报错: Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'delete from test_user; ASC' at line 5 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) a

Comment From: WhiteBookMan1994

@wormhole

Comment From: qmdx

当前使用版本(必填,否则不予处理)

3.4.0

该问题是如何引起的?(确定最新版也有问题再提!!!)

order by存在sql注入问题

重现步骤(如果有就写完整)

QueryWrapper wrapper = new QueryWrapper<>(); wrapper.orderBy(true, true, "id;delete from test;");

报错信息

表被清空了

为什么我用3.4.0版本测试,没有复现呢?会报错: Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'delete from test_user; ASC' at line 5 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) a

不建议前端直接把你需要的 order by 内容传入后端,你可以加一个映射处理,或者升级升级到最新版本, 最新版本会对常见的 sql 注入进行判断处理。(建议不让前端直接传入任意排序任何,允许传入也是后端要严格控制传入内容的)

Comment From: shanzhaozhen

@hnxljd @oday-xiexin 这个白名单的处理有没有demo啊,自己尝试弄了一下实在太不优雅了

Comment From: qmdx

@hnxljd @oday-xiexin 这个白名单的处理有没有demo啊,自己尝试弄了一下实在太不优雅了

TableInfoHelper 根据实体可以找到存在的字段,根据数据库字段做白名单过滤

Comment From: shanzhaozhen

@hnxljd @oday-xiexin 这个白名单的处理有没有demo啊,自己尝试弄了一下实在太不优雅了

TableInfoHelper 根据实体可以找到存在的字段,根据数据库字段做白名单过滤

十分感谢,按照自己需求感觉只需要获取实体类反射字段就可以,不用直接查数据库字段名

        /**
     * 检查字段是否在实体类中
     * @param columns 字段列表
     * @param clazz 实体类
     */
    public static void checkColumnsInEntity(String[] columns, Class<?> clazz) {
        List<Field> allFields = TableInfoHelper.getAllFields(clazz);
        List<String> fieldName = allFields.stream().map(Field::getName).collect(Collectors.toList());

        for (String column: columns) {
            if (!fieldName.contains(column)) {
                log.error("请注意,存在SQL注入关键词---> {}", column);
                log.error("请注意,值可能存在SQL注入风险!---> {}", column);
                throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + column);
            }
        }
    }

    public static void checkColumnsInEntity(String column, Class<?> clazz) {
        checkColumnsInEntity(new String[]{column}, clazz);

    }

    public static void checkColumnsInEntity(OrderItem orderItem, Class<?> clazz) {
        checkColumnsInEntity(orderItem.getColumn(), clazz);
    }

    public static void checkColumnsInEntity(List<OrderItem> orderItemList, Class<?> clazz) {
        String[] columns = orderItemList.stream().map(OrderItem::getColumn).toArray(String[] :: new);
        checkColumnsInEntity(columns, clazz);
    }