freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

代码审计学习-5(sql相关学习)
2024-04-24 15:13:09

前言

学到一半发现学起来反而轻松了,可能是因为做渗透的原因,有基础上手比较快,今天来综合总结一下自己的相关学习心得。

1.产生该漏洞的原因是什么

SQL注入漏洞的主要原因在于应用程序在构建SQL查询语句时未能正确处理用户输入的数据。具体来说,当应用程序直接将用户输入的数据拼接到SQL查询语句中,而没有进行充分的验证和过滤时,攻击者就可以利用这一漏洞,通过输入恶意的SQL代码来篡改原始的查询语句,从而实现对数据库的非法访问和操作。

可以粗浅的理解为主要原因在于你输入的数据库恶意语句被执行了。

2.审计思路总结

简单概括下自己的思路。

  • 查看过滤器:是否有过滤器,过滤器规则写的对不对
  • sql语句的规则:是否预编译或参数化查询
  • sql语句的写法:如何恶意产生闭合,能否前端利用,是否能通过参数拼接生成恶意的语句

大体思路是这个样子,但是其实里面细节很多的,像是各种技术的不同,各种替代,注释等等,在此不在多提,只是为了总结思路。

3.预编译可以预防所有的注入吗

我之前一直以为是能的,但是后来学习才发现,工具再好,架不住有些不当人啊。把前端的参数变量名直接给你当语句本身执行了,你有什么办法。。。。。。

预编译并不能预防所有的SQL注入。虽然预编译是一种有效的防止SQL注入的方法,但它并不能完全杜绝所有的SQL注入攻击。

预编译的主要原理是通过将SQL语句和参数分开处理,使得攻击者无法直接修改SQL语句的结构,从而减少了SQL注入的风险。但是,如果预编译语句的构造或使用不当,仍然存在被攻击的可能性。例如,如果预编译语句中的参数处理不严谨,或者某些特殊情况下参数被错误地解释为SQL代码的一部分,仍然可能导致SQL注入的发生。

此外,预编译只能防止基于SQL语句拼接的注入攻击,对于其他类型的注入攻击(如通过存储过程、触发器等),预编译可能无法起到有效的防护作用。

因此,虽然预编译是防御SQL注入的重要手段之一,但并不能完全依赖它来解决所有SQL注入问题。在开发过程中,还需要结合其他安全措施,如输入验证、输出编码、使用安全的数据库连接库等,来构建更加安全的应用程序。

总的来说,预防SQL注入需要综合考虑多种因素,并采取多层次的安全防护措施。

4.Mybaits相关

我之前知道开发常用的框架是ssm和ssh,其中的ssm的“m”指的就是Mybaits。之前有说过这是个半ORM模型,移植性差,但是其实不明白其工作原理,为什么 说是半ORM。

4.1运行过程

MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通的 Java 对象)为数据库中的记录。接下来,我将描述 MyBatis 的启动和使用过程。

1. 添加依赖

首先,你需要在你的项目中添加 MyBatis 的依赖。如果你使用的是 Maven,你可以在 pom.xml 文件中添加如下依赖:

xml
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>你的MyBatis版本号</version>
</dependency>

2. 配置 MyBatis

你需要创建一个 MyBatis 的配置文件,通常命名为 mybatis-config.xml。这个文件包含了数据库连接信息、事务管理器、数据源等配置。

xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="你的数据库驱动"/>
<property name="url" value="你的数据库URL"/>
<property name="username" value="你的数据库用户名"/>
<property name="password" value="你的数据库密码"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="你的Mapper文件路径"/>
</mappers>
</configuration>

3. 创建 Mapper 接口和映射文件

Mapper 接口定义了与数据库交互的方法,而映射文件则定义了 SQL 语句和结果集的映射规则。

例如,你可以创建一个 UserMapper.java 接口和一个 UserMapper.xml 映射文件。

UserMapper.java

java
public interface UserMapper {
User selectUserById(int id);
}


UserMapper.xml

xml
<mapper namespace="你的包名.UserMapper">
<select id="selectUserById" resultType="你的User类全路径">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>

4. 启动 MyBatis

你可以通过 MyBatis 的 SqlSessionFactoryBuilder 来构建 SqlSessionFactory,然后通过 SqlSessionFactory 来获取 SqlSession。SqlSession 是 MyBatis 的核心接口,用于执行 SQL 语句。

java
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();

5. 使用 MyBatis

通过 SqlSession,你可以获取 Mapper 接口的实现,并调用其方法。

java
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.selectUserById(1);
System.out.println(user);
} finally {
session.close();
}

注意事项
确保你的数据库驱动、URL、用户名和密码是正确的。
确保你的 Mapper 接口和映射文件的命名空间和 ID 是匹配的。
在使用完 SqlSession 后,记得关闭它,以释放资源。你也可以使用 try-with-resources 语句来自动关闭 SqlSession。

这就是 MyBatis 的基本启动和使用过程。可以说很清晰了,怎么加载怎么启动,也比较好理解

4.2为什么叫半ORM,跟全ORM区别在哪

MyBatis作为半ORM模型,与全ORM模型在多个方面存在显著差异。以下是MyBatis与全ORM模型的主要区别,并通过具体例子加以说明:

  • SQL控制:

MyBatis:需要开发者手动编写SQL语句,通过XML或注解方式配置。例如,开发者可能需要编写一个复杂的查询语句,用于检索满足特定条件的记录。这种方式允许开发者对SQL进行精确控制,但也需要更多的数据库知识和经验。
全ORM(如Hibernate):全自动生成SQL语句,开发者只需定义对象关系模型,ORM框架会自动处理数据库操作。这使得开发更加便捷,但可能会在某些复杂查询或性能优化方面受限。

  • 对象映射:

MyBatis:将查询结果映射成Java对象,但不会自动建立对象之间的关系。开发者需要手动控制对象之间的关系,例如通过关联查询或手动构建对象图。
全ORM:自动建立对象之间的关系,可以根据对象关系模型直接获取关联对象或集合。这使得代码更加简洁,但在处理复杂关系时可能不如MyBatis灵活。

  • 性能优化:

MyBatis:提供了延迟加载机制,当需要使用某个关联对象时,才通过代理模式实现对该对象的加载。这可以有效提高性能,尤其在处理大量数据时。
全ORM:更多地依赖内存和缓存技术来实现性能优化。虽然这在大多数情况下是有效的,但在某些特定场景下可能不如MyBatis的延迟加载机制高效。

  • 数据库独立性:

MyBatis:不完全支持数据库无关性。如果需要支持多种数据库,开发者需要自定义多套SQL映射文件,工作量大。
全ORM:通常具有较好的数据库无关性,可以更容易地切换数据库。

综上所述,MyBatis和全ORM模型在SQL控制、对象映射、性能优化和数据库独立性等方面存在显著区别。我个人觉得就是需不需要进行手写sql语句的区别,全自动生成必然高适配,手写必然更高精准度但适配性低。

Hibernate如何启动和加载的

简单举个例子说明吧。

Hibernate的启动和使用过程通常涉及配置、初始化SessionFactory、创建Session以及执行数据库操作等步骤。下面是一个简单的示例,展示了Hibernate的启动和使用过程:

1. 添加依赖

首先,确保你的项目中包含了Hibernate的依赖。如果你使用Maven,可以在pom.xml文件中添加如下依赖:

xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>YOUR_HIBERNATE_VERSION</version>
</dependency>

2. 创建实体类

创建一个简单的实体类,例如User,并为其添加注解以映射到数据库表。

java
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class User {
@Id
private Long id;
private String name;
private String email;

// 省略构造器、getter和setter方法
}

3. 配置Hibernate

使用hibernate.cfg.xml文件来配置Hibernate。

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 数据库连接配置 -->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydatabase</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>

<!-- 数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

<!-- 显示SQL语句 -->
<property name="hibernate.show_sql">true</property>

<!-- 格式化SQL语句 -->
<property name="hibernate.format_sql">true</property>

<!-- 配置映射文件或实体类 -->
<mapping class="com.example.User"/>
</session-factory>
</hibernate-configuration>

4. 初始化SessionFactory

在应用程序启动时,初始化SessionFactory。

java
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
private static final SessionFactory sessionFactory;

static {
try {
// 创建配置对象
Configuration configuration = new Configuration().configure();

// 创建服务注册对象
StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();
StandardServiceRegistry serviceRegistry = serviceRegistryBuilder.applySettings(configuration.getProperties()).build();

// 创建元数据对象
Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();

// 创建SessionFactory
sessionFactory = metadata.getSessionFactoryBuilder().build();
} catch (Throwable ex) {
// 处理异常
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory() {
return sessionFactor

上面简单的使用例子,跟mybaits对照看区别还是比较明显的。

写在最后

再会,兄弟,如果能帮助到你是我的荣幸!88~

# 代码审计 # Java代码审计
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录