20250321 ‐ Browser Forensics - rundas-r00t/blog GitHub Wiki

Firefox Browser Forensics with SQLite

given a browser.sqlite file, answer the following questions:

  1. What did the user search for on craigslist?
  2. What was the current price of bitcoin when the user was browsing?
  3. What Bitcoin exchange did the user log in to?
  4. What is the email that was used to log into the exchange?
  5. What was the ID of the Bitcoin transaction that the user looked at?
  6. What was the total BTC of all the inputs of the Bitcoin transaction?
  7. Which bitcoin address received the majority of the Bitcoin in the transaction?

before getting too deep into sqlite3, lets see if we can strings | grep and answer some of these questions. First, let's try:

Click to reveal

strings browser.sqlite|grep 'craigslist'

image

with a keen eye, we see the &query=bitcoin part of the URL in the 2nd line and in the 6th from the bottom. to confirm, let's redo our grep statement:

strings browser.sqlite|grep 'craigslist|grep 'query'

image

looks good.

for the second question, let's continue our grepping skills, this time using a strings|grep|grep combo again.

Click to reveal

strings browser.sqlite|grep 'bitcoin'|grep '\$' --being sure to escape the $ with a \.

image

there we go!

For the 3rd question, let's just look at all the https entries and see what we can see:

Click to reveal

strings browser.sqlite|grep 'https'

image

Coinbase is a fairly large crypto-exchange, and we can tell by the .com/accounts/528cf016.... web address that the user logged in and viewed his/her wallet.

we're doing great so far, and haven't even needed sqlite3 just yet. amazing!

looking further through our current results, we see some hits for mail.google.com, so let's grep for gmail.com and see what we get:

Click to reveal

strings browser.sqlite|grep 'https'|grep 'gmail'

image

ok looks good.

keeping this trend going, let's answer the next question by grep 'transaction':

Click to reveal

strings browser.sqlite|grep 'transactions'

image

Nice.

for the next question, let's finally utilize sqlite3 and start poking around some tables.

Click to reveal

sqlite3 browser.sqlite

sqlite> .tables

sqlite> select * from moz_inputhistory;

sqlite> select * from moz_historyvisits;

image

not exactly sure what i'm looking at here... let's amke this a little more legible:

sqlite> .headers ON

sqlite> .mode column

sqlite> select * from moz_historyvisits;

image

that looks better. now we can see that the long string of numbers in indeed Epoch Time. we also see headings for place_id. With ChatGPT's help, let's try a JOIN and see if we can match the place_id with a URL, say craigslist.org:

image

sqlite> SELECT moz_places.url, datetime(moz_historyvisits.visit_date / 1000000, 'unixepoch') AS visit_time FROM moz_places JOIN moz_historyvisits ON moz_places.id = moz_historyvisits.place_id WHERE moz_places.url LIKE '%craigslist.org%' ORDER BY visit_time DESC LIMIT 10;

what exactly is this command doing? we are selecting columns moz_places.url and moz_hostiryvisits.visit_date, while also converting Epoch time to a typical date stamp and renaming the visit_date column to visit_time. then we're cross-referencing table moz_historyvisits with moz_places where the id matches, and where the URL is similar to craigslist.org, and let's order it newest first. results should look like:

image

sweet! we now know when the user visited some variation of craigslist.org. unfortunately, this doesn't really help us answer Question 6. but it is nice to see that we're able to navigate some tables and get the output we need. Since i'm not sure at all how to answer Question 6, i utilized ChatGPT with quite a few prompts to eventually produce a script that would dump all the information from all the tables to the screen.

sqlite3 browser.sqlite < megadump.sql

image

scrolling further down the results, we see our Epoch Time again:

image

in a real-life scenario, i would look for transaction URL's similar to this:

sqlite3 browser.sqlite < megadump.sql | grep '/tx/'

image

Unfortunately, the transaction doesn't actually exist:

image

Feeling pretty stuck on this, i had to turn to the guide, which references a really awesome website https://inloop.github.io/sqlite-viewer/ .

image

let's upload our database to it and see if we can finally answer Question 6.

image

checking each table in the dropdown menu produces familiar data:

image

again, i'm not seeing anything new, so back to the guide, which just so happens to reference the URL that we tried earlier which we thought was invalid. i guess i made a typo or didn't clean it up properly to trying it. but i tried all 3 URLs that show up using this command:

sqlite3 browser.sqlite < megadump.sql | grep '/tx/'

image

using notepad to clean them up b/c i'm slightly irked by this whole thing now lol:

image

and loading anyone of these into a web browser produces a page like this:

Click to reveal

image

so basically on this screen we see "2 inputs". scrolling down, we see that this matches to the "From" category:

image

adding these numbers up produces the correct answer.

phew! man Question 6 was a wild ride! but now that we got through it, Question 7 will be a breeze!

all we need to do is look at the "To:" column and copy/paste the correct address into the answer field.

Click to reveal

image

SQLite Forensics? Done!

⚠️ **GitHub.com Fallback** ⚠️