The Logs Aren’t Alright
Description
A new social media star arises, fans asking personal questions, sponsor emails raining like crazy. The case CloutHaus: Social Media leads to Compromise teaches security awareness going beyond corp boundaries.

Note: The scope of this write-up will be explaining the KQL queries used to solve the exercise questions. If you wanna enjoy the full story, go check KC7 Game, it’s free.
Tasks
-
According to CloutHaus internal employee logs, what is Afomiya’s designated professional email?
The table Employees includes all the personnel information. Here we may look for Afomiya’s email.
This query will solve questions 1 to 3:
Employees | where name contains "afomiya"-
Employeessets the table to be looked at, which optimizes the searching performance. -
whereshows results based on satisfied conditions to extract the relevant logs from noise. -
nameis the field that the query is interested in, do please note that it is case-sensitive. -
containssearches for strings containing the provided characters, for example the records may include afomiya123 or xyzafomiya.

So, Afomiya’s designated professional email can be found at the field email_addr.
Answer:
afomiya_storm@clouthaus[.]com -
-
What is Afomiya’s role with CloutHaus?
The role of Afomiya is within the field role.
Answer:
Influencer Partner -
Based on the CloutHaus employee table, what is the status of Multi-Factor Authentication (MFA) for Afomiya’s account?
Look at the mfa_enabled field, bad practice but it is what it is.
Answer:
False -
What is the sender’s email address in the email Afomiya received from “Dior”?
Now, we’re looking through the Email table, then use the recipient email and do a general search with the keyword dior.
This query will solve questions 4 to 6:
Email | where recipient == "afomiya_storm@clouthaus.com" | where subject contains "dior" or links contains "dior"-
==is the equal operator, which must match every character of the provided string. -
orunites two conditions, if one of them are satisfied, then it returns the matched row.

Then, the sender email is found at the sender field.
Answer:
collabs@dior-partners[.]com -
-
What is the subject line of the email Afomiya received from “Dior”?
Search for the field subject and you got it.
Answer:
[EXTERNAL] Exclusive Partnership Opportunity with Dior -
What is the link provided in the email?
Look at the list field called links.
Answer:
hxxps[:]//super-brand-offer[.]com/login -
When did Afomiya click on the link? Paste the entire timestamp.
The OutboundNetworkEvents table records whenever a user visits a website, let’s write it down.
This query will solve questions 7 to 8:
OutboundNetworkEvents | where url contains "https://super-brand-offer.com/login"This is the first time Afomiya clicked the URL:

And this is the login attempt performed by Afomiya:

So, better take the first generated event’s timestamp.
Answer:
2025-04-03T11:20:00.000Z -
What username did she enter?
Within the url value there is a parameter called username.
Answer:
afstorm -
What is the IP address associated with the domain?
Every IP could have an associated domain, that’s when PassiveDNS table comes into play.
PassiveDns | where domain contains "super-brand-offer.com"
Check the ip field.
Answer:
198[.]51[.]100[.]12 -
How many distinct domains are linked to the suspicious IP address?
The previous query may be updated to search all the domains that have shared the same IP address.
PassiveDns | where ip == "198.51.100.12" | distinct domaindistinctserves to display just one entry for each match, for example if there are three rows with the same domain, then the results will show that domain once.

Then, the count sums 3 different domains.
Answer:
3 -
What IP address was used to gain access?
The AuthenticationEvents table may provide the information related to account access attempts.
This query will solve questions 11 and 13:
AuthenticationEvents | where username == "afstorm"
Here, the question focuses on Afomiya’s email, then correlate the MAIL-SERVER01 with the src_ip.
Answer:
182[.]45[.]67[.]89 -
What domains are associated with this IP? (enter one)
Let’s use the reliable PassiveDNS table for this question.
PassiveDns | where ip == "182.45.67.89" | distinct domain
So, just provide one of the two domains.
Answer:
influencer-deals[.]net -
What part of the User-Agent string indicates the suspicious browser and operating system? (Submit either the browser name/version or the operating system name/version.)
Look at the question 11 results, there is a field called user_agent.
Answer:
Mozilla/5.0 (compatible; MSIE 5.0; Windows NT 5.2; Trident/4.1) -
What country did the login originate from?
Here, KC7 recommends the tool MaxMind to look for the IP Geolocation.

In this case, just put the country that resides in the Location field.
Answer:
China -
According to the attacker’s web search history on the site, what were they trying to hack?
Let’s check the InboundNetworkEvents activity from the ip 182[.]45[.]67[.]89.
InboundNetworkEvents | where src_ip == "182.45.67.89"
Looking through the url records, one stands out for containing the keyword hack and so the target.
Answer:
Location -
According to another search log, what kind of personal info were they sneakily trying to uncover (and pretending to ask “for a friend”)?
Now, add another filter to the previous InboundNetworkEvents table, to reduce the logs noise.
InboundNetworkEvents | where src_ip == "182.45.67.89" | where url has "friend"hashunts for a complete case-insensitive string, for example best friend has friend or fRiEnD.

Then, the threat actor was looking for Afomiya’s residence.
Answer:
Home Address -
What kind of account or app does that log suggest they were targeting? (Note: It’s about money).
So, if money is involved, we may build up a list of possible keywords to get to the roots in the InboundNetworkEvents logs.
let keywords = dynamic(["payment", "transaction", "history"]); InboundNetworkEvents | where src_ip == "182.45.67.89" | where url has_any (keywords)letcreates a variable, like an expression or a function, great for reusing along the query.dynamicsets up a flexible data type going from key-value structures to a list of elements.;do not skip it, as it closes the sentence to proceed with the next instruction.has_anyis the evolution of has, compares with a predefined array of values.

In the url path segment there is a reference to a known payment service.
Answer:
Venmo -
Based on another search, what shady and fake event were they pretending to plan as a way to lure Afomiya?
Within the InboundNetworkEvents table, we may globally search for the asked keyword.
InboundNetworkEvents | where src_ip == "182.45.67.89" | search "fake" | distinct urlsearchlooks for any match no matter the case sensitiveness nor the fields, then it’s costly.

As the question needs an event, choose the one that is closer.
Answer:
Birthday Party -
What external email address received messages forwarded from Afomiya’s account?
It’s an exfiltration technique, where the threat actor sets a forward rule in the victim’s Email.
Email | where sender == "afomiya_storm@clouthaus.com" | where subject has "forward"
So, we may confirm that there is a established forwarding rule pointing to a particular recipient.
Answer:
noreply@influencer-deals[.]net -
Which forwarded email contained Afomiya’s payment details or direct deposit form?
We may take advantage of the previous Email query, with an extra sauce.
Email | where sender == "afomiya_storm@clouthaus.com" | where subject has_all ("forward", "deposit")has_allrequires that every keyword in the provided list be present in the target field.

The subject provides the exact information that we’re looking for.
Answer:
[EXTERNAL] [FORWARD] Afomiya's payment details – direct deposit form -
What forwarded email subject included a passport scan?
What if the keywords are defined as a list, before searching in the Email table.
let keywords = dynamic(["forward", "passport"]); Email | where sender == "afomiya_storm@clouthaus.com" | where subject has_all (keywords)
Now we’re in the mood, getting to the same solution in different ways. Take out the subject.
Answer:
[EXTERNAL] [FORWARD] Afomiya's passport scan – confidential -
Which forwarded email subject contained either Afomiya’s bank statement or year-end tax documents?
What if the keywords are defined as a list, before searching in the Email table.
let keywords = dynamic(["bank", "tax"]); Email | where sender == "afomiya_storm@clouthaus.com" | where subject has "forward" and subject has_any (keywords) | distinct subjectandcombines two conditions which both must be true, in order to return the matched row.

And this is how we can build up more complex queries overtime. Go ahead with any subject.
Answer:
[EXTERNAL] [FORWARD] Re: Re: Re: Afomiya's bank statement – confidential -
Based on everything you’ve discovered, what do you think the attacker’s true objective was?
This investigation involved a multi-stage attack, starting from a phishing email targeting Afomiya’s CloutHaus account, which got the keys to the castle stolen.
It led to the setting of a forwarding rule for constant data exfiltration to the threat actor’s email. Along with the data harvesting technique, trying to know everything about the victim’s Personally Identifiable Information (PII) within the Clouthaus website.
Then, the answer should consider all the observed attack vectors and malicious intentions.

Final Thoughts: Who knows what may come next after this initial breach, but once the detection and analysis are done, this incident should proceed with the containment, eradication and recovery of Afomiya’s account, finishing with a due care and diligent post-incident activity which strengthens the security posture of Clouthaus’ identity management. Think twice, click once, otherwise get zeroed
Raw Results
This is a space for saving the query results in text format, useful whenever a value is needed.
Employees
"hire_date": 2024-10-10T00:00:00.000Z,
"name": Afomiya Storm,
"user_agent": Mozilla/5.0 (Windows NT 10.0; rv:51.0) Gecko/20100101 Firefox/51.0,
"ip_addr": 10.10.0.3,
"email_addr": afomiya_storm@clouthaus.com,
"username": afstorm,
"role": Influencer Partner,
"hostname": OQPA-DESKTOP,
"mfa_enabled": False,
"company_domain": clouthaus.com
"timestamp": 2025-04-03T10:41:00.000Z,
"sender": collabs@dior-partners.com,
"reply_to": collabs@dior-partners.com,
"recipient": afomiya_storm@clouthaus.com,
"subject": [EXTERNAL] Exclusive Partnership Opportunity with Dior,
"verdict": CLEAN,
"links": [
"https://super-brand-offer.com/login"
],
"attachments":
"timestamp": 2025-04-08T15:59:54.000Z,
"sender": afomiya_storm@clouthaus.com,
"reply_to": afomiya_storm@clouthaus.com,
"recipient": noreply@influencer-deals.net,
"subject": [EXTERNAL] [FORWARD] Re: Re: Afomiya’s dog photos – VERY DEMURE, VERY CUTE,
"verdict": CLEAN,
"links": [
""
],
"attachments":
"timestamp": 2025-04-08T15:55:21.000Z,
"sender": afomiya_storm@clouthaus.com,
"reply_to": afomiya_storm@clouthaus.com,
"recipient": noreply@influencer-deals.net,
"subject": [EXTERNAL] [FORWARD] Afomiya’s payment details – direct deposit form,
"verdict": CLEAN,
"links": [
""
],
"attachments":
"timestamp": 2025-04-08T15:56:38.000Z,
"sender": afomiya_storm@clouthaus.com,
"reply_to": afomiya_storm@clouthaus.com,
"recipient": noreply@influencer-deals.net,
"subject": [EXTERNAL] [FORWARD] Afomiya’s passport scan – confidential,
"verdict": CLEAN,
"links": [
""
],
"attachments":
[EXTERNAL] [FORWARD] Re: Re: Re: Afomiya’s bank statement – confidential
[EXTERNAL] [FORWARD] Re: Tax documents – year-end summary
OutboundNetworkEvents
"timestamp": 2025-04-03T11:20:00.000Z,
"method": GET,
"src_ip": 10.10.0.3,
"user_agent": Mozilla/5.0 (Windows NT 10.0; rv:51.0) Gecko/20100101 Firefox/51.0,
"url": https://super-brand-offer.com/login
"timestamp": 2025-04-03T11:20:02.000Z,
"method": GET,
"src_ip": 10.10.0.3,
"user_agent": Mozilla/5.0 (Windows NT 10.0; rv:51.0) Gecko/20100101 Firefox/51.0,
"url": https://super-brand-offer.com/login?username=afstorm&password=**********
PassiveDNS
"timestamp": 2025-04-01T10:20:34.000Z,
"ip": 198.51.100.12,
"domain": super-brand-offer.com
super-brand-offer.com
dior-partners.com
influencer-deals.net
AuthenticationEvents
"timestamp": 2025-04-03T12:20:00.000Z,
"hostname": MAIL-SERVER01,
"src_ip": 182.45.67.89,
"user_agent": Mozilla/5.0 (compatible; MSIE 5.0; Windows NT 5.2; Trident/4.1),
"username": afstorm,
"result": Successful Login,
"password_hash": a2feaddef8e617fa9cf861b3b49b1dd5,
"description": User successfully logged into their email account.
InboundNetworkEvents
"timestamp": 2025-04-03T14:23:21.000Z,
"method": GET,
"src_ip": 182.45.67.89,
"user_agent": Mozilla/5.0 (compatible; MSIE 5.0; Windows NT 5.2; Trident/4.1),
"url": https://clouthaus.com/search=How+to+hack+an+influencer’s+location+from+their+Instagram+story,
"referrer": https:clouthaus.com/search,
"status_code": 200
"timestamp": 2025-04-03T00:00:00.000Z,
"method": GET,
"src_ip": 182.45.67.89,
"user_agent": Mozilla/5.0 (compatible; MSIE 5.0; Windows NT 5.2; Trident/4.1),
"url": https://clouthaus.com/search=Afomiya+Storm+home+address??+(asking+for+a+friend),
"referrer": https:clouthaus.com/search,
"status_code": 200
"timestamp": 2025-04-04T14:21:29.000Z,
"method": GET,
"src_ip": 182.45.67.89,
"user_agent": Mozilla/5.0 (compatible; MSIE 5.0; Windows NT 5.2; Trident/4.1),
"url": https://clouthaus.com/search=Afomiya’s+Venmo+history+–+is+that+public??,
"referrer": https:clouthaus.com/search,
"status_code": 200
https://clouthaus.com/search=How+to+fake+an+influencer+friendship+online+(no+judgment)
https://clouthaus.com/search=How+much+would+it+cost+to+hire+Afomiya+for+a+fake+birthday+party?
Cheat Sheet
-
whereshows results based on satisfied conditions to extract the relevant logs from noise. -
nameis the field that the query is interested in, do please note that it is case-sensitive. -
containssearches for strings containing the provided characters, for example if the keyword is “afomiya”, then the records may include afomiya123 or xyzafomiya. -
==is the equal operator, which must match every character of the provided string. -
orunites two conditions, if one of them are satisfied, then it returns the matched row. -
distinctserves to display just one entry for each match, for example if there are three rows with the same domain, then the results will show that domain once. -
hashunts for a complete case-insensitive string, for example best friend has friend or fRiEnD. -
letcreates a variable, like an expression or a function, great for reusing along the query. -
dynamicsets up a flexible data type going from key-value structures to a list of elements. -
;do not skip it, as it closes the sentence to proceed with the next instruction. -
has_anyis the evolution of has, compares with a predefined array of values. -
searchlooks for any match no matter the case sensitiveness nor the fields, then it’s costly. -
has_allrequires that every keyword in the provided list be present in the target field. -
andcombines two conditions which both must be true, in order to return the matched row.