Java代码审计——SSH 框架审计技巧

news2024/11/19 15:33:20

目录

(一) SSH 框架简介

(二) Java SSH 框架审计技巧


(一) SSH 框架简介


        上个月介绍了 SSM 框架,即 Spring MVC Spring MyBatis 。接下来介绍 Java Web曾经开发的 SSH 框架,即 Struts2 Spring Hibernate
        自 Struts2 诞生以来,漏洞层出不穷,比如说  S2-059 S2-060 ,高危漏洞仍然不计其数。由于安全上的种种原因,以及 Spring MVC Spring Boot 等框架的兴起,Struts2 逐渐淡出了开发人员的视野。但是很多企业的项目还是使用 Struts2 进行开发的,所以 Java 代码审计人员非常有必要了解该框架的审计方法。
        接下来介绍 DAO 层的框架,它和 MyBatis 一样同为 ORM 框架的 Hibernate 。虽然二者同为 ORM 框架,但是区别还是挺大的,后续讲解中会介绍两个框架之间的区别,以及审计 Hibernate 时的注意事项。

(二) Java SSH 框架审计技巧


        Struts2 是一个 MVC 框架,在之前分析 SSM 中与之对应的是 Spring MVC , 那么审计 Struts2 与审计 Spring MVC 究竟有什么不同?接下来我们就从一个 SSH 的Demo 入手进行讲解。
        我们将前面的 SSM Demo 进行重写,方便两个框架之间进行比较,从而加深理解,项目目录结构如图 2-1  所示
图 2-1 项目目录结构

        如前所述,在有 web.xml 的情况下,审计一个项目时首先需要查看该文件,以便对整个项目有一个初步的了解。
        web.xml 内容如图 2 -2  所示
图 2-2 web.xml 内容

        web.xml 文件中,第一项配置表明了 Spring 配置文件的所在位置,第二项配置是一个 Filter ,这里明显不同于 SSM web.xml 的配置,本质上都是 Tomcat 通过加载 web.xml 文件读取其中的信息来判断将前端的请求交由谁进行处理。 Spring MVC 的选择是配置一个 Servlet ,而 Struts2 的选择是配置一个 Filter 。而且师傅还会发现,在配置 Spring MVC DispatcherServlet 时, Spring 配置文件(也就是applicationContext.xml 位置)是直接通过配置参数传入的,而这里则是通过配置一个context-param。
        接下来查看 applicationContext.xml ,该配置文件内容如图 2 -3  所示:
图 2-3 查看 applicationContext.xml

        该文件中主要配置了项目所需的各种 bean ,这里可以清楚地看到使用的是 c3p0的连接池。接着是配置 sessionFactory ,并将连接池作为参数传入,同时作为参数传输的还有一个 hibernate 的总配置文件,以及一个 hibernate 的映射文件。接下来是配置每个 Action bean 对象。
        查看完 Spring 的配置文件后,在审计 SSH 框架的代码之前还需要对一个配置文件有所了解,即 Struts2 的核心配置文件 struts2.xml ,该配置文件的详细内容如图 2 -4所示。
图 2-4 查看 struts2.xml 文件

        该配置文件中配置了 Sturts2 中最核心的部分,即所谓的 Action

        这里配置的每一个 Action 都有其对应的请求 URI 和处理该请求的 Class,以及所对应的方法。我们先从 allBook 这个 action 开始讲解,该功能用于首页所有书籍的展示。allBook action 对应的class 的全限定类名是com.sshProject.action.QueryAllBookAction。class 属性后面还有一个 method 属性,该属性的作用就是执行指定的方法,默认值为“execute”,当不为该属性赋值时,默认执行 Action 的“execute”方法。

        每个 action 标签中还会有一些 result 子标签,该标签有两个属性,分别是 name属性和 type 属性。 name 属性的主要作用是匹配返回的字符串,并选择与之对应的页面。这里当 QueryAllBookAction 执行完成后,如果返回的字符串是 success ,则返回 queryBookByID.jsp;如果返回的字符串是 false ,则返回 error.jsp
        result 中还有一个常用属性是 type type 属性的值代表去往 JSP 页面是通过转发还是通过重定向。转发和重定向这两种方式的区别为,转发是服务端自己的行为,在转发的过程中Controller 层执行后的返回结果;而重定向则需要客户端的参与,通过 300 状态码让客户端对指定页面重新发起请求。
       分析完 Action 标签中的常见属性,下一步就是追踪 QueryAllBookAction 这个类,来详细观察其中的内容。根据 result 的标签的配置, struts2 会执行 QueryAllBookAction类的 execute 方法,该方法的实现过程如图 2 -5  所示。
图 2-5 execute 方法的实现过程

如果只看 execute 方法的内容,可能会不太清楚其中的一些变量是如何获取,QueryAllBookAction 类的剩余部分如图 2-6 所示

图 2-6 QueryAllBookAction 类的剩余部分

        这里的 bookService 就是 Web 三层架构中服务层的部分。 setBookService 方法在当前 QueryAllBookAction 实例化时会被一个名为 params 的拦截器进行调用,并为bookService 变量进行赋值。
        QueryAllBookAction除继承 ActionSupport 这个父类以外,还实现了 RequestAware 接口,该接口内容如图 2-7  所示。

图 2-7 RequestAware 接口

        该接口内只有一个方法,目的是获取 request 对象中的全部 attributes 的一个 map对象。如果想要获取整个 request 对象,则需要实现 ServletRequestAware,该接口内
容如图 2 -8  所示
图 2-8 ServletRequestAware 接口

        在介绍完 QueryAllBookAction 对象的属性如何被赋值之后,最关键的还是execute 方法,在图 7-51 中可以看到在 execute 方法中调用了 bookService. queryAllBook()方法。
        bookService 变量的类型是 BookService ,是一个接口,其内容如图 2 -9  所示

图 2-9 BookService 接口

        该接口中针对常用的增、删、改、查各定义对应的抽象方法,并由 BooksServiceImpl 来具体负责实现。在 BooksServiceImpl 中找到 queryAllBook 方法,如图 2-10 所示

图 2-10 queryAllBook 方法

        这里调用了一个 bookManagerDao.queryAllBook 方法, bookManagerDao 明显是一个全局变量,观察其类型是 BookManagerDao 类型,如图 2 -11  所示。
图 2-11 bookManagerDao 变量

         这里要讲到 Spring 的依赖注入,BooksServiceImpl 类提供了 bookManagerDao 变量的 setter 方法,然后使用 Spring 的依赖注入在 BooksServiceImpl 类实例化时通过读取配置信息后调用 setter 方法将值注入 bookManagerDao 变量中。这里提到了读取配置文件,接下来查看该项目的 Spring 配置文件,即 applicationContext.xml 中的配置信息,如图 2-12所示:

图 2-12  applicationContext.xml 文件

        首先是导入了 jdbc 的配置文件,并配置了连接池和 SessionFactory 。然后配置了bookManagerDao 和 bookService 两个 bean ,并将 bookManagerDao 注入 bookService ,Spring 在启动时会读取 applicationContext.xml 并根据其中配置的 bean 的顺序将其逐个进行实例化,同时对每个 bean 中指定的属性进行注入。 Spring 依赖注入的方式有很多种,比如说注解,这里介绍的通过配置 xml 然后通过 setter 方法进行注入只是其中一种。
        从 applicationContext.xml 配置文件中可以发现 BooksServiceImpl 类中的bookManagerDao 存储的是一个 BookManagerDao 对象,所以定位到 BookManagerDao类的 queryAllBook 方法来看其具体实现,其内容如图 2 -13  所示
图 2-13 queryAllBook 方法

        这里进行了一次查询操作,并将查询的结果封装进一个 list 对象中进行返回。以上就是 SSH 框架处理一个用户请求的大致流程,生产环境中的业务比较复杂,会对各种参数进行合法性校验,但是整体的审计思路不会改变,就是按照程序执行的流程,关注程序每一步对传入参数的操作。
        该项目中有一个根据 ID 查询书籍的功能。 selectBook.jsp 中的表单内容如图 2 -14 所示
图 2-14 selectBook.jsp 中的表单

        根据表单提交的 url struts.xml 中查询,找到处理该请求的 Action ,如图 2 -15 所示。
图 2-15 处理请求的 Action
然后到 QueryBookByIdAction 类中查看该类的 execute 方法的具体内容,如图 2-16  所示
图 2-16 查看 execute 方法

结合之前的表单提交的一个图书的 id ,大概可知此处是通过传入的图书 id 在后台数据库中进行查询。根据之前的观察已知 bookService 变量指向的是一个BooksServiceImpl 对象,所以找到该类中的 queryBookById 方法,该方法的具体内容如图 2-17 所示。
图 2-17 查看 queryBookById 方法(一)

        同样根据之前的观察结果,可以发现 bookManagerDao 变量指向的是一个BookManagerDao 对象。在 BookManagerDao 类中找到 queryBookById 方法,如图 2 -18 所示
图 2-18 查看 queryBookById 方法(二)

        通过这一段的审计,不难发现图书的 id 参数是由前端传入的,最终拼接进了 SQL语句中并代入数据库中进行查询。在这整个流程中程序并没有对 id 参数进行任何校验,因此很有可能产生 SQL 注入漏洞。

        代码审计的思路就是要关注参数是否是前端传入,参数是否可控,在对这个参数处理的过程中是否有针对性地对参数的合法性进行校验,如果同时存在以上 3 个问题,则很可能会存在漏洞。以该 SQL 注入漏洞为例,常用的防御 SQL 注入的手段有两种:一种是通 Filter进行过滤,另一种是使用预编译进行参数化查询,这两种方式各有优缺点,也有各自的应用场景。
        Filter是 Servlet 自带的一种技术,也是在代码审计过程中需要特别注意的一个点。用户可以自定义一个简单的过滤器,通过匹配传递来的参数中有无恶意 SQL 语句来判断程序是否继续执行。
        
        自定义 Filter 时需要实现 Javax.servlet.Filter 接口,该接口内容如图 2 -19  所示

图 2-19 Javax.servlet.Filter 接口

        审计过程中最需要注意的是其中的 doFilter 方法,过滤的规则一般都在该方法中。以下是该接口的一个自定义 Filter doFilter 方法的具体实现,内容如图 2 -20  所示。
图 2-10 自定义 Filter 对 doFilter 方法的具体实现

        在 doFilter 方法中,遍历获取了查询请求中的参数,并将请求参数传递给 sqlValidate 函数进行匹配,所以需要再去观察 sqlValidate 函数的具体内容,如图 2 -11所示。

图 2-11 查看 sqlValidate 函数

        根据图 2-11 中的代码可见,传递进来的参数会先被转化成小写,然后和 basdstr 中定义的 SQL 语句进行比对,如果比对成功则返回 flase,返回到 doFilter 方法中就会终止程序继续执行,并重定向至 error.jsp 页面。

   
      Strut2 自身也提供了验证机制,例如 ActionSupport 类中提供的 validate 方法如图 2-12  所示
图 2-12  validate 方法

        当一个 Action 中重写 ActionSupport 中的 validate 方法后, Struts2 每次执行该Action 时都会最先执行该 Action 中的 validate ,以起到检验参数合法性的作用。这里将之前 Filter doFilter 方法的过滤规则直接复制过来进行展示,如图 2 -13  所示。
图 2-13 doFilter 方法的过滤规则

        如此一来,每一次 Struts2 执行 QueryBookByIdAction 的 execute 方法时都会首先调用 validate 方法,这样每当传入的参数中包含恶意 SQL 语句就会终止执行并重定向至 error.jsp ,所以如果开发人员在开发过程中没有使用 Filter 来进行过滤,采用上述重写 validate 方法的方式也可以起到防止 SQL 注入的目的。

        除使用上述过滤方式来实现防止 SQL 注入外,在审计过程中还有很重要的一点就是预编译,除可以使用原生的 SQL 语句外, Hibernate 本身还自带一个名为 HQL的面向对象的查询语言,该语言并不被后台数据库所识别,所以在执行 HQL 语句时,Hibernate需要将 HQL 翻译成 SQL 语句后交由后台数据库进行查询操作。将原生 HQL语句改写成 SQL 语句,可以很便捷地在众多不同的数据库中进行移植,只需要修改配置而不必再对 HQL 语句进行任何改写。但是要注意的一点就是 HQL 是面向对象的查询语句,只支持查询操作,对于增、删、改等操作是不支持的。
        使用之前的查询语句来举例,SQL 语法和 HQL 语法的简单区别如图 2 -14  所示
 
图 2-14 SQL 语法和 HQL 语法的简单区别
        可以发现 SQL 语句是依据 bookID 字段的值从 SSH_PROJECT 数据库的 BOOKS表中查询出指定的数据,而 HQL 的语句则更像是从 Books 对象中取出指定 bookID属性的对象。Hibernate 可以像调用对象属性一样进行数据查询,是因为事先针对要查询的 POJO 对象进行映射,映射文件的具体内容如图 2 -15  所示
图 2-16 映射文件的具体内容

 

        POJO 类的每个属性都与表中的字段进行一一映射,这样 HQL 才能用类似于操作对象属性的方式进行指定数据查询。与 SQL 语句相似, HQL 也存在注入问题,但是限制颇多,以下列举一些 HQL 注入的限制。
  1. 无法查询未进行映射的表。
  2. 在模型关系不明确的情况下无法使用“UNION”进行查询。
  3. HQL 表名、列名对大小写敏感,查询时使用的列名大小写必须与映射类的属性一致。
  4. 不能使用*#--
  5. 没有延时函数。
        所以说在生产环境中利用 HQL 注入是一件很困难的事。但是防御 HQL 注入时,除前面介绍的使用过滤器进行过滤的方法以外,还可以使用图 2-17  所示的预编译形式。

图 2-17 预编译形式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/29430.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

河北涿州水稻种植历史 国稻种芯·中国水稻节:保定效益双赢

河北涿州水稻种植历史 国稻种芯中国水稻节:保定效益双赢 央视网消息 保定日报讯(通讯员张千 刘永兴 王蕾)新闻中国采编网 中国新闻采编网 谋定研究中国智库网 中国农民丰收节国际贸易促进会 国稻种芯中国水稻节 中国三农智库网-功能性农业农…

浅谈前缀索引

一.什么是前缀索引 所谓前缀索引说白了就是对字符串或前n个字符建立索引 二.为什么选择前缀索引 一般来说使用前缀索引,可能都是因为整个字段的数据量太大,没有必要针对整个字段建立索引,前缀索引仅仅是选择一个字段的前n个字符作为索引&a…

Linux运维工程师的操作规范

,Linux运维工程师的操作规范从事运维有一段时间了,遇到过各式各样的问题,数据丢失,网站挂马,误删数据库文件,黑客攻击等各类问题。 今天简单整理一下,分享给各位小伙伴。 一、线上操作规范 1、…

你可见过如此细致的延时任务详解

概述 延时任务相信大家都不陌生,在现实的业务中应用场景可以说是比比皆是。例如订单下单 15 分钟未支付直接取消,外卖超时自动赔付等等。这些情况下,我们该怎么设计我们的服务的实现呢? 笨一点的方法自然是定时任务去数据库进行轮…

华为机试 - 滑动窗口最大和

目录 题目描述 输入描述 输出描述 用例 题目解析 算法源码 题目描述 有一个N个整数的数组,和一个长度为M的窗口,窗口从数组内的第一个数开始滑动直到窗口不能滑动为止, 每次窗口滑动产生一个窗口和(窗口内所有数的和&…

常用的框架技术-09 Spring Security Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录1.Spring Security简介1.1 Spring Security概述1.2 Spring Security历史发展1.3 产品的对比1.3.1 Spring Security1.3.2 Shiro1.4 Spring Security 核心类1.4.1 Auth…

qemu 线程 vhost

[rootlocalhost cloud_images]# lsmod | grep vhost_net vhost_net 262144 0 vhost 262144 1 vhost_net tap 262144 1 vhost_net tun 262144 2 vhost_net [rootlocalhost cloud_images]#vhost-net网卡的…

[附源码]SSM计算机毕业设计基于实时定位的超市配送业务管理JAVA

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

低碳世界杂志低碳世界杂志社低碳世界编辑部2022年第7期目录

节能环保 挥发性有机物的全厂控制措施 董少军; 1-3 《低碳世界》投稿:cnqikantg126.com 佛山市市政排水管网通沟污泥处理处置工艺设计 张红; 4-6 “双碳”背景下海岸带地区适应气候变化评估与对策研究 王鸿浩;邬乐雅;吴晓晨;张丽佳;黄婧蓼琦;胡斐…

【毕业设计】基于情感分析的网络舆情热点分析系统

文章目录0 前言1 课题背景2 数据处理3 文本情感分析3.1 情感分析-词库搭建3.2 文本情感分析实现3.3 建立情感倾向性分析模型4 数据可视化工具4.1 django框架介绍4.2 ECharts5 Django使用echarts进行可视化展示5.1 修改setting.py连接mysql数据库5.2 导入数据5.3 使用echarts可视…

Java编程实战9:统计只差一个字符的子串数目

目录统计只差一个字符的子串数目题目示例 1示例 2示例 3示例 4提示解答解题思路完整代码统计只差一个字符的子串数目 题目 给你两个字符串 s 和 t ,请你找出 s 中的非空子串的数目,这些子串满足替换 一个不同字符 以后,是 t 串的子串。换言…

实验1:Arduino的nRF24L01单向收发实验

实验结果: 发送端发送“Hello World”,发送成功打印1 接收端接收到“Hello World”,在串口中打印出“Hello World” OK,直接讲代码 因为我用的Arduino和nRF24L01 是用扩展板连接的,而我的嵌入式硬件开发,也就是AD实在不擅长,就不解释了 其中(9,10)CE,CSN 那么我…

通关算法题之 ⌈数组⌋ 下

二分搜索 704. 二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 输入: nums [-1,0,3,5,9,12], target 9 输出…

【后台技术】异步编程指北,问题和重点

导语:同步、异步,并发、并行、串行,这些名词在我们的开发中会经常遇到,这里对异步编程做一个详细的归纳总结,希望可以对这方面的开发有一些帮助。 内容大纲: 1、几个名词的概念 多任务的时候,…

jmeter压力测试报告

出版社智能智造测试报告 (二期版本) 2022年11月 目 录 1. 测试背景 1.1. 项目背景 1.2. 测试目的 1.3. 测试时间 1.4. 测试资源 1.5. 参考资料 2. 测试范围 3. 性能需求指标 3.1. 业界指标 4. 测试工具 5. 测试环境 5.1. 阿里云测试环境软…

搭建Gitlab

Gitlab是目前被广泛使用的基于git的开源代码管理平台, 基于Ruby on Rails构建, 主要针对软件开发过程中产生的代码和文档进行管理 一、搭建gitlab服务器,统一管理软件项目 第一步: 创建一个4G内存的虚拟机,否则很容易启动不了,报…

(附源码)计算机毕业设计Java“华商转转”平台的设计和实现

项目运行 环境配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: Springboot mybatis Maven Vue 等等组成,B/…

python常用进制转换

整数之间转换 # 1. 10 -> 16 hex(number)# 2. 10 -> 2 bin(number)# 3. 10 -> 8 oct(number)# 4. x进制 -> 10 int(Union[str, bytes, bytearray],basex) ------------------ print(int("0x16", base16)) // 22字符串转整数 # 10进制 val int(10) pri…

SPP-学习笔记

Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition SPP提出的原因 1、现有的深度卷积神经网络(spp出现之前的)需要固定大小的输入图像(例如224224)。往往需要对图片裁剪或者resize,导致图片信息损失或者产生几何畸变。这样可能会损…

奥比中光亮相全球1024开发者节,与科大讯飞达成战略合作

作者 | 奥比中光 编辑 | 3D视觉开发者社区 11月17日-23日,第五届世界声博会暨2022科大讯飞全球1024开发者节在安徽合肥举办,奥比中光作为3D视觉感知头部企业参展,并与科大讯飞达成战略合作,共同赋能3D视觉行业应用开发。 本次参…