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路径


构建测试语句


浙公网安备 33010602011771号