SOC Prime Bias: High

30 Jun 2026 06:21 UTC

Abusing GitLab CI Runners as a Command-and-Control Framework

Author Photo
SOC Prime Team linkedin icon Follow
Abusing GitLab CI Runners as a Command-and-Control Framework
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Summary

The article describes a proof of concept named GitRunner C2 that turns legitimate, digitally signed GitLab CI runner binaries into a command-and-control framework. By installing the runners as Windows services, an attacker can run arbitrary PowerShell commands and exfiltrate data through GitLab’s built-in infrastructure. Because the traffic uses outbound HTTPS to gitlab.com, the activity can blend in with normal developer communications.

Investigation

The researcher demonstrated the complete attack chain, starting with enrollment through an elevated PowerShell one-liner and ending with interactive command execution. The investigation relied on Sysmon and PowerShell Operational logs to record process creation, registry changes, and executed commands through Script Block Logging. The study showed that the runner’s legitimate behavior can help evade traditional EDR and network-based detection.

Mitigation

Defenders should watch for newly installed Windows services with unusual names or services launched from non-standard file paths. Enabling PowerShell Script Block Logging is essential for visibility into commands executed through the runner. Organizations should also limit who can install services and monitor for suspicious outbound HTTPS traffic to GitLab from endpoints that are not used for development work.

Response

If this activity is detected, isolate the affected endpoint immediately to stop further command-and-control communication. Revoke any GitLab Personal Access Tokens and runner registration tokens tied to the compromised environment. Investigators should then review PowerShell logs and Windows Event Logs to determine the scope of executed commands and any resulting data exfiltration.

"flowchart TD step_ingress["T1105 u2013 Ingress Tool Transfer: Download of legitimate gitlab-runner-windows-amd64.exe via PowerShell from S3"] step_persistence["T1543.003 u2013 Create or Modify System Process: Windows Service: Installing GitLab runner as a native Windows service for persistence"] rules_for_persistence("<b>Rule Name</b>: Suspicious Service Binary Path (via system)<br/><b>Rule ID</b>: 780e6396-d9f4-42b2-8d73-89918e2dab16") step_trust_subversion["T1553.002 u2013 Subvert Trust Controls: Code Signing: Using the digitally signed GitLab binary to evade detection"] step_execution["T1059.003 u2013 Command and Scripting Interpreter: Windows Command Shell: Executing command payloads via CI variables using shell executor"] step_c2["T1071 u2013 Application Layer Protocol: Using HTTPS (port 443) to GitLab infrastructure as a C2 relay"] step_exfiltration["T1567.001 u2013 Exfiltration Over Web Service: Exfiltration to Code Repository: Moving files via GitLab Artifacts and Generic Package Registry"] step_ingress –>|leads_to| step_persistence step_persistence –>|enables| step_trust_subversion step_persistence -.->|detected_by| rules_for_persistence step_trust_subversion –>|then| step_execution step_execution –>|uses| step_c2 step_c2 –>|leads_to| step_exfiltration "

Attack Flow

Simulation Execution

Prerequisite: The Telemetry & Baseline Pre-flight Check must have passed.

Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative MUST directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic. Abstract or unrelated examples will lead to misdiagnosis.

  • Attack Narrative & Commands: An adversary has gained initial access and intends to establish a persistent Command and Control (C2) channel. Instead of using known malware, they download the legitimate gitlab-runner-windows-amd64.exe to blend in with DevOps activity. They use PowerShell to drop the file into a temporary directory and then register it as a Windows Service named “gitlab-runner”. This method aims to exploit the trusted nature of CI/CD tools to bypass traditional security scrutiny.

  • Regression Test Script:

    # Simulation of GitLab Runner Installation for Detection Validation
    $ErrorActionPreference = "Stop"
    
    # 1. Define paths and names to match the detection logic exactly
    $TargetDir = "C:WindowsTemp"
    $BinaryName = "gitlab-runner-windows-amd64.exe"
    $BinaryPath = Join-Path $TargetDir $BinaryName
    $ServiceName = "gitlab-runner"
    
    Write-Host "[+] Starting Simulation: Installing $BinaryName"
    
    # 2. Simulate File Creation (Sysmon Event ID 11)
    # In a real attack, this would be a web download. Here we create a dummy file with the specific name.
    New-Item -Path $BinaryPath -ItemType File -Force | Out-Null
    Write-Host "[+] Created file: $BinaryPath (Triggers Event ID 11)"
    
    # 3. Simulate Registry Service Installation (Sysmon Event ID 13)
    # Creating the service path in the registry to trigger the ImagePath detection.
    $RegPath = "HKLM:SYSTEMCurrentControlSetServices$ServiceName"
    New-Item -Path $RegPath -Force | Out-Null
    Set-ItemProperty -Path $RegPath -Name "ImagePath" -Value $BinaryPath
    Write-Host "[+] Created registry key and ImagePath: $RegPath (Triggers Event ID 13)"
    
    Write-Host "[+] Simulation Complete. Check SIEM for alerts."
  • Cleanup Commands:

    # Cleanup simulation artifacts
    $TargetDir = "C:WindowsTemp"
    $BinaryName = "gitlab-runner-windows-amd64.exe"
    $BinaryPath = Join-Path $TargetDir $BinaryName
    $ServiceName = "gitlab-runner"
    
    Remove-Item -Path $BinaryPath -Force -ErrorAction SilentlyContinue
    Remove-Item -Path "HKLM:SYSTEMCurrentControlSetServices$ServiceName" -Recurse -Force -ErrorAction SilentlyContinue
    Write-Host "[+] Cleanup complete."