Edge browser history forensics

Note that there are forensics tools that will make browser history forensics easy to do. This is mostly for learning, but for real incident handling and forensics using an established tool will be a much faster route to results!

Basics

The edge browser history is stored in a sqlite3 database under each user profile. You find this database as C:\Users\<username>\AppData\Local\Microsoft\Edge\User Data\Default\History

The “History” file is a sqlite3 database, and you can analyse the database using the sqlite3 shell utility, that can be downloaded from here: SQLite Download Page.

If we list the tables in the database, we see there are quite a few.

screeshot terminal showing tables of HIstory sqlite3 database

Several of these seem quite interesting. The “urls” table seems to contain all the visited URL’s that exist in the browser history. Looking at the schema of this table shows that we can also here see the “last visited” timestamp, which can be useful.

sqlite> .schema urls
CREATE TABLE urls(id INTEGER PRIMARY KEY AUTOINCREMENT,url LONGVARCHAR,title LONGVARCHAR,visit_count INTEGER DEFAULT 0 NOT NULL,typed_count INTEGER DEFAULT 0 NOT NULL,last_visit_time INTEGER NOT NULL,hidden INTEGER DEFAULT 0 NOT NULL);
CREATE INDEX urls_url_index ON urls (url);

It can also be interesting to check out the visit_count.  For example, in the history file I am looking at, the top 3 visited URL’s are:

sqlite> select url, visit_count from urls order by visit_count desc limit 3;

https://www.linkedin.com/|24

https://www.linkedin.com/feed/|15

https://www.vg.no/|14

Another table that is interesting is, “visits”. This table has the following fields (among many, use .schema to inspect the full set of columns):

  • url
  • visit_time
  • visit_duration

The visits table contains mostly references to other tables:

sqlite> select * from visits where id=1;

1|1|13341690141373445|0||805306368|0|0|0|0||0|0|0|0|1|

To get more useful data out of this, we need to use some join queries. For example, if I would like to know which URL was last visited I could do this:

select visit_time, urls.url from visits inner join urls on urls.id = visits.url order by visit_time desc limit 1;

13342089225183294|https://docs.python.org/3/library/sqlite3.html

The time stamp is not very reader friendly, and it appears to be the number of microseconds since midnight January 1, 1601. sqlite – What is the format of Chrome’s timestamps? – Stack Overflow. This value has the same basis, but different counting from than Windows File Time File Times – Win32 apps | Microsoft Learn.

So.. at what times did I visit the Python docs page? The good news is that sqlite3 contains a datetime function that allows us to convert to human readable form directly in the query:

sqlite> SELECT
   ...>   datetime(visit_time / 1000000 + (strftime('%s', '1601-01-01')), 'unixepoch', 'localtime'), urls.url
   ...> FROM visits
   ...> INNER JOIN urls
   ...>   ON urls.id = visits.url
   ...> WHERE
   ...>   urls.url LIKE '%python.org%'
   ...> ORDER BY visit_time DESC
   ...> LIMIT 3;

2023-10-18 09:53:45|https://docs.python.org/3/library/sqlite3.html

2023-10-17 10:01:54|https://docs.python.org/3/library/subprocess.html

2023-10-17 09:58:51|https://docs.python.org/3/library/subprocess.html

Making some scripts

Typing all of this into the shell can be a bit tedious and difficult to remember. It could be handy to have a script to help with some of these queries. During incident handling, there are some typical questions about web browsing that tend to show up:

  1. When did the user click the phishing link?
  2. What files were downloaded?
  3. What was the origin of the link?

If we now try to make a small Python utility to figure out when a link has been visited, this could be a useful little tool. We concentrate on the first of the questions above for now – we have a URL, and want to check if it has been visited, and what the last visit time was.

Such a script can be found here: cbtools/phishtime.py at main · hakdo/cbtools (github.com).

Phishing investigation

Consider a hypothetical case, where we know that a user has visited a phishing link from his home computer, and that this led to a compromise, that later moved into the corporate environment. The user has been so friendly as to allow us to review his Edge history database.

We know from investigation of other similar cases that payloads are often sent with links to Pastebin content. We therefore want to search for “pastebin.com” in the URL history.

We copy over the History file to an evidence folder before working on it (to make sure we don’t cause any problems for the browser). It is a good idea to document the evidence capture, with a hash, timestamp, who did it etc.

Then we run our little Python script, looking for Pastebin references in the urls table. The command we use is

python phishtime.py History pastebin.com 2

The result of the query gives us two informative lines:

2023-10-18 12:42:37  hxxps://pastebin.com/raw/k3NjT2Cp

2023-10-18 12:42:37  hxxps://www.google.com/url?q=https://pastebin.com/raw/k3NjT2Cp&source=gmail&ust=1697712137533000&usg=AOvVaw1TK8-pr8-7Xsp8BG72hbP5

From this we quickly conclude that there was a Pastebin link provided, and that the user clicked this phishing link from his Gmail account.

One thought on “Edge browser history forensics

Leave a comment