GRIDTIDE: Detecting Google Sheets C2 in a Global Espionage Campaign
A sophisticated espionage operation has compromised dozens of telecommunications providers and government organizations across 42 countries on four continents. The campaign, run by a suspected Chinese government-backed group tracked since 2017, used a custom-built hidden access tool to maintain persistent control over networks that handle sensitive personal data and communications systems.
Think of it like a spy who gets a job at the post office. Instead of breaking in to read letters, they blend in with the regular mail carriers, using the same trucks and delivery routes to move stolen information undetected. This group hid their secret communications inside a popular cloud spreadsheet service, making their activity look identical to normal business operations and nearly impossible to spot with standard security tools.
Organizations compromised in this campaign faced exposure of personal records including names, phone numbers, birth dates, and government identification numbers. Access to telecommunications networks enabled call interception, message monitoring, and surveillance of targeted individuals. Google terminated the group's access points in February 2026, but security researchers expect the operators to rebuild their capabilities using alternative platforms.
Hunting Controls & Observations
Organizations can detect GRIDTIDE activity through multiple telemetry sources across endpoint, network, identity, and cloud domains:
- Endpoint Controls: Linux audit logs (auditd), Sysmon for Linux, file integrity monitoring for systemd service directories, process execution monitoring for binaries in staging paths (/var/tmp/)
- Network Controls: Web proxy logs (TLS inspection), DNS logs, network connection monitoring for non-browser HTTPS traffic to sheets.googleapis.com, SoftEther VPN protocol detection
- Identity & Access Controls: SSH authentication logs, service account activity monitoring, lateral movement detection across multiple hosts
- Cloud Controls: Google Workspace audit logs, Google Sheets API access monitoring, Google Cloud Project creation auditing
Behavioral Indicators of Attack
The following behavioral patterns characterize GRIDTIDE operations and distinguish them from legitimate activity:
- Systemd Service Persistence: Creation of unauthorized systemd service files at /etc/systemd/system/ that spawn binaries from staging directories such as /var/tmp/ or unexpected locations under /usr/sbin/
- Google Sheets API Abuse: Non-browser processes initiating HTTPS connections to sheets.googleapis.com:443, particularly those issuing batchClear, batchUpdate, or valueRenderOption=FORMULA API calls
- SSH Lateral Movement: Service accounts authenticating via SSH to multiple internal hosts in rapid succession, indicating network traversal beyond normal automation patterns
- SoftEther VPN Deployment: Presence of SoftEther VPN Bridge artifacts (hamcore.se2, vpn_bridge.config) on endpoints, indicating encrypted outbound tunneling infrastructure
- Binary Staging and Execution: Binaries downloaded to /var/tmp/ and executed via nohup to survive session termination, followed by privilege verification through shell commands such as id
- Anomalous User-Agent Strings: Server processes sending requests with user-agent strings matching "Google-HTTP-Java-Client/1.42.3 (gzip)" outside of expected application contexts
- Encrypted Configuration Files: AES-128 CBC encrypted configuration files (xapt.cfg) stored alongside unknown binaries, containing Google Service Account credentials and target spreadsheet identifiers
- Spreadsheet Data Wiping: Automated clearing of the first 1,000 rows across columns A through Z in Google Sheets documents via the batchClear API at process initialization, indicating operational evidence destruction
MITRE Enterprise ATT&CK Tactics and Techniques
MITRE ATT&CK framework mapping for the GRIDTIDE/UNC2814 campaign, sorted by kill chain progression:
- Initial Access: T1190 - Exploit Public-Facing Application: UNC2814 targets web servers and edge devices to gain initial network entry into telecommunications and government environments.
- Execution: T1059.004 - Command and Scripting Interpreter: Unix Shell: GRIDTIDE executes Base64-encoded shell commands received through the C2 channel, including privilege verification via
sh -c id 2>&1. - Persistence: T1543.002 - Create or Modify System Process: Systemd Service: GRIDTIDE registers as a systemd service (xapt.service) to maintain persistence across system reboots, spawning from /usr/sbin/xapt.
- Defense Evasion: T1140 - Deobfuscate/Decode Files or Information: Commands and data encoded using URL-safe Base64 to obscure content during transit through the Google Sheets API.
- Defense Evasion: T1036 - Masquerading: C2 traffic disguised as legitimate Google Sheets API calls, blending with normal cloud service usage patterns.
- Defense Evasion: T1070.004 - Indicator Removal: File Deletion: GRIDTIDE wipes the first 1,000 spreadsheet rows at initialization using the batchClear API to remove operational evidence.
- Defense Evasion: T1027 - Obfuscated Files or Information: Configuration data encrypted with AES-128 CBC using a separate 16-byte key file (xapt.cfg).
- Credential Access: T1078 - Valid Accounts: UNC2814 uses compromised service accounts for SSH-based lateral movement between hosts.
- Discovery: T1082 - System Information Discovery: GRIDTIDE posts a beacon containing username, hostname, operating system, IP address, timezone, and language to cell V1 of the C2 spreadsheet.
- Discovery: T1033 - System Owner/User Discovery: The beacon captures the current username of the compromised system for operator awareness.
- Lateral Movement: T1021.004 - Remote Services: SSH: UNC2814 uses service accounts and SSH to traverse victim networks laterally across internal hosts.
- Collection: T1005 - Data from Local System: UNC2814 targets systems containing personally identifiable information including names, phone numbers, birth dates, and government identification numbers.
- Command and Control: T1071.001 - Application Layer Protocol: Web Protocols: GRIDTIDE communicates via HTTPS to sheets.googleapis.com for command polling and data transfer.
- Command and Control: T1102.002 - Web Service: Bidirectional Communication: Google Sheets API serves as a bidirectional C2 channel with commands arriving in cell A1 and responses posted back to the spreadsheet.
- Command and Control: T1572 - Protocol Tunneling: SoftEther VPN Bridge creates encrypted outbound tunnels for additional C2 and exfiltration channels.
- Exfiltration: T1041 - Exfiltration Over C2 Channel: Files exfiltrated in 45-KB fragments through the Google Sheets API, posted as cell values in the C2 spreadsheet.
Controls' Observables
Endpoint Controls
- Unauthorized systemd service file creation in /etc/systemd/system/ that references binaries in /var/tmp/ or non-standard /usr/sbin/ paths (T1543.002) - Detection Difficulty: LOW
- Process execution from staging directory /var/tmp/xapt or persistence path /usr/sbin/xapt (T1036) - Detection Difficulty: LOW
- Shell spawning with privilege verification command:
sh -c id 2>&1(T1059.004) - Detection Difficulty: LOW - Nohup execution of unknown binaries to survive session termination (T1059.004) - Detection Difficulty: LOW
- SoftEther VPN Bridge artifacts: hamcore.se2 and vpn_bridge.config present on endpoints (T1572) - Detection Difficulty: LOW
- AES-128 encrypted configuration file (xapt.cfg) stored alongside unknown binaries (T1027) - Detection Difficulty: MEDIUM
Network Controls
- Non-browser HTTPS connections to sheets.googleapis.com:443 originating from server processes (T1071.001, T1102.002) - Detection Difficulty: HIGH
- Google Sheets API batchClear and batchUpdate calls from automated or non-interactive processes (T1102.002) - Detection Difficulty: HIGH
- HTTP download from known attacker infrastructure: 130.94.6[.]228/update.tar.gz (T1190) - Detection Difficulty: LOW
- SoftEther VPN Bridge connections to known attacker IP addresses (e.g., 38.60.194[.]21) (T1572) - Detection Difficulty: MEDIUM
- User-agent string "Google-HTTP-Java-Client/1.42.3 (gzip)" from non-browser or non-standard application processes (T1071.001) - Detection Difficulty: MEDIUM
Identity & Access Controls
- Service account SSH sessions to multiple internal hosts within short timeframes indicating lateral traversal (T1021.004, T1078) - Detection Difficulty: MEDIUM
- Unauthorized creation or modification of service accounts used for system-to-system authentication (T1078) - Detection Difficulty: MEDIUM
Cloud Controls
- Google Cloud Projects created by unauthorized or unrecognized accounts (T1102.002) - Detection Difficulty: MEDIUM
- Google Sheets API access from unexpected service accounts or outside normal business workflows (T1102.002) - Detection Difficulty: HIGH
- Anomalous spreadsheet usage patterns including frequent cell clears and rapid automated reads/writes (T1070.004) - Detection Difficulty: HIGH
Insights and Recommendation
A successful GRIDTIDE compromise grants persistent, covert access to telecommunications infrastructure and government networks. This access enables surveillance of targeted individuals through call interception, message monitoring, and collection of personal identification records. The use of legitimate cloud services for command and control makes detection through standard network monitoring extremely difficult, allowing long-term undetected presence that persisted for years across dozens of victim organizations.
Organizations should implement application-level monitoring for Google Sheets API calls originating from server processes or non-browser user agents, flagging batchClear and batchUpdate operations from automated sources. Security teams should audit Linux systemd services for unauthorized entries that spawn binaries from staging directories like /var/tmp/, review service account SSH activity for lateral movement patterns across multiple hosts, and deploy file integrity monitoring on /etc/systemd/system/ to detect new service registration. Telecommunications providers and government entities should treat this as a high-priority hunt given UNC2814's documented focus on these sectors.
Source and Credits
This summary is based on research published by Google Threat Intelligence Group (GTIG) and Mandiant, titled "Exposing the Undercurrent: Disrupting the GRIDTIDE Global Cyber Espionage Campaign," published on February 25, 2026. Additional technical details referenced from reporting by The Hacker News and The Record. IOC data sourced from the AlienVault OTX pulse published by GTIG.
Threat Hunting IOCs & Queries
This section contains Indicators of Compromise and threat hunting queries for detecting GRIDTIDE activity and UNC2814 tradecraft in your environment.
Known Indicators of Compromise
- File Hashes (SHA256):
ce36a5fc44cbd7de947130b67be9e732a7b4086fb1df98a5afd724087c973b47(GRIDTIDE backdoor binary: xapt)01fc3bd5a78cd59255a867ffb3dfdd6e0b7713ee90098ea96cc01c640c6495eb(Key file: xapt.cfg)eb08c840f4c95e2fa5eff05e5f922f86c766f5368a63476f046b2b9dbffc2033(Persistence: xapt.service)4eb994b816a1a24cf97bfd7551d00fe14b810859170dbf15180d39e05cd7c0f9d25024ccea8eac85a9522289cfb709f2ed4e20176dd37855bacc2cd75c995606669917bad46a57e5f2de037f8ec200a44fb579d723af3e2f1be1e8479a267966
- IP Addresses:
130.94.6[.]228(GRIDTIDE download server)38.54.82[.]6938.60.224[.]25195.123.211[.]7038.180.205[.]1438.60.194[.]21(SoftEther VPN server)
- URLs:
http://130.94.6[.]228/update.tar.gz - File Paths:
/var/tmp/xapt(staging location)/usr/sbin/xapt(persistence location)/etc/systemd/system/xapt.service(systemd persistence)hamcore.se2(SoftEther VPN artifact)vpn_bridge.config(SoftEther VPN configuration)
- Dynamic DNS Domains (C2): 100+ domains using providers including kozow[.]com, ddnsfree[.]com, accesscam[.]org, and loseyourip[.]com subdomains. Full list available in the GTIG AlienVault OTX pulse.
- User-Agent Strings:
Google-HTTP-Java-Client/1.42.3 (gzip)Directory API Google-API-Java-Client/2.0.0 Google-HTTP-Java-Client/1.42.3 (gzip)
Note: IOCs rotate frequently. Behavioral detection queries below provide more durable detection coverage than static IOC matching.
Query 1: Unauthorized Systemd Service Persistence
Query Details
- Behavior Targeted: Detection of new systemd service files that execute binaries from staging directories (/var/tmp/) or known GRIDTIDE paths (/usr/sbin/xapt). UNC2814 establishes persistence by creating a systemd service that auto-starts the GRIDTIDE backdoor on boot.
- MITRE ATT&CK: T1543.002 - Create or Modify System Process: Systemd Service
- Expected Results: New or modified systemd service files that reference binaries in temporary or unusual directories. Legitimate services typically execute from /usr/bin/ or /opt/.
- False Positive Likelihood: LOW - Custom systemd services spawning from /var/tmp/ are rare in production environments.
- Tuning Guidance: Establish a baseline of authorized systemd services. Exclude known package-managed services. Adjust path filters to match your organization's software deployment patterns.
- Telemetry Requirements: Linux syslog (journald or rsyslog), Sysmon for Linux, or file integrity monitoring data.
- Detection Difficulty: EASY
Splunk SPL
index=linux sourcetype="syslog" earliest=-7d
("systemctl enable" OR "systemctl start" OR "systemctl daemon-reload"
OR "Created symlink")
| search ("/etc/systemd/system/" OR "xapt")
| rex field=_raw "(?<service_name>[\w\-]+\.service)"
| eval risk=case(
match(_raw, "xapt"), "CRITICAL - Known GRIDTIDE indicator",
match(_raw, "/var/tmp/"), "HIGH - Staging directory execution",
match(_raw, "/tmp/"), "HIGH - Temp directory execution",
match(_raw, "/dev/shm/"), "HIGH - Shared memory execution",
1=1, "LOW - Review against baseline"
)
| where risk!="LOW - Review against baseline"
| stats count earliest(_time) as first_seen latest(_time) as last_seen
values(host) as affected_hosts by service_name risk
| sort -risk
Microsoft KQL (Sentinel)
Syslog
| where TimeGenerated > ago(7d)
| where SyslogMessage has_any ("systemctl enable", "systemctl start",
"Created symlink", "daemon-reload")
or SyslogMessage has "xapt"
| extend ServiceName = extract(@"([\w\-]+\.service)", 1, SyslogMessage)
| extend Risk = case(
SyslogMessage has "xapt", "CRITICAL - Known GRIDTIDE",
SyslogMessage has "/var/tmp/", "HIGH - Staging directory",
SyslogMessage has "/tmp/", "HIGH - Temp directory",
SyslogMessage has "/dev/shm/", "HIGH - Shared memory",
"LOW - Review"
)
| where Risk != "LOW - Review"
| summarize Count = count(), FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated), Hosts = make_set(HostName)
by ServiceName, Risk
| sort by Risk desc
Query 2: Non-Browser Google Sheets API Access (C2 Detection)
Query Details
- Behavior Targeted: GRIDTIDE communicates with its C2 infrastructure through the Google Sheets API, sending HTTPS requests to sheets.googleapis.com from non-browser processes. Detecting these connections identifies potential C2 activity hidden in legitimate cloud traffic.
- MITRE ATT&CK: T1071.001 - Application Layer Protocol: Web Protocols, T1102.002 - Web Service: Bidirectional Communication
- Expected Results: Server processes or command-line tools connecting to sheets.googleapis.com. Legitimate traffic originates from browsers or authorized automation tools.
- False Positive Likelihood: MEDIUM - Some organizations use Google Sheets API for legitimate automation. Investigate process names and usage patterns.
- Tuning Guidance: Whitelist known automation services that legitimately use the Google Sheets API. Focus on Linux servers and processes without a GUI context. Alert on batchClear/batchUpdate patterns from unusual sources.
- Telemetry Requirements: Web proxy logs (with TLS inspection), DNS query logs, endpoint network telemetry.
- Detection Difficulty: HARD
Splunk SPL
index=network sourcetype="squid" OR sourcetype="bluecoat:proxysg:access:syslog"
OR sourcetype="zscaler" earliest=-7d
("sheets.googleapis.com" OR "googleapis.com/v4/spreadsheets")
| eval suspicious_ua=if(
match(cs_user_agent, "Google-HTTP-Java-Client|Java|Python|curl|wget")
AND NOT match(cs_user_agent, "Chrome|Firefox|Safari|Edge"), 1, 0)
| eval api_action=case(
match(url, "batchClear"), "CLEAR_CELLS",
match(url, "batchUpdate"), "UPDATE_CELLS",
match(url, "valueRenderOption"), "READ_CELLS",
1=1, "OTHER"
)
| where suspicious_ua=1
| stats count dc(url) as unique_urls values(api_action) as actions
earliest(_time) as first_seen latest(_time) as last_seen
by src_ip cs_user_agent
| where count > 10
| sort -count
Microsoft KQL (Defender for Endpoint)
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where RemoteUrl has "sheets.googleapis.com"
or RemoteUrl has "googleapis.com/v4/spreadsheets"
| extend ProcessName = tostring(split(InitiatingProcessFileName, "\\")[-1])
| where ProcessName !in ("chrome.exe", "firefox.exe", "msedge.exe",
"chrome", "firefox", "safari")
| extend ApiAction = case(
RemoteUrl has "batchClear", "CLEAR_CELLS",
RemoteUrl has "batchUpdate", "UPDATE_CELLS",
RemoteUrl has "valueRenderOption", "READ_CELLS",
"OTHER"
)
| summarize ConnectionCount = count(),
UniqueActions = make_set(ApiAction),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by DeviceName, ProcessName, InitiatingProcessCommandLine
| where ConnectionCount > 10
| sort by ConnectionCount desc
Query 3: SSH Lateral Movement via Service Accounts
Query Details
- Behavior Targeted: UNC2814 uses service accounts to move laterally via SSH across victim networks. Detecting service accounts authenticating to multiple internal hosts in short timeframes identifies potential lateral movement activity.
- MITRE ATT&CK: T1021.004 - Remote Services: SSH, T1078 - Valid Accounts
- Expected Results: Service accounts connecting to multiple hosts via SSH in short windows. Legitimate service accounts typically connect to a consistent set of systems.
- False Positive Likelihood: MEDIUM - Configuration management tools (Ansible, Puppet, Chef) use SSH with service accounts. Baseline normal patterns before deploying.
- Tuning Guidance: Establish a baseline of authorized SSH connections per service account. Alert on new destination hosts or unusually high connection counts. Exclude known automation tools by source IP or account name patterns.
- Telemetry Requirements: Linux auth logs (syslog), SSH daemon logs.
- Detection Difficulty: MODERATE
Splunk SPL
index=linux sourcetype="syslog" earliest=-7d
("Accepted publickey" OR "Accepted password") "ssh"
| rex field=_raw "Accepted\s+\w+\s+for\s+(?<ssh_user>\S+)\s+from\s+(?<src_ip>\S+)"
| where match(ssh_user, "^(svc_|service|daemon|sys_)")
| stats dc(host) as unique_destinations count
earliest(_time) as first_seen latest(_time) as last_seen
values(host) as target_hosts by ssh_user src_ip
| where unique_destinations > 3
| sort -unique_destinations
Microsoft KQL (Sentinel)
Syslog
| where TimeGenerated > ago(7d)
| where SyslogMessage has "Accepted" and SyslogMessage has "ssh"
| extend SSHUser = extract(@"Accepted\s+\w+\s+for\s+(\S+)\s+from", 1,
SyslogMessage)
| extend SourceIP = extract(@"from\s+(\d+\.\d+\.\d+\.\d+)", 1,
SyslogMessage)
| where SSHUser matches regex @"^(svc_|service|daemon|sys_)"
| summarize UniqueDestinations = dcount(HostName),
ConnectionCount = count(),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
TargetHosts = make_set(HostName)
by SSHUser, SourceIP
| where UniqueDestinations > 3
| sort by UniqueDestinations desc
Query 4: SoftEther VPN Bridge Detection
Query Details
- Behavior Targeted: UNC2814 deploys SoftEther VPN Bridge to create encrypted outbound tunnels from compromised environments. SoftEther VPN is a legitimate open-source tool frequently abused by threat actors for covert communications.
- MITRE ATT&CK: T1572 - Protocol Tunneling
- Expected Results: SoftEther VPN-related processes, configuration files, or network connections. SoftEther is rarely authorized in enterprise environments; any detection warrants investigation.
- False Positive Likelihood: LOW - SoftEther VPN Bridge is uncommon in most enterprise environments.
- Tuning Guidance: If SoftEther is authorized in your environment, filter by known installation paths and authorized accounts. Otherwise, treat any detection as suspicious.
- Telemetry Requirements: Endpoint process monitoring, file integrity monitoring, Sysmon for Linux or Windows.
- Detection Difficulty: EASY
Splunk SPL
index=linux OR index=windows sourcetype="syslog"
OR sourcetype="WinEventLog:Microsoft-Windows-Sysmon/Operational"
earliest=-7d
("vpnbridge" OR "vpn_bridge" OR "softether" OR "hamcore.se2"
OR "vpn_bridge.config" OR "SoftEtherVPN")
| eval artifact_type=case(
match(_raw, "hamcore\.se2"), "SOFTETHER_CORE_FILE",
match(_raw, "vpn_bridge\.config"), "SOFTETHER_CONFIG",
match(_raw, "vpnbridge|vpn_bridge"), "SOFTETHER_PROCESS",
1=1, "SOFTETHER_REFERENCE"
)
| stats count earliest(_time) as first_seen latest(_time) as last_seen
values(host) as affected_hosts by artifact_type
| sort -artifact_type
Microsoft KQL (Defender for Endpoint)
union DeviceProcessEvents, DeviceFileEvents
| where TimeGenerated > ago(7d)
| where FileName has_any ("vpnbridge", "vpn_bridge", "softether",
"hamcore.se2", "vpn_bridge.config")
or ProcessCommandLine has_any ("vpnbridge", "softether", "vpn_bridge")
or FolderPath has_any ("hamcore.se2", "vpn_bridge.config",
"SoftEtherVPN")
| extend ArtifactType = case(
FileName has "hamcore.se2", "SOFTETHER_CORE_FILE",
FileName has "vpn_bridge.config", "SOFTETHER_CONFIG",
FileName has_any ("vpnbridge", "vpn_bridge"), "SOFTETHER_PROCESS",
"SOFTETHER_REFERENCE"
)
| summarize Count = count(), FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated), Devices = make_set(DeviceName)
by ArtifactType, FileName, FolderPath
| sort by ArtifactType desc
These queries were generated with AI assistance. Test thoroughly in your environment before production use. Validate field names against your data model and adjust thresholds based on your baseline activity levels.
