The Big Question: Avoid Becoming The Next Salesloft
Mitiga Labs began investigating a series of suspicious activities targeting Salesforce environments well before the news broke publicly. It all started with traffic from Tor exit nodes interacting with Salesforce via an app called Drift. Is this normal behavior? What is Drift? And how do we assess its legitimacy? This is where the challenge of shadow IT surfaces – security operations teams are often left scrambling to determine whether such activity is authorized or a sign of compromise.
As we now know, Salesforce data was exfiltrated.
In this post, we’ll dive into the technical details of multiple campaigns currently targeting Salesforce. We’ll explore detection strategies, share insights from Mitiga’s investigations, and discuss how you can avoid becoming the next Salesloft.
Background: Two Campaigns Targeting Salesforce
It is crucial to first understand that, currently, there are two different groups with different campaigns. Each campaign is derived from a different sort of compromise.
Let’s break it down.
ShinyHunters (UNC6040): OAuth Abuse Meets VISHING
A financially motivated extortion group first observed in early 2020, ShinyHunters has recently pivoted toward cloud platform exploitation. Their campaign targeting Salesforce environments over the summer of 2025, using a blend of OAuth abuse and vishing
Attack Flow Summary:
- The attacker configures OAuth Device Flow via a local Salesforce Data Loader, generating an 8-character code.
- The Data Loader listens for successful authentication tied to that code.
- A vishing call is made to an English-speaking employee, impersonating IT support.
- The victim is tricked into visiting Salesforce's verification page and entering the code.
- Upon login and approval, an access token is issued to the attacker's Data Loader instance.
- All subsequent actions are performed on behalf of the victim, enabling silent, slow data exfiltration of small chunks of data at a time.
No public leaks have been confirmed yet, but ransom demands reportedly range from 4 to 20 BTC, with a 3 to 4-day deadline
Salesforce Data Loader is a legitimate client application used for bulk data operations, making it an ideal disguise for attackers.

UNC6395 AND THE DRIFT SUPPLY CHAIN COMPROMISE
The threat actors began their activity in early August 2025, with evidence of data exfiltration starting on August 12, 2025. Their motives remain unknown. While some have noted the group's overlap with ShinyHunters’ focus on Salesforce, no confirmed relationship between UNC6395 and ShinyHunters has been established.
Attack Flow Summary:
- Threat actors gained access to Salesloft Drift customer environments after a compromise allowed them to leverage stolen OAuth tokens.
- Drift’s application had a dedicated user, and threat actors leveraged that for exfiltration, without any attempt at hiding it.
- Indicators surfaced from the internet, with Tor exit nodes performing GET requests at an abnormal high volume.
- The high volume spiraled out of control very quickly, eventually impacting the supply chain, due to the fact that Drift was connected to Salesforce, which is hosted by many large organizations.
- Drift was also connected to Google Workspace and Outlook, although, as of this writing, no evidence of the attacker’s footprint appears anywhere near these platforms.
- Attackers were reported to have gained control of leading technology companies such as:
- CloudFlare
- Tenable
- Palo Alto
- Zscaler
- Many more…
How did Salesloft get breached?
Based on Mandiant’s investigation efforts on this incident – between March and June 2025, the threat actor gained access to the Salesloft GitHub account, which was followed by multiple download events of repository content, as well as the addition of a guest user and workflows were seen established.
The report also mentions observing reconnaissance activities throughout the mentioned period, with claims that the investigation did not yield evidence of a deeper compromise other than the mentioned reconnaissance within the core of the Salesloft application.
The threat actor leveraged the existing access to pivot to Drift’s AWS environment and began stealing OAuth tokens for Drift customers’ integrations.

Detection Approach
Following our recent incident response assessments, we conducted a deep analysis of the adversary campaigns and their behavioral patterns. These investigations revealed nuanced tactics, techniques, and procedures (TTPs) that were not immediately evident through traditional signature-based detection.
To address these gaps, we developed a series of behavioral detections using PySpark, enabling scalable and efficient analysis across large volumes of telemetry data. These detections are designed to surface anomalous activity indicative of the attack lifecycle - from initial access to lateral movement and data exfiltration.
Note: It is critical to understand the structure and semantics of your infrastructure logs – especially those from platforms GitHub, AWS, and Salesforce. Each of these sources has unique logging formats, event types, and contextual nuances that must be interpreted correctly to ensure accurate detection and minimize false positives.
The following detection logic reflects real-world attacker behavior observed during our investigations and can be adapted to your environment to enhance visibility and response capabilities.
Reconnaissance: GitHub secrets publicly leaked
filtered_df = (
raw_github_auditlogs_df.filter(col("action") == secret_scanning_alert.public_leak)
.withColumn(COL_SECRET_NAME, get_json_object("json", "$.secret_type_display_name"))
)
Indicating GitHub Secrets Leakage attributed to Salesloft compromise
Using GitHub Audit Logs, filtering the action equals to secret_scanning_alert.public_leak, will yield results on GitHub secrets publicly leaked. This would allow preventing the incident and catching the leaked secret before exposed.
Initial Access: AWS Anomalous usage of access key
filtered_df = cloudtrail_df \
.filter(
(col("event_name") == "GetCallerIdentity") &
(col("src_useragent") == "TruffleHog")
) \
.filter(col("error_code") == "") \
.withColumn(COL_ACCESS_KEY, col('accessKeyId'))
filtered_df.display()
Indicating AWS Access Key Anomalous Usage attributed to Salesloft compromise
Using CloudTrail logs, filtering TruffleHog user agent, successfully performing GetCallerIdentity. This indicates TruffleHog was used to validate an access key – following Salesloft Drift breach, a secret was validated.
Persistence: Github new member addition
filtered_df = github_auditlogs_df \
.filter(col("action") == user) \
.withColumn(COL_TEAM, get_json_object("json", "$.team"))
Indicating GitHub New Member Addition to a group, attributed to Salesloft compromise
Using GitHub Audit Logs, filtering user additions and enriching the JSON column to include the team as a separate column. This helps us assess whether an unwanted visitor is persisting in our GitHub environment.
Exfiltration: Salesforce slow exfiltration
SF_MIN_SCHEMA = StructType([
StructField("METHOD", StringType()),
StructField("STATUS_CODE", StringType()),
StructField("RESPONSE_SIZE", StringType()),
StructField("ENTITY_NAME", StringType()),
StructField("URI", StringType()),
]) # this requires a thorough understanding of the Salesforce schema.
def detect_sf_data_exfiltration(raw_salesforce_df, min_size=1200000, max_size=6400000, time_window="600 seconds", req_threshold=30):
df = raw_salesforce_df.withColumn("sf_parsed", from_json(col("json"), SF_MIN_SCHEMA)) \
.withColumn("method", col("sf_parsed.METHOD")) \
.withColumn("status", col("sf_parsed.STATUS_CODE")) \
.withColumn("size", col("sf_parsed.RESPONSE_SIZE").cast("long")) \
.withColumn("entity", col("sf_parsed.ENTITY_NAME")) \
.withColumn("uri", col("sf_parsed.URI"))
filtered_df = df.filter(
(col("EVENT_TYPE") == "RestApi") &
(col("method") == "GET") &
(col("status") == "200") &
(col("size").between(min_size, max_size)) &
col("uri").rlike(r"^/services/data/v\d+\.\d+/query$")
)
windowed_df = filtered_df.withColumn("time_window", window(col("TIMESTAMP_DERIVED"), time_window))
aggregated_df = windowed_df.groupBy("user_id", "entity", "time_window") \
.count() \
.filter(col("count") >= req_threshold)
return windowed_df.join(aggregated_df, ["user_id", "entity", "time_window"]) \
.withColumn("row_num", row_number().over(Window.partitionBy("user_id", "entity", "time_window").orderBy("TIMESTAMP_DERIVED"))) \
.filter(col("row_num") == 1) \
.drop("row_num", "time_window")
Salesforce Slow Exfiltration Technique attributed to ShinyHunters infiltration.
An advanced Salesforce hunting logic, using Salesforce event logs files (ELFs) and filtering the illustration of a slow exfiltration, based on ShinyHunters behavior, according to our continuous Incident Response efforts. This filtering requires a thorough understanding of Salesforce logs and logic. Consider using the documentation to align the detection to your environment.
Collection: Github repository downloaded as a zip
raw_repo = raw_github_auditlogs_df.where(col("action") == repo.download_zip)
repo_agg = raw_repo.where(get_json_object("json", "$.actor_is_bot") == "false") \
.groupBy("date", "actor", "actor_ip") \
.agg(
collect_set("repo").alias("repos"),
count_distinct("repo").alias("repo_count")
)
final_df = repo_agg.join(raw_repo, on=["date", "actor", "actor_ip"])
A repository downloaded as a ZIP from GitHub, attributed to Salesloft compromise.
Using GitHub audit logs, we are able to filter repo.download_zip to detect downloads of repositories as archive file. The detection logic includes noise filtering.
DISCLAIMER: It is highly recommended to use an anomaly engine to filter out false positive rates and increase the fidelity of the detections.
Indicators of Compromise
We highly recommend implementing all of the indicators of compromise to trigger detections in your SIEM or Detection Response solutions.
BUILDING CLOUD BREACH READINESS: LESSONS FROM SALESLOFT AND SALESFORCE ATTACKS
Let’s be real. A breach is inevitable. The real question is: how ready are you? It all comes down to your detection coverage, how well your incident response team is organized, and most importantly, what logs you have access to.
In the Drift case, customers weren’t careless. The attackers didn’t hack their way in. They logged in, pretending to be a trusted third-party service. That kind of stealth move caused major chaos. And while attackers are getting smarter and expanding their tactics, many organizations still think keeping logs for just one day is enough to investigate a data breach. Spoiler: it’s not.
This kind of short retention leads to panic when trying to figure out what secrets were stolen, what credentials need to be rotated, and what systems might need to be shut down entirely. If you don’t have the logs, you’re flying blind.
START YOUR SALESFORCE THREAT HUNT
Let’s team up. Request a demo and you could run a free Salesforce threat hunt with Mitiga. Our team will also monitor your Salesforce environment with our detection rules for 30 days and alert you to anomalies. Request a demo, or head to the form on this page and get started.
Not ready to dive in? Watch Mitiga CTO and Co-founder Ofer Maor in this special webcast. Ofer takes you inside the Salesforce breach campaign, including activity linked to UNC6395 and UNC6040, to uncover practical steps to start hunting and detecting these campaigns today.