java审计-通俗的理解并审出自己的第一个漏洞
2021-02-18 14:46:59 Author: xz.aliyun.com(查看原文) 阅读量:161 收藏

要熟悉java语法,知道啥是类,啥是方法,啥是接口,啥是常量巴拉巴拉巴拉

在打开源码时先判断系统框架,例如一个struts2项目中web.xml文件存在Filter-class为:
org.apache.struts2.dispatcher.xxxx

以及resources目录(或src(root)目录下)中存在strtus.xml

如果存在pom那pom.xml中存在struts依赖信息

而springmvc的特征则是在pom.xml中会存在相关依赖

web.xml中存在关于DispatcherServlet的注册配置

3.1.Struts2

3.1.1.过滤器及映射配置

3.1.1.1.Web.xml

查看web.xml中<filter-mapping><url-pattern>来确定拦截规则,当是.action时所有以.action为结尾的请求都会被struts处理拦截,/test/.action则只有test目录下的请求会被拦截。

3.1.1.2.struts.xml

通过struts.xml文件,查看存在哪些action,以及处理具体请求的java文件路径
例如:

<action name="test" method="test" class="novy.action.LoginAction"/>

表示novy.action.LoginAction类中的test方法,处理http://127.0.0.1/test.action的请求。而在另一种的写法中

<action name="GoLogin" class="com.action.GoLogin">
<result name="input">/Login.jsp</result>
<result name="success">/Index.jsp</result>
</action>

表示GoLogin类处理http://127.0.0.1/login.jsp和index.jsp请求

在审计漏洞之前,我们需要了解一下web各层流程

3.1.2.层次介绍

通常在struts2中
action为业务逻辑处理层,action层接收来自视图层(.jsp(可以理解为前端吧,就是用户看到操作的那层))的请求,并接收请求参数,同时负责调用模型Model层方法来完成业务逻辑的处理,最后控制程序的流程,选择一个合适的视图,将结果显示给用户,一般这个目录下文件的特征表现为xxxxaction.java,比如NovyAction.java;

dao为数据持久层,在这层中通常是用来做数据库请求处理的,增删查改都在这里,一般这个目录下文件的特征表现为xxxxDao.java,比如NovyDao.java。

在web运行处理请求时流程为业务逻辑处理层-数据持久层

3.1.3.实例

Idea打开项目,查看目录结构

从目录得知该框架为struts,web运行处理流程为action->dao,bean是实体处理,db是数据库连接配置,两者不在流程之中。
根据之前3.1.1.介绍,我们首先看web.xml文件,查看拦截配置

.action请求会被struts处理,再查看struts.xml中含有哪些action及处理请求的类

根据配置我们知道login.jsp请求由GoLogin类处理,所以我们可以根据路径跟进GoLogin类,其路径组成对应为
src(root)/com/action/GoLogin.java

3.1.3.1.代码分析

在GoLogin类中我们就可以看到一些对登陆的处理,如果我们找登陆处的SQL注入的话就看处理登陆参数的相关方法,比如此处new了一个AdminDao类下的checkLogin方法来处理username及Password,再根据判断返回的结果是否为空来显示相应内容

根据3.1.2介绍我们知道AdminDao为数据持久层,那么ChekLogin方法通常就是对登陆做数据库操作的地方,所以我们跟进一下该方法

在此处因为直接拼接请求参数,然后带入数据库去执行查询导致了SQL注入漏洞的产生

3.1.3.2.漏洞验证

根据前面3.1.1.2介绍我们知道其请求路由为login.jsp
根据漏洞位置我们模拟其sql语句为

select * from Admin where Admin_Username='username' and Admin_Password='password'

所以登陆时我们可以使用万能用户名来进行登陆绕过
Admin’or”=”or--+

3.2.SpringMVC

3.2.1.配置及依赖

3.2.1.1.Web.xml

通过web.xml中DispatcherServlet配置,来查看springMVC作用范围

通过servlet中contextConfigLocation配置,查看springMVC配置文件所在路径

3.2.1.2.Springmvc.xml

在springMVC配置文件中,component-scan是用来查找Controller类所在位置,org.springframework.web.servlet.view.InternalResourceViewResolver为自定义视图解析器

3.2.1.3.pom.xml

它是Maven项目中的文件,使用XML表示,也可以由此判断该项目是否为maven项目,该配置文件通常用来声明项目信息、环境的配置、引用组件依赖等等

还是老规矩,在审计漏洞之前,我们先看下spring的请求处理流程

3.2.2.层次介绍

通常在springmvc中
controller为控制层(业务逻辑),用来接收客户端的请求,然后调用Service层业务逻辑,获取到数据,传递数据给视图层(客户端)用于视觉呈现,一般请求的url在这里,比如

@Controller
@RequestMapping(value = "/novy")

则请求url为http://localhost/novy
控制层的文件一般为xxxcontroller.java,比如NovyController.java

Service是业务层,接收Controller层数据,与DAO/Mapper层交互,处理业务逻辑,生成responseDTO数据并返回Controller层 ,该层文件一般为xxxServce.java,比如NovyService.java,此处是接口定义,就是定义一些方法,没有这些方法的实现,但是有时候数据操作会在这里发生(看开发)

Implements是服务实现层(接口实现),用来处理一些方法的实现(这个方法干了啥干了啥),该层文件一般为xxxImpl.java,比如NovyImpl.java,impl 是把mapper和service进行整合的文件,有时候一些sql操作也会发生在这里

Mapper是数据持久层,对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的,数据持久层文件通常都是xxxMapper.xml,比如NovyMapper.xml

Dao是数据接口层,一些数据请求(接口)会在这里发生(一般用于内部实现)

Entity是实体处理层,用于存放我们的实体类,与数据库中的属性值基本保持一致(定义前端传来的请求参数)

在web运行时处理请求的流程为Controller->Service->impl->mapper

3.2.3.实例

这里以含有漏洞的springboot项目做案例(springboot和springmvc配置不一样,感兴趣的自行百度,但是请求处理流程一样,这里讲的又不是开发,不影响演示),Idea打开项目,等待依赖导入完成

发生报错的就自己下载相关组件导入
查看目录结构

按照3.2.2介绍得知流程为controller->services->mapper,按照3.2.2对pom的介绍,我们先看pom.xml引用了哪些组件,以此来找出包含漏洞版本的组件,然后再看controller及其他,可以在idea中利用file mask来查看所有controller或全局搜索@Controller

3.2.3.1.代码分析

首先查看引用的组件
pom.xml

看到了两个存在漏洞的组件,拿fastjson反序列化来说,全局搜索json.parseObject或JSONObject.parseObject或@RequestBody来查找参数可控的地方

在此处中用@RequestBody注解来获取整个请求体,然后对请求体进行反序列化

按照上面介绍到的搜索并点进一个controller,从3.2.2对controller介绍得知此处请求url为/informlistpaging

在此处我们可以看到informListPaging方法定义了很多参数,拿basekey做例子,在该刚方法中被定义为字符串请求参数,按照3.1.3.1的思路,我们想要找注入就找到调用方法处理该参数的地方

在80行中,nm的sortMyNotice方法对几个参数进行处理,这里需要注意的是,nm并不是一个类,而是一个被定义的接口,所以我们需要注意nm在哪里被定义了

跟进NoticeMapper

此处为接口,为nm提供了sortMyNotice方法,但这里还不是数据库操作的地方,因为controller无法直接调用mapper.xml的方法(select id),所以就需要这个mapper.java来做一个接口中转,所以我们根据3.2.2介绍,转到mapper.xml层
全局搜索sortMyNotice方法

转到notice-mapper.xml

此处的select id即为调用到的方法,往下为sql语句,我们可以看到在like后面直接用%${}%进行模糊查询,导致了漏洞的产生
有人会问service层呢?在这里

imformRelationService的setList方法对mapper处理返回的数据进行封装处理后返回到controller,然后controller返回到视图层,流程结束

3.2.3.2.漏洞验证

3.2.2对controller的介绍中得知,根据controller构造url:
http://localhost/informlistpaging?baseKey=

3.3.ps:其他情况

3.3.1.Sql操作在service层

有时候sql查询会直接发生在service层,比如
某个项目中的某个方法有个查询,定义了一个字符串参数defkey

查看wfservice在哪里被定义

跟进WorkFlowService,在该service层中搜索前面调用到的getHavedonePage方法,在该方法中含有一条没有进行预编译的sql查询,此处直接进行带入到数据库查询导致了漏洞的产生

3.3.2.跟到接口断了

当跟进方法时跟到接口断了怎么办,比如出现这种情况
controller里有一个密码重置

跟进updatePassword方法

到这里之后只看到提供给userService的updatePassword方法,没有看到具体的实现,
不要慌,根据3.2.2对implements的介绍,我们还有个impl没有看,全局搜索implements UserService

就可以看到对接口UserService的updatePassword方法的实现

这时候再继续往下跟就可以了,流程一样

4.1.命名

无论是struts还是springmvc/boot,按照我的理解,为了方便区分和后续其他开发,除非另类命名(比如3.1.3),在整个请求处理流程中对于类名的前置命名都是一致的,比如
NovyController->NovyService->(NovyServiceImpl->)NovyMapper.xml
而不会出现
NovyController->TestService->(WhyServiceImpl->)OasdMapper.xml
这种情况,所以在审计过程中跟进代码时利用idea的全局搜索能更好的提高审计效率

4.2.方法的跟进

通常调用方法时都是类名.方法名,或者写了一个EntityManager接口,然后再定义一次:
private EntityManager em;
这样em就可以用到EntityManager里的方法
比如某个项目有一个序列化工具类SerializeUtil,在该类里有一个deserialize方法来反序列化接收的request数据

而在controller中定义了一个接口
private SerializeUtil fvlh;
然后在某个@PostMapping注解下的方法进行调用
fvlh.deserialize(request);
如果我们想找反序列化漏洞就在跟进时可以直接ctrl+左键(idea)来跟进deserialize方法查看具体实现,或者先查看哪里定义了fvlh,然后再根据接口去跟进deserialize方法进行漏洞跟踪,最后确定该漏洞是否利用

还有tapestry框架,这个我在公司项目中审的,开源没碰见过,所以不好解释,等哪天碰到了再另说。总的来说跟进思路就这样,其他漏洞同理。感谢shxjia对相关专业知识的解答,感谢白帽100少先队的技术分享


文章来源: http://xz.aliyun.com/t/9173
如有侵权请联系:admin#unsafe.sh