JavaSec 之 SQL 注入简单了解

2024-02-23 08:28

本文主要是介绍JavaSec 之 SQL 注入简单了解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • JDBC 注入
      • 语句拼接(Statement)
        • 修复方案
      • 语句拼接(PrepareStatement)
        • 修复方案 预编译
      • JdbcTemplate
        • 修复方案
    • MyBatis
      • Like 注入
      • Order By 注入
      • In 注入

寒假学了一个月 pwn,真心感觉这玩意太底层学的我生理不适应了,接下来学一段时间 java 安全缓一缓吧。

靶场来源:j3ers3/Hello-Java-Sec: ☕️ Java Security,安全编码和代码审计 (github.com)

bewhale/JavaSec: Java安全 学习记录 (github.com)

JDBC 注入

语句拼接(Statement)

// 采用Statement方法拼接SQL语句,导致注入产生public String vul1(String id) {Class.forName("com.mysql.cj.jdbc.Driver");Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);Statement stmt = conn.createStatement();// 拼接语句产生SQL注入String sql = "select * from users where id = '" + id + "'";ResultSet rs = stmt.executeQuery(sql);...
}

这就是原始人漏洞了,这边我们报错注入。

payload

1' and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)-- +
修复方案
// 采用黑名单过滤危险字符,同时也容易误伤(次方案)public static boolean checkSql(String content) {String[] black_list = {"'", ";", "--", "+", ",", "%", "=", ">", "*", "(", ")", "and", "or", "exec", "insert", "select", "delete", "update", "count", "drop", "chr", "mid", "master", "truncate", "char", "declare"};for (String s : black_list) {if (content.toLowerCase().contains(s)) {return true;}}return false;
}

语句拼接(PrepareStatement)

// PrepareStatement会对SQL语句进行预编译,但如果直接采取拼接的方式构造SQL,此时进行预编译也无用。public String vul2(String id) {Class.forName("com.mysql.cj.jdbc.Driver");Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);String sql = "select * from users where id = " + id;PreparedStatement st = conn.prepareStatement(sql);ResultSet rs = st.executeQuery();
}

虽然是预编译吧,但是没用占位符 ?,和字符拼接没什么区别

payload

id=2 or 1=1
修复方案 预编译
// 正确的使用PrepareStatement可以有效避免SQL注入,使用?作为占位符,进行参数化查询public String safe1(String id) {String sql = "select * from users where id = ?";PreparedStatement st = conn.prepareStatement(sql);st.setString(1, id);ResultSet rs = st.executeQuery();
}    

JdbcTemplate

// JDBCTemplate是Spring对JDBC的封装,如果使用拼接语句便会产生注入public Map<String, Object> vul3(String id) {DriverManagerDataSource dataSource = new DriverManagerDataSource();...JdbcTemplate jdbctemplate = new JdbcTemplate(dataSource);String sql_vul = "select * from users where id = " + id;// 安全语句// String sql_safe = "select * from users where id = ?";return jdbctemplate.queryForMap(sql_vul);
}

化石拼接语句的锅

修复方案
// ESAPI 是一个免费、开源的、网页应用程序安全控件库,它使程序员能够更容易写出更低风险的程序
// 官网:https://owasp.org/www-project-enterprise-security-api/public String safe3(String id) {Codec<Character> oracleCodec = new OracleCodec();Statement stmt = conn.createStatement();String sql = "select * from users where id = '" + ESAPI.encoder().encodeForSQL(oracleCodec, id) + "'";ResultSet rs = stmt.executeQuery(sql);
}

MyBatis

Mybatis的SQL语句可以基于注解的方式写在类方法上面,更多的是以xml的方式写到xml文件。

Mybatis中SQL语句需要我们自己手动编写或者用generator自动生成。编写xml文件时,Mybatis支持两种参数符号,一种是#,另一种是$。比如:

<select id="queryAll"  resultMap="resultMap">  SELECT * FROM NEWS WHERE ID = #{id}</select>

使用预编译,$使用拼接 SQL。Mybatis框架下易产生SQL注入漏洞的情况主要分为以下三种:

Like 注入

Mybatis模糊查询:

Select * from users where username like '%#{username}%'

在这种情况下使用 # 程序会报错,把 # 号改成 $ 可以解决

但是如果java代码层面没有对用户输入的内容做处理,那么将会产生SQL注入漏洞。

正确写法:

Select * from users where username like concat('%',#{username}, '%')

Order By 注入

由于使用 #{} 会将对象转成字符串(因为预编译机制,系统将我们输入的字符当作了一个字符串)根据字符串排序是不生效的

因此很多研发会采用${}来解决,从而造成SQL注入

POC:

id and (updatexml(1,concat(0x7e,(select user())),0))-- -

因此,此种情况下,安全的做法应当在 Java 代码层面来进行解决。可以设置一个字段值的白名单,仅允许用户传入白名单内的字段。

String sort = request.getParameter("sort");
String[] sortWhiteList = {"id", "username", "password"};
if(!Arrays.asList(sortWhiteList).contains(sort)){sort = "id";
} 

In 注入

在 IN 关键字之后使用 #{} 查询多个参数:

<select id="getUser" parameterType="java.lang.String" resultType="user.NewUserDO">select * from user_table where username in (#{usernames})
</select>

in之后多个username查询时使用 # 同样会报错(因为预编译机制,系统将我们输入的字符当作了一个字符串,因此查询结果为空,不能满足业务功能需求),因此很多研发会采用${}来解决,从而造成SQL注入

select * from user_table where username in (${usernames})

POC:

1,2,3) and (updatexml(1,concat(0x7e,(select user())),0))-- -

此种情况下,安全的做法应当使用 foreach 标签

<select id="getUserFromList" resultType="user.NewUserDO">select * from user_table where username in<foreach collection="list" item="username" open="(" separator="," close=")">#{username}</foreach>
</select>

总结一下,碰到 jdbc 的 预编译 + 占位符 或者 mabatis 的预编译 #{} 就不用深挖了。如果碰到 jdbc 不带 预编译占位符 或者 mybatis 拼接字符 ${} 的话,值得 sql 注入一试。

这篇关于JavaSec 之 SQL 注入简单了解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/738045

相关文章

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

springboot项目中常用的工具类和api详解

《springboot项目中常用的工具类和api详解》在SpringBoot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖Spring原生... 目录1. Spring Framework 自带工具类(1) StringUtils(2) Coll

MySQL 分区与分库分表策略应用小结

《MySQL分区与分库分表策略应用小结》在大数据量、复杂查询和高并发的应用场景下,单一数据库往往难以满足性能和扩展性的要求,本文将详细介绍这两种策略的基本概念、实现方法及优缺点,并通过实际案例展示如... 目录mysql 分区与分库分表策略1. 数据库水平拆分的背景2. MySQL 分区策略2.1 分区概念

SpringBoot条件注解核心作用与使用场景详解

《SpringBoot条件注解核心作用与使用场景详解》SpringBoot的条件注解为开发者提供了强大的动态配置能力,理解其原理和适用场景是构建灵活、可扩展应用的关键,本文将系统梳理所有常用的条件注... 目录引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、@ConditionalOn

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

Spring LDAP目录服务的使用示例

《SpringLDAP目录服务的使用示例》本文主要介绍了SpringLDAP目录服务的使用示例... 目录引言一、Spring LDAP基础二、LdapTemplate详解三、LDAP对象映射四、基本LDAP操作4.1 查询操作4.2 添加操作4.3 修改操作4.4 删除操作五、认证与授权六、高级特性与最佳

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

SpringSecurity JWT基于令牌的无状态认证实现

《SpringSecurityJWT基于令牌的无状态认证实现》SpringSecurity中实现基于JWT的无状态认证是一种常见的做法,本文就来介绍一下SpringSecurityJWT基于令牌的无... 目录引言一、JWT基本原理与结构二、Spring Security JWT依赖配置三、JWT令牌生成与