IrisCTF 2025: Tracem 2

Challenge Name: Tracem 2

Category: Forensics

Author: @Skat

Challenge Description:

Another knock from our ISP and HR looking for a John Doe... but now it's not so easy.

Flag format: irisctf{username} (e.g. irisctf{jdoe}). Usernames are case-sensitive.

Artifact Files:

Logs Analysis:

More RADIUS logs! As before, we see DHCP and DNS stream traffic as well as user authentications and disconnects - except this time, the challenge requires some lateral thinking to solve!

Like last time, I took a more minimal approach and just went with my IDE of choice and some grep and regex magic :)

As always when starting log analysis, I get a unique list of URIs requested to identify traffic with interesting domains:

grep -oP 'queries.*"name":\s"\K[^"]*' logs.json | sort -u > query_domains.txt

Output:

Output Image 1

After looking through the output, I noticed some bad domains:

Output Image 2

Following the same strategy as Tracem 1, I look for all traffic requesting these domains:

grep -iE "queries.*(piratebay|generic-illicit)" logs.json

Output:

{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:51:51.12", "data": {"timestamp": "2024-12-04 08:51:51.092921", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 48851, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 119, "queries": [{"type": "A", "class": "IN", "name": "thepiratebay.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:51:51.13", "data": {"timestamp": "2024-12-04 08:51:51.102210", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 2975, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 13007, "queries": [{"type": "AAAA", "class": "IN", "name": "thepiratebay.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 09:05:01.12", "data": {"timestamp": "2024-12-04 09:05:00.400067", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 22066, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 2835, "queries": [{"type": "A", "class": "IN", "name": "generic-illicit-activities-hub.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 09:05:00.70", "data": {"timestamp": "2024-12-04 09:05:00.520979", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 64559, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 3019, "queries": [{"type": "AAAA", "class": "IN", "name": "generic-illicit-activities-hub.org"}]}}

Seeing that the only IP requesting those is 10.18.21.121, I check for DHCP assignments:

grep -iE "10.18.21.121.*(DHCPACK|DHCPREQUEST|DHCPRELEASE)" logs.json

Output:

{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 08:49:21.00", "data": {"timestamp": "2024-12-04 08:49:20.982612", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "EB:A8:B3:FB:A0:AB", "src_ip": "10.18.0.2", "src_port": 67, "dest_mac": "de:ad:be:ef:ca:fe", "dest_ip": "10.18.21.121", "dest_port": 68, "chaddr": "de:ad:be:ef:ca:fe", "ciaddr": "10.18.21.121", "transaction_id": 1005317175, "opcode": "DHCPACK"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 09:22:01.12", "data": {"timestamp": "2024-12-04 09:22:00.411200", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "de:ad:be:ef:ca:fe", "src_ip": "10.18.21.121", "src_port": 68, "dest_mac": "FF:FF:FF:FF:FF:FF", "dest_ip": "255.255.255.255", "dest_port": 67, "chaddr": "de:ad:be:ef:ca:fe", "ciaddr": "0.0.0.0", "transaction_id": 2674233379, "opcode": "DHCPRELEASE"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 09:22:01.15", "data": {"timestamp": "2024-12-04 09:22:00.519792", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "EB:A8:B3:FB:A0:AB", "src_ip": "10.18.0.2", "src_port": 67, "dest_mac": "de:ad:be:ef:ca:fe", "dest_ip": "10.18.21.121", "dest_port": 68, "chaddr": "de:ad:be:ef:ca:fe", "ciaddr": "10.18.21.121", "transaction_id": 2674233379, "opcode": "DHCPACK"}}

Looking at this activity, we can see that this IP address is assigned to (likely spoofed) MAC address de:ad:be:ef:ca:fe - lovely nod to DEADBEEF and DEADCAFE :)

Now, this is where the challenge requires some lateral thinking. This IP address is not included in any SAML / SSO URIs containing a username, and in fact, we see no reassignments or reusage of this de:ad:be:ef:ca:fe MAC address anywhere in the logs...

grep -iE "de:ad:be:ef:ca:fe" logs.json

Output:

{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 08:49:20.52", "data": {"timestamp": "2024-12-04 08:49:20.310176", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "de:ad:be:ef:ca:fe", "src_ip": "0.0.0.0", "src_port": 68, "dest_mac": "FF:FF:FF:FF:FF:FF", "dest_ip": "255.255.255.255", "dest_port": 67, "chaddr": "de:ad:be:ef:ca:fe", "ciaddr": "0.0.0.0", "transaction_id": 1005317175, "opcode": "DHCPREQUEST", "riaddr": "10.18.21.121"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 08:49:21.00", "data": {"timestamp": "2024-12-04 08:49:20.982612", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "EB:A8:B3:FB:A0:AB", "src_ip": "10.18.0.2", "src_port": 67, "dest_mac": "de:ad:be:ef:ca:fe", "dest_ip": "10.18.21.121", "dest_port": 68, "chaddr": "de:ad:be:ef:ca:fe", "ciaddr": "10.18.21.121", "transaction_id": 1005317175, "opcode": "DHCPACK"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 09:22:01.12", "data": {"timestamp": "2024-12-04 09:22:00.411200", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "de:ad:be:ef:ca:fe", "src_ip": "10.18.21.121", "src_port": 68, "dest_mac": "FF:FF:FF:FF:FF:FF", "dest_ip": "255.255.255.255", "dest_port": 67, "chaddr": "de:ad:be:ef:ca:fe", "ciaddr": "0.0.0.0", "transaction_id": 2674233379, "opcode": "DHCPRELEASE"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 09:22:01.15", "data": {"timestamp": "2024-12-04 09:22:00.519792", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "EB:A8:B3:FB:A0:AB", "src_ip": "10.18.0.2", "src_port": 67, "dest_mac": "de:ad:be:ef:ca:fe", "dest_ip": "10.18.21.121", "dest_port": 68, "chaddr": "de:ad:be:ef:ca:fe", "ciaddr": "10.18.21.121", "transaction_id": 2674233379, "opcode": "DHCPACK"}}

So, to organize the evidence we have so far, I made a table of these DHCP events - as forensic analysts, tables are our best friend :)

Timestamp Event Notes
2024-12-04 08:49:20.52 de:ad:be:ef:ca:fe first requests IP assignment requests 10.18.21.121
2024-12-04 08:49:20.982612 first IP assignment to de:ad:be:ef:ca:fe assigned 10.18.21.121
2024-12-04 09:22:00.411200 de:ad:be:ef:ca:fe releases IP 10.18.21.121
2024-12-04 09:22:00.519792 last IP assignment to de:ad:be:ef:ca:fe assigned 10.18.21.121

Now we grep for queried domains by the 10.18.21.121 IP address, extract the domain, and add to the table:

grep -oP '.*10.18.21.121.*queries.*' logs.json > 10-18-21-121_queries.txt

Output:

{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:49:34.58", "data": {"timestamp": "2024-12-04 08:49:33.772810", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 42110, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 61288, "queries": [{"type": "A", "class": "IN", "name": "www.google.com"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:49:34.58", "data": {"timestamp": "2024-12-04 08:49:33.780002", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 12733, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 25258, "queries": [{"type": "AAAA", "class": "IN", "name": "www.google.com"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:51:18.72", "data": {"timestamp": "2024-12-04 08:51:17.829209", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 18183, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 6754, "queries": [{"type": "A", "class": "IN", "name": "2.arch.pool.ntp.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:51:18.73", "data": {"timestamp": "2024-12-04 08:51:17.830022", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 4232, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 34487, "queries": [{"type": "AAAA", "class": "IN", "name": "2.arch.pool.ntp.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:51:51.12", "data": {"timestamp": "2024-12-04 08:51:51.092921", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 48851, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 119, "queries": [{"type": "A", "class": "IN", "name": "thepiratebay.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 08:51:51.13", "data": {"timestamp": "2024-12-04 08:51:51.102210", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 2975, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 13007, "queries": [{"type": "AAAA", "class": "IN", "name": "thepiratebay.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 09:05:01.12", "data": {"timestamp": "2024-12-04 09:05:00.400067", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 22066, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 2835, "queries": [{"type": "A", "class": "IN", "name": "generic-illicit-activities-hub.org"}]}}
{"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 09:05:00.70", "data": {"timestamp": "2024-12-04 09:05:00.520979", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.18.21.121", "src_port": 64559, "dest_ip": "10.18.0.2", "dest_port": 53, "transaction_id": 3019, "queries": [{"type": "AAAA", "class": "IN", "name": "generic-illicit-activities-hub.org"}]}}

Putting into a table:

Timestamp Event Notes
2024-12-04 08:49:20.52 de:ad:be:ef:ca:fe first requests IP assignment requests 10.18.21.121
2024-12-04 08:49:20.982612 first IP assignment to de:ad:be:ef:ca:fe assigned 10.18.21.121
2024-12-04 08:49:34.58 10.18.21.121 requests www.google.com
2024-12-04 08:51:18.72 10.18.21.121 requests 2.arch.pool.ntp.org device runs Arch!
2024-12-04 08:51:51.12 10.18.21.121 requests thepiratebay.org illicit domain
2024-12-04 09:05:01.12 10.18.21.121 requests generic-illicit-activities-hub.org illicit domain
2024-12-04 09:22:00.411200 de:ad:be:ef:ca:fe releases IP 10.18.21.121
2024-12-04 09:22:00.519792 last IP assignment to de:ad:be:ef:ca:fe assigned 10.18.21.121

Nice! We can see that the device in question is running Arch!

Arch Fedora GIF

My next step will be to grab all unique IPs contacting that Arch NTP domain:

grep -iE 'queries.*2.arch.pool.ntp.org' logs.json | grep -oP '"src_ip":\s"\K[^"]*' | sort -u

Output:

10.17.161.10
10.17.171.253
10.17.26.247
10.17.6.47
10.17.90.14
10.18.21.121
10.34.192.28
10.35.126.228
10.49.220.32
10.49.65.21
10.49.79.62
10.50.103.29
10.50.184.143
10.51.64.145
10.65.228.127
10.65.26.90
10.65.68.160
10.66.156.255
10.66.68.75
10.66.91.95
10.67.252.116

Now, I'll extract SAML / SSO URIs from the logs that contain X11 as a user agent, so we can exclude SSO usernames from any machines that aren't running a unix flavor:

grep -iE '.*X11;.*saml2/sso.*' logs.json > linux_saml.json

Output: 125 SAML URIs from 94 unique IP addresses and users.

Using a monster of a one-liner instead of a few lines of Python (I was sick and not thinking quite right), we filter the SAML even further by the IP addresses we saw reach out to the Arch NTP server:

IFS=',' read -ra ips <<< "10.17.161.10,10.17.171.253,10.17.26.247,10.17.6.47,10.17.90.14,10.18.21.121,10.34.192.28,10.35.126.228,10.49.220.32,10.49.65.21,10.49.79.62,10.50.103.29,10.50.184.143,10.51.64.145,10.65.228.127,10.65.26.90,10.65.68.160,10.66.156.255,10.66.68.75,10.66.91.95,10.67.252.116" && for ip in "${ips[@]}"; do grep "$ip" linux_saml.json; done

Output:

{"host": "primary", "source": "udp:514", "sourcetype": "syslog", "_time": "2024-12-04 07:42:16.11", "data": {"_raw": "2024-12-04 07:42:16.058355||https://sso.evil-insurance.corp/idp/profile/SAML2/Redirect/SSO|/idp/profile/SAML2/Redirect/SSO|6be5e0fe638be3ae75c3702ae6f3fa91|authn/MFA|10.17.161.10|Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/53.0.3 Safari/537.3|https://sso.evil-insurance.corp/ns/profiles/saml2/sso/browser|mhammond||uid|gitlab.evil-insurance.corp|https://sso.evil-insurance.corp/idp/sso|url:oasis:names:tc:SAML:2.0:protocol|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST|dxjj4bc2qh7nNYCxDufIMJUJgZg7XEC6stCo4dlJwt74i2KuXFbL6Qx3OJEOSOdnvea2zz6oK76KK2/9xWxJ0A==|urn:oasis:names:tc:SAML:2.0:nameid-format:transient|_2b0a5fe78da29cb3c501145bf54e92a5|2024-12-04 07:42:16.058355|_5cee657f-4daf-4b2f-bdaf-9bee0d9bc103||||urn:oasis:names:tc:SAML:2.0:status:Success|||false|false|true", "timestamp": "2024-12-04 07:42:16.058355", "xWxJ0A": "=|urn:oasis:names:tc:SAML:2.0:nameid-format:transient|_2b0a5fe78da29cb3c501145bf54e92a5|2024-12-04"}}
{"host": "primary", "source": "udp:514", "sourcetype": "syslog", "_time": "2024-12-04 05:31:30.54", "data": {"_raw": "2024-12-04 05:31:29.304465||https://sso.evil-insurance.corp/idp/profile/SAML2/Redirect/SSO|/idp/profile/SAML2/Redirect/SSO|5430468a84a6a6b63c68a49e42f24275|authn/MFA|10.51.64.145|Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/53.0.3 Safari/537.3|https://sso.evil-insurance.corp/ns/profiles/saml2/sso/browser|acontreras2||uid|meetings.evil-insurance.corp|https://sso.evil-insurance.corp/idp/sso|url:oasis:names:tc:SAML:2.0:protocol|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST|pctKS7XkclQzMdECw1+eu/VhrvlwDZjkNhKMcFsEFWjyxW36buimeNRMavUTAWb83aZ5ngkbZ5ByweVG0FlHKQ==|urn:oasis:names:tc:SAML:2.0:nameid-format:transient|_c32d5abb27783f04758e5894299096f4|2024-12-04 05:31:29.304465|_44f5c896-9a99-4e15-95fb-6c41f04c1ce8||||urn:oasis:names:tc:SAML:2.0:status:Success|||false|false|true", "timestamp": "2024-12-04 05:31:29.304465", "VhrvlwDZjkNhKMcFsEFWjyxW36buimeNRMavUTAWb83aZ5ngkbZ5ByweVG0FlHKQ": "=|urn:oasis:names:tc:SAML:2.0:nameid-format:transient|_c32d5abb27783f04758e5894299096f4|2024-12-04"}}
{"host": "primary", "source": "udp:514", "sourcetype": "syslog", "_time": "2024-12-04 10:18:09.91", "data": {"_raw": "2024-12-04 10:18:08.976782||https://sso.evil-insurance.corp/idp/profile/SAML2/Redirect/SSO|/idp/profile/SAML2/Redirect/SSO|2d33d3cd963380d37bb220bdc945c980|authn/MFA|10.51.64.145|Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/53.0.3 Safari/537.3|https://sso.evil-insurance.corp/ns/profiles/saml2/sso/browser|acontreras2||uid|hr.evil-insurance.corp|https://sso.evil-insurance.corp/idp/sso|url:oasis:names:tc:SAML:2.0:protocol|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST|JEK418ch88IQvEQTai3LIFsZoikWh6tMVU2yo0slelw6+4FlQ4zqqx2eNY4dcKOnahCwpggJDtSW+blZy08fpA==|urn:oasis:names:tc:SAML:2.0:nameid-format:transient|_d8af2b509e27067880c52462899fabfd|2024-12-04 10:18:08.976782|_1992e0b0-dcda-410c-8136-8e350bf8970b||||urn:oasis:names:tc:SAML:2.0:status:Success|||false|false|true", "timestamp": "2024-12-04 10:18:08.976782", "blZy08fpA": "=|urn:oasis:names:tc:SAML:2.0:nameid-format:transient|_d8af2b509e27067880c52462899fabfd|2024-12-04"}}

We see two users here! mhammond, using IP 10.17.161.10, and acontreras2, using IP 10.51.64.145.

From here, I want to filter on the disconnects and successful authentications for each of these users - I'll then put that into our timeline. For brevity's sake, I started with mhammond, only including the most relevant events:

grep -iE '((authentication|disconnect).*10.17.161.10)|(.*10.17.161.10.*(DHCPREQUEST|DHCPRELEASE|DHCPACK))' logs.json > 10-17-161-10_events.json

Output (some relevant events, there are 58 total events in the one-liner output):

{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 08:45:31.83", "data": {"timestamp": "2024-12-04 08:45:30.896506", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "8E:BC:D0:56:E9:D6", "src_ip": "10.17.0.2", "src_port": 67, "dest_mac": "53:75:56:a7:98:8f", "dest_ip": "10.17.161.10", "dest_port": 68, "chaddr": "53:75:56:a7:98:8f", "ciaddr": "10.17.161.10", "transaction_id": 641194902, "opcode": "DHCPACK"}}
{"host": "primary", "source": "udp:514", "sourcetype": "syslog", "_time": "2024-12-04 08:35:27.57", "data": {"_raw": "2024-12-04 08:45:33.555166 net-ctrl1 dot1x-proc:1[4406]: <522300> <4406>   User disconnected. username=1021321009 ip=10.17.161.10 usermac=53:75:56:a7:98:8f authmethod=802.1x servername=cppm01-RADIUS serverip=10.17.0.3 apname=B1-W0 bssid=F4:2E:7F:FF:FB:EC", "timestamp": "2024-12-04 08:45:33.555166", "username": "1021321009", "ip": "10.17.161.10", "usermac": "53:75:56:a7:98:8f", "authmethod": "802.1x", "servername": "cppm01-RADIUS", "serverip": "10.17.0.3", "apname": "B1-W0", "bssid": "F4:2E:7F:FF:FB:EC"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 09:42:01.53", "data": {"timestamp": "2024-12-04 09:42:00.907257", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "8E:BC:D0:56:E9:D6", "src_ip": "10.17.0.2", "src_port": 67, "dest_mac": "53:75:56:a7:98:8f", "dest_ip": "10.17.161.10", "dest_port": 68, "chaddr": "53:75:56:a7:98:8f", "ciaddr": "10.17.161.10", "transaction_id": 2426784686, "opcode": "DHCPACK"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 09:51:03.70", "data": {"timestamp": "2024-12-04 09:51:02.958353", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "8E:BC:D0:56:E9:D6", "src_ip": "10.17.0.2", "src_port": 67, "dest_mac": "53:75:56:a7:98:8f", "dest_ip": "10.17.161.10", "dest_port": 68, "chaddr": "53:75:56:a7:98:8f", "ciaddr": "10.17.161.10", "transaction_id": 2426784686, "opcode": "DHCPACK"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 10:05:29.46", "data": {"timestamp": "2024-12-04 10:05:28.681512", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "8E:BC:D0:56:E9:D6", "src_ip": "10.17.0.2", "src_port": 67, "dest_mac": "53:75:56:a7:98:8f", "dest_ip": "10.17.161.10", "dest_port": 68, "chaddr": "53:75:56:a7:98:8f", "ciaddr": "10.17.161.10", "transaction_id": 2426784686, "opcode": "DHCPACK"}}
{"host": "primary", "source": "stream:dhcp", "sourcetype": "stream:dhcp", "_time": "2024-12-04 10:12:22.75", "data": {"timestamp": "2024-12-04 10:12:22.333422", "protocol_stack": "ip:udp:dhcp", "transport": "udp", "src_mac": "8E:BC:D0:56:E9:D6", "src_ip": "10.17.0.2", "src_port": 67, "dest_mac": "53:75:56:a7:98:8f", "dest_ip": "10.17.161.10", "dest_port": 68, "chaddr": "53:75:56:a7:98:8f", "ciaddr": "10.17.161.10", "transaction_id": 2426784686, "opcode": "DHCPACK"}}
{"host": "primary", "source": "udp:514", "sourcetype": "syslog", "_time": "2024-12-04 09:41:57.11", "data": {"_raw": "2024-12-04 10:12:24.054146 net-ctrl1 dot1x-proc:1[4406]: <522300> <4406>   User disconnected. username=1021321009 ip=10.17.161.10 usermac=53:75:56:a7:98:8f authmethod=802.1x servername=cppm01-RADIUS serverip=10.17.0.3 apname=B1-W3 bssid=F4:2E:7F:FC:30:CC", "timestamp": "2024-12-04 10:12:24.054146", "username": "1021321009", "ip": "10.17.161.10", "usermac": "53:75:56:a7:98:8f", "authmethod": "802.1x", "servername": "cppm01-RADIUS", "serverip": "10.17.0.3", "apname": "B1-W3", "bssid": "F4:2E:7F:FC:30:CC"}}

Putting relevant events into table:

Timestamp Event Notes
2024-12-04 08:45:33.555166 10.17.161.10 (mhammond) disconnects from network releases 10.17.161.10 + pause in traffic from 10.17.161.10
2024-12-04 08:49:20.52 de:ad:be:ef:ca:fe first requests IP assignment requests 10.18.21.121
2024-12-04 08:49:20.982612 first IP assignment to de:ad:be:ef:ca:fe assigned 10.18.21.121
2024-12-04 08:49:34.58 10.18.21.121 requests www.google.com
2024-12-04 08:51:18.72 10.18.21.121 requests 2.arch.pool.ntp.org device runs Arch!
2024-12-04 08:51:51.12 10.18.21.121 requests thepiratebay.org illicit domain
2024-12-04 09:05:01.12 10.18.21.121 requests generic-illicit-activities-hub.org illicit domain
2024-12-04 09:22:00.411200 de:ad:be:ef:ca:fe releases IP 10.18.21.121
2024-12-04 09:22:00.519792 last IP assignment to de:ad:be:ef:ca:fe assigned 10.18.21.121
2024-12-04 09:42:00.907257 IP assignment to 10.17.161.10 (mhammond) traffic from 10.17.161.10 continues

This makes much more sense now! We can see that mhammond is the likely user visiting those illicit sites! The flag is irisctf{mhammond}

This challenge required slightly more nuanced log analysis knowledge, but overall the biggest change was the necessity of lateral thinking - in forensics, we're often presented with situations where we need to think creatively to solve a problem, even if what we find may not be definitive evidence to prove an event occurred how we think it did - in this case, we would likely collect an image and/or system artifacts from mhammond's work machine to further prove illegitimate activity was performed using that device.

From an analyst's perspective, this was a very fun challenge to work on, and directly reflects the work I do professionally, which is a breath of fresh air compared to many CTF forensics challenges that model unique or impractical techniques compared to daily work. Best regards to Skat for this challenge :)