fastcms v0.1.5 后台SQL注入

前置知识

MyBatis

MyBatis是一个持久层框架,对jdbc的操作数据库的过程进行封装。通过 xml 或注解的方式将要执行的各种 statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过 java 对象和 statement 中的 sql 进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射成 java 对象并返回。

xml配置文件一般放置在resources目录下,mapper都会有一个namespace,避免多个mapper冲突,而且这个namespace不可以重复。id表示查询方法的唯一标识符,resultType定义返回值的类型,即调用sql的完整类名。
图片

每个基于MyBatis的应用都是以一个SqlSessionFactory实例为核心。SqlSessionFactory实例可以通过SqlSessionFactoryBuilder加载配置文件获得。
MyBatis包含一个Resources工具类,其包含的方法从类路径或其他位置加载资源文件更容易。
SqlSession类提供了在数据库执行SQL命名所需的所有方法。

package org.example;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        final String resource = "mybatis-config.xml";
        SqlSessionFactory sql=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(resource));
        
        //这里需要去了解下mubatis的Mapper接口代理模式
        SqlSession session=sql.openSession();
        UserMapper userMapper=session.getMapper(UserMapper.class);
        User user=userMapper.getUserById(1);

        System.out.println(user);
        session.close();
    }
}
class User{
    private Integer id;
    private String name;
    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + "]";
    }
    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
}

//接口类名要与配置文件的mapper名一致,方法则要与配置文件的sql语句的id名一致
interface UserMapper{
    User getUserById(Integer id);
}

Order by注入

#{}:预编译处理,MyBatis会将其转换为参数化查询

${}:直接字符串替换

由于order by子句后通常跟随列名而不是值,使用预编译语句会导致语法错误,开发者不得不使用字符串拼接方式构建。如:

select * from user order by #{chid}  -- 会被编译为order by 'id',由于多了引号从而报错

正文

fastcms的sql语句不出意外也是在resources目录下
图片
代码审计最通用的方法:直接搜索关键字,由于这里是找sql注入,所以直接全局搜${,而且一定是在xml文件里。
图片
可以看到ArticleCommentMapper.xml的pageArticleComment存在${,找对应的mapper接口
图片
继续跟踪pageArticleComment方法,发现有两个用法
图片
先看第一个,在ArticleController.java
图片
代码使用了QueryWrapper来构建查询条件,而不是直接拼接SQL语句,因此不会导致SQL注入问题。
图片
第二个也是使用了QueryWrapper来构建查询条件。

继续换下一个xml文件查找,重复流程
图片
发现存在order by,且能控制
图片
那么接下来就是去寻找api路径
图片
图片
构建测试语句
图片

posted @ 2026-02-26 17:07  死都学不会啊  阅读(9)  评论(0)    收藏  举报