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.

Shinyhunters Vishing to Salesforce Access Flow

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: 

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.

Salesloft Drift Compromise and Abuse Flow

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. 

IP Address User-Agent String
44.215.108.109 Salesforce-Multi-Org-Fetcher/1.0
154.41.95.2 Salesforce-CLI/1.0
176.65.149.100 python-requests/2.32.4
179.43.159.198 Python/3.11 aiohttp/3.12.15
185.130.47.58
185.207.107.130
185.220.101.33
185.220.101.133
185.220.101.143
185.220.101.164
185.220.101.167
185.220.101.169
185.220.101.180
185.220.101.185
192.42.116.20
192.42.116.179
194.15.36.117
195.47.238.83
195.47.238.178
208.68.36.90

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.

LAST UPDATED:

September 29, 2025

Don't miss these stories:

Inside Mitiga’s Forensic Data Lake: Built for Real-World Cloud Investigations

Most security tools weren’t designed for the scale or complexity of cloud investigations. Mitiga’s Forensic Data Lake was.

Breaking Down the Microsoft Entra ID Actor Token Vulnerability: The Perfect Crime in the Cloud

When we think about catastrophic vulnerabilities in the cloud, we usually imagine complex exploits that require advanced techniques, persistence, or luck. Sometimes a single flaw breaks the trust we put in our identity providers.

Invisible Threats: Wireless Exploits in the Enterprise with Brett Walkenhorst

In this episode of Mitiga Mic, Field CISO Brian Contos talks with Brett Walkenhorst, CTO of Bastille, about how wireless attack techniques like Evil Twin and Nearest Neighbor are used to gain access to protected environments. They discuss how these threats show up inside data halls, executive spaces, and high-security facilities, often bypassing traditional network defenses

From Rogue OAuth App to Cloud Infrastructure Takeover

How a rogue OAuth app led to a full AWS environment takeover. And the key steps security leaders can take to prevent similar cloud breaches.

CORSLeak: Abusing IAP for Stealthy Data Exfiltration

When people talk about “highly restricted” cloud environments, they usually mean environments with no public IPs, no outbound internet, and strict VPC Service Controls locking everything down.

Defending SaaS & Cloud Workflows: Supply Chain Security Insights with Idan Cohen

From GitHub Actions to SaaS platforms, supply chain threats are growing. Hear Mitiga’s Idan Cohen and Field CISO Brian Contos explore real-world compromises, detection tips, and strategies to strengthen your cloud security.