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 usingKeePass
(/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
:
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
.
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.
Similarly, we can find the right process on our targeted dump.
We dump all its memory, and start searching for a memory aligned with 3c000000
.
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
:
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:
There are now good chances for Admin3Kz7:5sdtYh68
to be valid credentials, and they were !
Flag : FCSC{Admin3Kz7:5sdtYh68}