要熟悉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的注册配置
查看web.xml中<filter-mapping>
的<url-pattern>
来确定拦截规则,当是.action
时所有以.action
为结尾的请求都会被struts处理拦截,/test/.action则只有test目录下的请求会被拦截。
通过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各层流程
通常在struts2中
action为业务逻辑处理层,action层接收来自视图层(.jsp(可以理解为前端吧,就是用户看到操作的那层))的请求,并接收请求参数,同时负责调用模型Model层方法来完成业务逻辑的处理,最后控制程序的流程,选择一个合适的视图,将结果显示给用户,一般这个目录下文件的特征表现为xxxxaction.java,比如NovyAction.java;
dao为数据持久层,在这层中通常是用来做数据库请求处理的,增删查改都在这里,一般这个目录下文件的特征表现为xxxxDao.java,比如NovyDao.java。
在web运行处理请求时流程为业务逻辑处理层-数据持久层
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
在GoLogin类中我们就可以看到一些对登陆的处理,如果我们找登陆处的SQL注入的话就看处理登陆参数的相关方法,比如此处new了一个AdminDao类下的checkLogin方法来处理username及Password,再根据判断返回的结果是否为空来显示相应内容
根据3.1.2介绍我们知道AdminDao为数据持久层,那么ChekLogin方法通常就是对登陆做数据库操作的地方,所以我们跟进一下该方法
在此处因为直接拼接请求参数,然后带入数据库去执行查询导致了SQL注入漏洞的产生
根据前面3.1.1.2介绍我们知道其请求路由为login.jsp
根据漏洞位置我们模拟其sql语句为
select * from Admin where Admin_Username='username' and Admin_Password='password'
所以登陆时我们可以使用万能用户名来进行登陆绕过
Admin’or”=”or--+
通过web.xml中DispatcherServlet配置,来查看springMVC作用范围
通过servlet中contextConfigLocation配置,查看springMVC配置文件所在路径
在springMVC配置文件中,component-scan
是用来查找Controller类所在位置,org.springframework.web.servlet.view.InternalResourceViewResolver
为自定义视图解析器
它是Maven项目中的文件,使用XML表示,也可以由此判断该项目是否为maven项目,该配置文件通常用来声明项目信息、环境的配置、引用组件依赖等等
还是老规矩,在审计漏洞之前,我们先看下spring的请求处理流程
通常在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
这里以含有漏洞的springboot项目做案例(springboot和springmvc配置不一样,感兴趣的自行百度,但是请求处理流程一样,这里讲的又不是开发,不影响演示),Idea打开项目,等待依赖导入完成
发生报错的就自己下载相关组件导入
查看目录结构
按照3.2.2介绍得知流程为controller->services->mapper,按照3.2.2对pom的介绍,我们先看pom.xml引用了哪些组件,以此来找出包含漏洞版本的组件,然后再看controller及其他,可以在idea中利用file mask来查看所有controller或全局搜索@Controller
首先查看引用的组件
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.2对controller的介绍中得知,根据controller构造url:
http://localhost/informlistpaging?baseKey=
有时候sql查询会直接发生在service层,比如
某个项目中的某个方法有个查询,定义了一个字符串参数defkey
查看wfservice在哪里被定义
跟进WorkFlowService,在该service层中搜索前面调用到的getHavedonePage方法,在该方法中含有一条没有进行预编译的sql查询,此处直接进行带入到数据库查询导致了漏洞的产生
当跟进方法时跟到接口断了怎么办,比如出现这种情况
controller里有一个密码重置
跟进updatePassword方法
到这里之后只看到提供给userService的updatePassword方法,没有看到具体的实现,
不要慌,根据3.2.2对implements的介绍,我们还有个impl没有看,全局搜索implements UserService
就可以看到对接口UserService的updatePassword方法的实现
这时候再继续往下跟就可以了,流程一样
无论是struts还是springmvc/boot,按照我的理解,为了方便区分和后续其他开发,除非另类命名(比如3.1.3),在整个请求处理流程中对于类名的前置命名都是一致的,比如
NovyController->NovyService->(NovyServiceImpl->)NovyMapper.xml
而不会出现
NovyController->TestService->(WhyServiceImpl->)OasdMapper.xml
这种情况,所以在审计过程中跟进代码时利用idea的全局搜索能更好的提高审计效率
通常调用方法时都是类名.方法名
,或者写了一个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少先队的技术分享