Writeup by ._nofix for Académie de l'investigation - Dans les nuages

forensics memory linux

May 13, 2024

Introduction

This challenge is the last part of a forensics analysis series on a Linux memory dump.

We are asked to investigate and find the user name and the password used to connect to a web server at 10.42.42.132.

Recap about the analysis

We are investigating a memory dump of a Debian machine with a kernel v5-4-0. To create a profile for this dump, I booted a VM with Debian 10, added to backports to the apt-source list and installed the kernel from there. Once our machine is setup and our profile is built, we start to analyze our memory dump. The analysis indicated that the user has been creating a docx document recently, and is interested in pentesting, as he documents himself about post exploitation techniques on GitHub, using chromium. He is testing his skills using stuff like rkhunter (for post exploitation detection I assume), nmap or kernel modules, which we can see in his bash history:

Pid      Name                 Command Time                   Command
-------- -------------------- ------------------------------ -------
    1523 bash                 2020-03-26 23:24:18 UTC+0000   rm .bash_history
    1523 bash                 2020-03-26 23:24:18 UTC+0000   exit
    1523 bash                 2020-03-26 23:24:18 UTC+0000   vim /home/Lesage/.bash_history
    1523 bash                 2020-03-26 23:24:27 UTC+0000   ss -laupt
    1523 bash                 2020-03-26 23:26:06 UTC+0000   rkhunter -c
    1523 bash                 2020-03-26 23:29:19 UTC+0000   nmap -sS -sV 10.42.42.0/24
    1523 bash                 2020-03-26 23:31:31 UTC+0000   ?+^S??U
    1523 bash                 2020-03-26 23:31:31 UTC+0000   ip -c addr
    1523 bash                 2020-03-26 23:38:00 UTC+0000   swapoff -a
    1523 bash                 2020-03-26 23:38:05 UTC+0000   swapon -a
    1523 bash                 2020-03-26 23:40:18 UTC+0000   ls
    1523 bash                 2020-03-26 23:40:23 UTC+0000   cat LiME.txt
    1523 bash                 2020-03-26 23:40:33 UTC+0000   cd LiME/src/
    1523 bash                 2020-03-26 23:40:54 UTC+0000   ^D
    1523 bash                 2020-03-26 23:40:54 UTC+0000   insmod lime-5.4.0-4-amd64.ko "path=/dmp.mem format=lime timeout=0"

We also know that the user is called Lesage. I dumped the “in memory” file system using linux_recover_filesystem, in order to have a better idea about what was landing in the target machine. I also listed every file on the file system using linux_find_file.

Going trough the files, we can note down information that sadly wont be useful for the rest of our investigation :

  • tor is installed and running (/usr/tor/)
  • the user 1001 (Lesage) is using KeePass (/run/user/1001/KeePass)
  • firefox is installed
  • chromium is installed
  • KeePass2 is installed, as a .exe file (/usr/lib/keepass2/KeePass.exe)

The challenge

Approaches and rabbit holes

We need to find a user name and a password used to connect to a web server on 10.42.42.132. The best place to find passwords sound like to be the Keepass . I dumped Keepass' memory, and started to dig into it using our best friends strings and grep to find juicy information, such as kbdx files mapped into memory. Sadly, I could not find any encrypted password in there. Still, I found some information about potential kdbx files in an XML file that was landing in memory :

  • <Item>Database@../../../home/Lesage/Documents/pass</Item>
  • <Path>../../../home/Lesage/Documents/pass/mdp.kdbx</Path>

And a bit later into the memory :

{\*\generator Mono RichTextBox;}\pard\f0\fs22 \ul Group:IdmZfHKZcQfnm 453, \ul Title:IdmZfHKZcQfnm 453, \ul User Name:IdmZfHKZcQfnm LePasSage, \ul Password:IdmZfHKZcQfnm ********, \ul Creation Time:IdmZfHKZcQfnm 3/26/2020 2:36:34 PM, \ul Last Modification Time:IdmZfHKZcQfnm 3/26/2020 2:39:59 PM\par

Which indicates that a potential user name could be LePasSage. And maybe an encrypted password encoded into base64, but I am not fairly confident with that as all the base64 strings looks like each others.

Later again we find this string:

/run/user/1001/KeePass

Which confirms that the process is run from Lesage.

We even find a /etc/passwd file into the memory :

lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
dnsmasq:x:105:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
usbmux:x:106:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
rtkit:x:107:111:RealtimeKit,,,:/proc:/usr/sbin/nologin
speech-dispatcher:x:108:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
avahi:x:109:114:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
pulse:x:110:116:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
saned:x:111:118::/var/lib/saned:/usr/sbin/nologin
colord:x:112:119:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
lightdm:x:113:120:Light Display Manager:/var/lib/lightdm:/bin/false
debi:x:1000:1000:debi,,,:/home/debi:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
debian-tor:x:114:121::/var/lib/tor:/bin/false
unbound:x:115:122::/var/lib/unbound:/usr/sbin/nologin
Debian-exim:x:116:123::/var/spool/exim4:/usr/sbin/nologin
Lesage:x:1001:1001:,,,:/home/Lesage:/bin/bash
Leclair:x:1002:1002:,,,:/home/Leclair:/bin/bash

Which leaks us a potential second user name : Leclair. Sadly I could not find relevant passwords with both Leclair or LePasSage, and digging around with those.

This looked like a rabbit hole.

The right approach

Taking a step forward, the challenge asks me to find a password and a user name used to connect to a web server. The user obviously used either chromium or firefox. Due to the number of pids associated to chromium processes, I decided to dig first into chromium.

I dumped the process (the whole process map, using linux_dump_map, which gave me around 80 GB saved on disk, ouch). Then I used gf tool, a tool you can use to grep quickly to specific things. I used it to grep every URL in the process, and I found a lot of 10.42.42.x:

image-20200504031135060

With a bonus : we know that there is a panel page in this web server.

I also tried used the tool to search for base64 but it found nothing relevant.

Digging around using a big strings in our dumps, we find that 10.42.42.132 strings are quite close to an nginx/1.16.1 string, which might indicate that the user connected to an nginx web page.

After some time digging around in this memory, grepping for panel brings us this interesting string : Basic realm="Panel-\o/", typical of an HTTP-BASIC authentication.

It is now quite probable that our user connected to an nginx web server v1.16.1 using basic-auth.

At this point I have been looking again to my base64 strings in order to find relevant stuff, because this kind of authentication usually sends credentials in base64. But this is endless and I have no way to know if a string I find is the right user name or the right password, plus I previously found nothing relevant in base64.

However, the wikipedia page about this kind of authentication says :

Because the BA field has to be sent in the header of each HTTP request, the web browser needs to cache credentials for a reasonable period of time to avoid constantly prompting the user for their username and password. Caching policy differs between browsers.

This means that our credentials have a high chance of still be landing in chromium memory somehow.

But, where? There are a tons of strings in this 80GB chromium memory dump. From this point I assumed that chromium has to encode the value in a recoverable way, so clear text or base64, and it has to use it frequently to avoid prompting a login request.

Stop digging around

Using strings and grep won’t give me a good way to know where exactly is stored passwords from an HTTP basic authentication. To do so, a good method is simply to replay the attack ourself, on our VM with a known password and a known user name. We can then check precisely where they are located in chromium’s memory. I created a small web server running with nginx, and installed chromium. I modified nginx configuration so that it asks for credentials on connection using HTTP basic authentication and finally logged in with somedumuser:WAHLAH.

basic_auth_vm

Once this is done, I pause my VM, get start enumerating chromium’s PID using volatility:

[...]
15147  33     33     nginx: worker process
15288  1000   1000   /usr/lib/chromium/chromium --show-component-extension-options --enable-gpu-rasterization --no-default-browser-check --disable-pings --media-router=0 --enable-remote-extensions --load-extension
15302  1000   1000   /usr/lib/chromium/chrome-sandbox /usr/lib/chromium/chromium --type=zygote
15303  1000   1000   /usr/lib/chromium/chromium --type=zygote
15305  1000   1000   /usr/lib/chromium/chromium --type=zygote
15327  1000   1000   /usr/lib/chromium/chromium --type=gpu-process --field-trial-handle=4374570028609503657,3240024535021515531,131072 --enable-gpu-rasterization --gpu-preferences=MAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAQAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA= --s
15329  1000   1000   /usr/lib/chromium/chromium --type=utility --field-trial-handle=4374570028609503657,3240024535021515531,131072 --lang=en-US --service-sandbox-type=network --disable-webrtc-apm-in-audio-service --shared-files=v8_snapsh
15486  1000   1000   /usr/lib/chromium/chromium --type=rendere
15519  1000   1000   /usr/lib/chromium/chromium --type=rendere
15714  0      0      [kworker/2:1]
[...]

Ok so we got a bunch of chromiums process, we will need to find which one stores our credentials. I doubt that there is more than one used to store those, but more than one means more chance to get them anyway.

I get all chromiums pid into a file using:

cat pids.txt | grep chr | sed "s/  \+/ /g" | cut -d " " -f3 > chrpids.txt

I dumped the memory of all chromium processes, and started to use strings in my dumps to locate my password using. (Note : I first had no result, and I tried again using -el and found my password, which indicates that they are stored using wide char encoding).

> strings * --print-file-name | grep WAHLAH
task.15329.0x7f503c000000.vma: WAHLAH
task.15329.0x7f503c000000.vma: WAHLAH

This looks good ! The password is located in a single file of a single process. This is the process 15329, on a part of the memory ending by 3c000000. This is a good indicator because chromium’s memory should be aligned the same way between the one of our VM and the one of the dump.

If we look at our chromium pid list, we can notice that this pid corresponds to the chromium instance that uses --type=utility as argument. That is a nice way of recognizing the right process! Unfortunately, our real dump does not show any command line arguments when I list pids.

But we can notice that according to the process list of our VM, the chromium processes spawns in the order :

  • 15288 (first chromium)
  • 15302 (chrome-sandbox)
  • 15303, 15305 (standard chromium)
  • 15327 (–type=gpu-process)
  • 15329 –type-utility

So one process is spawned, then the sandbox, then 2 process, and finally one gpu-process before our utility.

vm_find_right_chromium

Similarly, we can find the right process on our targeted dump.

image-20200504051526172

We dump all its memory, and start searching for a memory aligned with 3c000000.

image-20200504051934292

This section seems to have a similar size and to be align on the same address.

As we know that passwords and user names are stored using windows encoding (wide character), we can do strings -el ./task.119187.0x7fb1cc000000.vma:

image-20200504052110361

We get a bunch of garbage and what is with no doubt an interesting string, which is probably the user name we are looking for. The second most probable real string is 5sdtYh68, which found out to be the password.

Executing the same command on the memory from our VM will confirm that the other strings are just garbage:

image-20200504052321191

There are now good chances for Admin3Kz7:5sdtYh68 to be valid credentials, and they were !

Flag : FCSC{Admin3Kz7:5sdtYh68}