java代码审计-某办公OA

举报
亿人安全 发表于 2023/03/28 14:38:51 2023/03/28
【摘要】 简介oasys是一个OA办公自动化系统,使用Maven进行项目管理,基于springboot框架开发的项目,mysql底层数据库,前端采用freemarker模板引擎,Bootstrap作为前端UI框架,集成了jpa、mybatis等框架。,源码可以访问链接下载:https://gitee.com/aaluoxiang/oa_system?_from=gitee_search 或者gitee...

简介

oasys是一个OA办公自动化系统,使用Maven进行项目管理,基于springboot框架开发的项目,mysql底层数据库,前端采用freemarker模板引擎,Bootstrap作为前端UI框架,集成了jpa、mybatis等框架。,源码可以访问链接下载:https://gitee.com/aaluoxiang/oa_system?_from=gitee_search 或者gitee搜索oasys自行下载。
审计过程采用白加黑方式,主要通过黑盒测试白盒确认。

环境搭建

环境搭建没有什么特别的,数据库创建oasys的数据库后导入oasys.sql,然后在application.properties文件中配置数据库地址就可以了。
配置文件中的Windows path需要根据自己系统环境调整,不然上传文件时会出错。

漏洞挖掘

SQL注入(通知列表)

首先拿到代码后看一下依赖,发现项目中使用了mybatis,然后找到映射文件看一下有没有用${}的:可以看到,果然有接口使用了${}字符串拼接。
接下来在控制器中搜索一下看哪个控制器使用了该接口,最终在通知列表处找到一次使用:

因为该接口不会将报错回显到前端,所以这里使用dnslog进行测试。发送上面请求后在dnslog服务器可以看到

SQL注入(通讯录)

这个注入和上面一样,同样因为使用${}进行字符串拼接。
映射文件如下:

控制器代码如下:

构造请求如下:

存储XSS(部门管理)

漏洞位于部门管理->添加部门处:

代码查看:

可以看到没有进行任何过滤直接调用deptdao.save将数据存入数据库。

存储XSS(用户管理)

用户管理->编辑用户处存在存储XSS。

可以看到同样没有任何过滤就直接存入数据库。
这说明XSS全站存在多处,其他的就不列举了。

代码分析:

越权

漏洞位于流程管理->我的申请->查看流程处:

可以看到URL中有个id参数,猜测该参数为流程id标识,看一下后端代码:

这里只放上部分关键代码,可以看到首先获取了当前用户对象,然后根据URL中的ID参数获取了流程对象,并且对比userID判断是申请人还是审批人。可以看出并没有对其他用户越权访问进行处理。

使用另外一个低权限账号登录系统,首先查看流程列表:

可以看到没有任何流程,接下来使用该用户cookie来调用查看流程的接口来枚举流程:
使用另外一个低权限账号登录系统,首先查看流程列表:

可以看到没有任何流程,接下来使用该用户cookie来调用查看流程的接口来枚举流程:


可以看到枚举出很多流程,证明越权确实存在。

任意文件读取


漏洞文件位于:src/main/java/cn/gson/oasys/controller/user/UserpanelController.java
src/main/java/cn/gson/oasys/controller/process/ProcedureController.java
两个文件都存在该漏洞,原理一致,这里拿第一个来说明。
在该控制器的image方法,存在任意文件读取漏洞,代码如下:

可以看到代码中首先通过getRequestURI方法当前访问的相对路径,然后将该路径中的iamge替换为空。接下来与rootpath拼接然后通过File打开文件后返回前端。

通过替换”/image”的操作,我们可以构造…/来造成目录穿越从而进行任意文件读取,BP请求如下:通过替换”/image”的操作,我们可以构造…/来造成目录穿越从而进行任意文件读取,BP请求如下:

前台sql注入

src/main/java/cn/gson/oasys/controller/inform/InformController.java 68行

有一个informlistpaging方法

在该方法中定义了一个字符串请求参数basekey,用list集合接收了sortMyNotice方法处理basekey等参数的结果,跟进查看哪里定义了nm

跟进NoticeMapper

转到mapper层

在此数据持久层搜索调用到的selectid

在like后面直接用${%%}进行模糊查询,导致了漏洞的产生

漏洞验证
根据controller的路由构造url:

sqlmap.py -r D:\test.txt
sqlmap.py -r D:\test.txt --random-agent --dbs --current-db

创建一个普通职工账号 test test

大致浏览pom.xml代码时发现了mybatis,mybatis中存在${}SQL注入,全局搜索${},发现在/src/main/resources/mappers/address-mapper.xml和/src/main/resources/mappers/notice-mapper.xml中存在${}

接下来就去看那个地方对该参数进行了调用,往上跟踪cn.gson.oasys.mappers.NoticeMapper接口——>sortMyNotice追踪到/src/main/java/cn/gson/oasys/controller/inform/InformController.java的如下代码中可以看到baseKey是可控的,直接从前端传入,下面给的有url,然后直接访问就行 http://localhost:8089/informlistpaging?baseKey=1

报错注入

通过构造payload可以使用报错注入的方式在控制台处得到返回的报错信息
Payload
http://localhost:8089/informlistpaging?baseKey=1' and (select extractvalue(“0x7e”,concat(‘~’,(select user())))a) and ‘1’=’1

时间盲注

同样可以构造时间盲注的payload
http://localhost:8089/informlistpaging?baseKey=1' and (select * from(select(sleep(2)))a) and ‘1’=’1%23

XSS(笔记处)

在测试功能点时发现在写笔记时将标题名可直接写为XSS恶意代码

代码中并未对该处输入坐任何限制,在存储时也是直接将得到的Title存储.

SQL注入

在resources\mappers中,发现了mapper文件,在第16行用了$拼接,那么会造成SQL注入,但前提是看一下pinyin这个参数是不是可控。

那就一步步往上跟:

cn.gson.oasys.mappers.AddressMapper接口------>allDirector方法直接全局搜索,定位到Controller中

进入到AddrController中outAddress方法,可以确定在Mapper中pinyin这个参数是可以被利用的。既然是RequestMapping,不用再去找页面中摸索功能点了。那么直接进行get方式访问。

构造请求

直接一手sqlmap跑出来。

文件管理-新建文件夹存在XSS漏洞

访问上述功能,点击新建文件夹,输入文件夹名为XSS验证语句<img src=1 onerror=alert(1) />,如下图所示:

成功实现弹框。

CSRF漏洞挖掘

本系统也存在多处CSRF漏洞.现在挑出一处来进行复现。

①、访问用户面板功能,点击写便签,输入任意内容。

②、打开BurpSuite,并打开浏览器代理,指向BurpSuite。BurpSuite打开Intercept is on进行拦截。

③、然后点击保存便签,BurpSuite拦截输入包如下图所示:、

代码分析:

获取到输入的内容之后,没有做任何限制。

这是 Java Web 应用程序中用于保存“便签纸”对象的方法。它似乎正在使用 Spring MVC,因为它具有基于注释的请求映射和会话属性。

该方法接受三个参数:

  • Notepaper npaper:这是一个代表便条纸的对象。它具有各种字段,例如标题、内容和用户 ID。
  • @SessionAttribute("userId") Long userId:这是一个保存用户 ID 的会话属性。它带有 注释@SessionAttribute,这意味着它将由 Spring MVC 框架从用户的会话中自动检索。
  • @RequestParam(value="concent",required=false)String concent:这是一个名为“concent”的请求参数。它被注释为@RequestParam,这意味着它将由 Spring MVC 框架从请求中自动检索。required=false属性表明该参数是可选的。

该方法执行以下操作:

  1. 它从会话属性中检索与用户 ID 关联的用户对象。
  2. 它将便条对象的创建时间设置为当前日期。
  3. 它将 notepaper 对象的用户 ID 设置为在步骤 1 中检索到的用户对象。
  4. 如果它为 null 或为空,它将便条对象的标题设置为“无标题”(中文意思是“无标题”)。
  5. 如果“concent”请求参数为 null 或为空,它将 notepaper 对象的内容设置为该值。
  6. 它使用对象保存便条纸对象ndao,该对象可能是某种数据访问对象。
  7. 它向客户端返回“重定向”响应,将客户端定向到“/userpanel”URL。这将导致客户端浏览器向“/userpanel”URL 发出新请求。

越权删除

从渗透测试黑盒角度测试,我们发现了日程管理处存在越权删除漏洞。现在我们从代码角度看看问题出在了哪里。

通过日程删URL中的dayremove,可以定位到日程删除位于src\main\java\cn\gson\oasys\controller\daymanage\DaymanageController.java,第204-211行,如下图所示:单从上面几行代码来看,仅是查询rcid参数后,进行了删除。我们进一步追下流程。

①、从上面可以看到,使用了daydao.findOne(rcid),来操作rcid,查看daydao发现来自DaymanageDao,如下图所示:②、进入DaymanageDao,发现并没有findOne,发现DayManageDao继承了JpaRepository,而进入JpaRepository之后也未发现findOne,但发现它继承了QueryByExampleExecutor,而findOne就在这里面,如下图所示:此时大家应该发现JpaRepositoryQueryByExampleExecutor代码属于引入依赖的代码了,这两个代码来源自Spring Data,其中findOne是其中一个方法,具体意思如下

就是说:

  • findOne返回一个Optional对象,可以实现动态查询;而Optional代表一个可能存在也可能不存在的值。

此时总结上面流程,简单说,日程删除功能先使用findOne去查询rcid是否存在该值。

然后再使用daydao.delete(rc)进行删除,此时我们追踪一下这个方法,发现这个delete方法也就是Spring Data CrudRepository中的delete(删除)方法,如下图所示:最后,我们回顾整个流程,也就是说查询了rcid的值,然后进行删除。整个流程没有任何权限的验证,因此导致了越权的操作。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。