代码审计-Echo2.3
代码审计-Echo2.3
Sherlock前言
本文先发于先知社区:代码审计-Echo2.3-先知社区
项目介绍
开源社区系统:基于 SpringBoot + MyBatis + MySQL + Redis + Kafka + Elasticsearch + Spring Security + … 并提供详细的开发文档和配套教程。包含帖子、评论、私信、系统通知、点赞、关注、搜索、用户设置、数据统计等模块。3000+Star的项目还是比较不错的
项目地址:https://gitee.com/veal98/Echo
环境搭建
1 | JDK 1.8.0_65 |
redis的安装较为简单,这里就不介绍了
对于zookeeper和kafka来说,两个是配套使用的,并且kafka就已经内置了适配的zookeeper了,不需要我们自己再去单独下载安装,要不然你还要考虑两个版本适不适配(吃了大亏。。。)
这里直接贴链接:https://www.cnblogs.com/Marydon20170307/p/17933358.html
对于Elasticsearch的安装可参考:https://zhuanlan.zhihu.com/p/451571598
但是有点不同的是,对于我自己来说,我在conf\elasticsearch.yml文件中还要多添加一点,如下:
1 | http.cors.enabled: true |
如上配置之后就可以正常使用了,就是多关闭了机器学习的功能
注:启动项目之前上面这些基础配置都要开启来
接下来我们需要先把该项目的源码下下来,然后对src/main/resources/application-develop.properties文件进行一部分的修改
1 | spring.datasource.url = jdbc:mysql://127.0.0.1:3306/数据库名?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong |
其他配置要是你的redis那些配置都保持默认的话那么也不需要进行更改
然后我们还需要创建数据库并将提供的sql文件全部导入进去,最后导入完后的结果如下:
最后就是启动springboot,访问我们设定的对应端口
审计
由于第一次审计java项目木有经验,再加上这是个小项目,代码量也不能算很多,所以我是全部的文件都看了一遍
首先该项目里面是不存在sql注入漏洞的,这是因为所有的输入点都进行了预编译处理,都用#{}
进行了处理
碰壁1
无妨,继续审计,看到了一个有趣的地方,位于UserController.java文件中
1 | /** |
方法是直接读取了云服务器上面的图像文件当作了头像,虽然说对最后的文件路径进行了处理,无法控制
这时我就想着上传图片的方法有没有设置检验图片内容啥的,该方法如下:
1 |
|
没有对上传的文件进行任何检验,也就是说我们可以上传任意文件,所以我尝试上传一个xss文件,但很遗憾的是无法触发,查了一下才发现该链接是通过<img>
标签进行的加载,浏览器会将 HTML 文件当作图片解析(显示破损图标),所以无法触发成功(忘了这茬。。。)
绕过鉴权
继续审计,在LoginTicketInterceptor.java中有一个preHandle方法存在漏洞
1 |
|
对于spring框架熟悉都知道,该类实现了HandlerInterceptor接口,其preHandle方法在每一次请求的过程中都会执行一遍
1 | HttpRequest --> Filter --> DispactherServlet --> Interceptor --> Controller |
而该方法只对ticket有值的时候进行鉴权,对于ticket值为null的时候没有进行任何处理,直接返回true,所以我们便可以轻松绕过鉴权了,具体如何使用会配合下面的漏洞进行
未授权上传任意文件
位于DiscussPostController.java文件中的uploadMdPic方法
这是一个通过post方法访问的接口,注释说的是拿来上传图片用的,但是看具体代码实现我们发现还是没有对上传的文件内容,后缀名进行任何的检验,也就是说我们可以上传任意文件,当然这功能是得在登录后才能使用的,但我们前面不是发现了一个鉴权绕过嘛,可以直接打配合实现未授权任意文件上传
让ai帮忙生成一个html表单上传文件的报文,然后进行利用
上传成功,访问该链接却报了404,打开hackbar查了一下问题如下:
将该报错拿去问了ai,按其提供的方法进行尝试依旧无果,不知道是哪里配置出的问题,但文件是确确实实上传成功了
我们通过application-develop.properties中的配置可以知道上传的文件存储位置
直接点该文件,确认了文件是没有问题的
那就很奇怪了。。。
未授权各种遍历
UserController.java文件中有好几个方法存在可以说是一模一样的漏洞,第一个是getProfilePage方法
该函数的内容不重要,重点是看上面的链接代码@GetMapping("/profile/{userId}")
,是根据userId的值来决定要访问的是哪一个用户,但是依然需要我们绕过鉴权,然后我们就可以对该userId的值进行爆破,获取大量信息
来一个例子如下:
第二个方法是getMyDiscussPosts方法
依旧是通过userId来访问每个人发布的帖子,进行利用如下:
最后一个方法是getMyComments方法
还是通过userId来访问每个人自己的评论/回复,进行利用如下:
碰壁2
是位于DiscussPostController.java文件中的setDelete方法
1 |
|
看着似乎是直接post传参id的值然后便可以进行一个删除帖子的操作,尝试一手
结果是直接跳转到了/denied页面,哦吼?进到具体的帖子里面进行查看,发现没有看到有删帖这个按钮
感觉这个操作是管理员才能做的,全局搜索一下admin
果然是有不同权限的,查看其用法
在SecurityConfig.java文件中的configure方法中定义了每个不同的权限可以访问的路由,而上面的删帖路由便要求必须是admin才可以
再查一下权限是在哪里确定的,位于UserService.java文件中的getAuthorities方法
继续查看该方法的调用
熟悉吧,我们绕过鉴权的方法就注定了我们连普通用户的权限都没有
那为什么上面的漏洞我们可以直接配合绕过鉴权来利用呢,这是因为在SecurityConfig.java文件中的configure方法中定义的所有需要权限的路由上面那几个正好都不包括在其中,又是一个人工失误的地方
总结
第一次进行java代码审计,采用了最笨的方法,把全部代码都看了一遍,虽然耗的时间长了些,但是从结果来看还是值得的
当然也有了一些思路了,重点关注controller目录下面的代码,当然还有interceptor目录下面的,毕竟该目录下面的文件作用主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上,可能存在绕过鉴权等漏洞