首页 > 数据库 >java代码审计-sqli

java代码审计-sqli

时间:2024-04-12 21:22:50浏览次数:25  
标签:审计 username java String 编译 sqli sql id select

Java代码审计-sqli

0x01 漏洞挖掘

jdbc

在上古时期,人们往往这么从数据库获取数据。

public User getUserById(String id) throws SQLException {
    Connection connection = JDBCTOOLS.getConnection();
		String sql = "select id,username from user where id=" + id;
		Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery(sql);

    resultSet.next();
    int userId = resultSet.getInt(1);
    String username = resultSet.getString(2);
    User user = new User(userId, username);
    return user;
}

通过拼接字符串来构建sql语句,其中又有用户可控的部分,很容易出现问题。

后来,出现了预编译机制,但是预编译只能处理查询参数,很多场景下仅仅使用预编译是不够的。

  • like

    在使用模糊查询的场景中,

    String sql = "select * from user where username like '%?%'";
    

    这种写法是无法进行预编译的,程序会报错。

  • order by

    需要按照时间、id等信息进行排序的时候,也是无法使用预编译的。

    String sort = req.getParameter("sort");
    
    String sql = "select * from user order by ?";
    PreparedStatement preparedStatement = connection.prepareStatement(sql); //预编译
    preparedStatement.setString(1, sort); //绑定参数
    ResultSet resultSet = preparedStatement.executeQuery();
    

    如果像上面这样强行使用预编译,数据库会将字段名解析为字符串,即实际执行的sql为

    select * from user order by 'username';
    

    无法达到实际需求。

Hibernate

@Autowired CategoryDAO categoryDAO; //依赖注入

@RequestMapping("/hibernate")
public String hibernate(@RequestParam(name = "id") int id) {
  Category category = categoryDAO.getOne(id);
  return category.getName();
}

hibernate即我们经常使用的orm的一种实现,如果使用已封装好的方法,那么默认是使用预编译的。需要注意的有这么几种情况:

  1. 对于一些复杂的sql语句,需要开发手写sql,此时要严格过滤用户输入。
  2. 上面提到的预编译不生效的几种场景。

Mybatis

mybatis有两种写法,一种是基于注解:

@Mapper
public interface CategoryMapper {
    @Select("select * from category_ where name= '${name}' ")
    public CategoryM getByName(@Param("name") String name);
}

另一种是基于xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="cn.seaii.springboot.mapper.CategoryMapper">
    <select id="get" resultType="cn.seaii.springboot.pojo.CategoryM">
        select * from category_ where id= ${id}
    </select>
</mapper>

注意在maven项目中,xml文件要放在resources目录中。

0x02 漏洞防御

2.1 类型转换

java是一门强类型的语言,所以数字型注入一般很少出现,但还是要有必要的类型转换。

比如通过HttpServletRequest的getParameter方法获取到的参数的类型都是String。

int id = Integer.valueof(req.getParameter("id"));

2.2 预编译

无论那种web编程语言,目前防注入最通用、最流行的方法就是使用预编译。

public User getUserById(String id) throws SQLException {
    Connection connection = JDBCTOOLS.getConnection(); //获取连接,细节省略
    String sql = "select id,username from user where id=?";
    PreparedStatement preparedStatement = connection.prepareStatement(sql); //预编译
    preparedStatement.setString(1, id); //绑定参数
    ResultSet resultSet = preparedStatement.executeQuery();

    resultSet.next();
    int userId = resultSet.getInt(1);
    String username = resultSet.getString(2);
    User user = new User(userId, username);
    return user;
}

在使用预编译之后,即使用户提交的参数中含有敏感关键字(union、select等),数据库也会将其作为对应字段的值来处理而不会解析其中的sql关键字。

mybatis中这样写:

@Mapper
public interface CategoryMapper {
    @Select("select * from category_ where name= #{name} ")
    public CategoryM getByName(String name);
}

看起来比不使用预编译还要简单一点。

2.3 其他防御

上面也提到过,预编译只能处理查询参数,对于其他位置存在用户可控的情况(order by、in、like等),无法提供有效的保护,此时就要具体情况具体分析。

以上面提到的两种情况为例:

//like
String sql = "select * from user where username like concat('%', ?, '%')";
//预编译

order by可以设置白名单,只有白名单中的字段才可以拼接。

private String checkSort(String sortBy) {
    List<String> columns = new ArrayList<>(Arrays.asList("id", "username"));
    return (columns.contains(sortBy)) ? sortBy : "''";
}

0x03 参考资料

Mybatis框架下SQL注入漏洞面面观
封抓套装:链接:https://pan.baidu.com/s/14fBtXPqIZM4pziBEFnr9gA
提取码:wang

标签:审计,username,java,String,编译,sqli,sql,id,select
From: https://www.cnblogs.com/xiaobao8/p/18132076

相关文章

  • java代码审计-反序列化
    Java代码审计-反序列化0x00漏洞挖掘业务代码简单来说,找readObject/readUnshared就好了protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{StringbaseStr=request.getParameter("str");b......
  • Java基础知识篇02——封装
    大家好,我是白夜,今天给大家聊聊面向对象的三大特征——封装一、包(package)1.1、包的引入先来看看我们之前写的代码结构以上代码存在的问题所有类写在一个目录下面,非常难管理,因为以后项目不可能只有这么几个类,当类数量很大的时候,就不容易管理了。不能写同名但是不同需求的类......
  • Java如何自行实现正向地理编码算法(不依赖api,不联网)
    政务场景中经常会遇到地址落图,或者三维挂接的场景。如何将文本地址转化为gps坐标是实现要解决的核心问题。addresstool为正向地理编码提供了非常简单、高效的算法。如何实现正向地理编码,只需要3步就行:第一步:带有坐标的标准地址加载到addresstool中。第二部:以业务地址作为参数,使......
  • java 怎么把负数变正数
    java怎么把负数变正数Java中将负数变为正数可以通过以下几种方式实现:使用绝对值函数、使用三目运算符、使用位运算或者使用移位运算。下面将详细介绍这些方法。1.使用绝对值函数Java提供了Math类中的abs()方法,可以返回一个数的绝对值。使用该方法可以将负数转换为正数......
  • java中cron表达式 每10分钟执行一次
    在Java中,可以使用Quartz框架来定义和调度任务,包括使用Cron表达式来定义任务的执行时间。下面是一个使用Quartz框架实现每10分钟执行一次任务的示例:添加Quartz依赖在Maven项目中,添加以下依赖到pom.xml文件中:<dependency><groupId>org.quartz-scheduler</groupId><arti......
  • bug记录:java.lang.UnsupportedOperationException: null
    java.lang.UnsupportedOperationException:null这个错一般是因为不支持的操作导致,即对象不支持某方法,显示抛出此异常。举个例子:Arrays.asList这个方法返回Arrays内部类ArrayList而不是java.util.ArrayList,而Arrays的内部类ArrayList是继承了AbstractList,AbstractList中的add、r......
  • Java策略模式实践
    1什么是策略模式策略模式(StrategyPattern):一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改......
  • java + geotools 读写shp时,中文属性乱码问题
    创建时要注意 :  newDataStore.setCharset(Charset.forName("GBK"));代码如下:FilenewFile=newFile(filepath);Map<String,Serializable>params=newHashMap<>();params.put("url",newFile.toURI().toURL());params.put("createspati......
  • Java stream sorted使用 Comparator 进行多字段排序
    摘要:介绍使用JavaStream流排序器Comparator对List集合进行多字段排序的方法,包括复杂实体对象多字段升降序混合排序方法。综述​ Java8的Stream使用了函数式编程模式,人如其名,它可以被用来对集合或数组进行链状流式的排序、过滤和统计等操作,从而让我们更方便的对集合或数组......
  • Java 中文官方教程 2022 版(四十一)
    原文:docs.oracle.com/javase/tutorial/reallybigindex.html错误处理原文:docs.oracle.com/javase/tutorial/jaxp/limits/error.html建议应用程序在设置新属性时捕获org.xml.sax.SAXNotRecognizedException异常,以便应用程序在不支持这些属性的旧版本上正常工作。例如,可下载的......