fix(security): Implement Phase 1 critical security fixes

CORS:
- Restrict CORS to DASHBOARD_URL environment variable
- Default to production dashboard domain

Authentication:
- Add AuthUser requirement to all agent management endpoints
- Add AuthUser requirement to all command endpoints
- Add AuthUser requirement to all metrics endpoints
- Add audit logging for command execution (user_id tracked)

Agent Security:
- Replace Unicode characters with ASCII markers [OK]/[ERROR]/[WARNING]
- Add certificate pinning for update downloads (allowlist domains)
- Fix insecure temp file creation (use /var/run/gururmm with 0700 perms)
- Fix rollback script backgrounding (use setsid instead of literal &)

Dashboard Security:
- Move token storage from localStorage to sessionStorage
- Add proper TypeScript types (remove 'any' from error handlers)
- Centralize token management functions

Legacy Agent:
- Add -AllowInsecureTLS parameter (opt-in required)
- Add Windows Event Log audit trail when insecure mode used
- Update documentation with security warnings

Closes: Phase 1 items in issue #1

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-20 21:16:24 -07:00
parent 6d3271c144
commit 65086f4407
15 changed files with 1708 additions and 99 deletions

View File

@@ -1,19 +1,56 @@
#Requires -Version 2.0
<#
.SYNOPSIS
GuruRMM Legacy Agent - PowerShell-based agent for Windows Server 2008 R2 and older systems
GuruRMM Legacy Agent for Windows Server 2008 R2 and older systems.
.DESCRIPTION
Lightweight RMM agent that:
- Registers with GuruRMM server using site code
- Reports system information
- Executes remote scripts/commands
- Monitors system health
This PowerShell-based agent is designed for legacy Windows systems that cannot
run the modern Rust-based GuruRMM agent. It provides basic RMM functionality
including registration, heartbeat, system info collection, and remote command
execution.
IMPORTANT: This agent is intended for legacy systems only. For Windows 10/
Server 2016 and newer, use the native Rust agent instead.
.PARAMETER ConfigPath
Path to the agent configuration file. Default: $env:ProgramData\GuruRMM\agent.json
.PARAMETER ServerUrl
The URL of the GuruRMM server (e.g., https://rmm.example.com)
.PARAMETER SiteCode
The site code for agent registration (e.g., ACME-CORP-1234)
.PARAMETER AllowInsecureTLS
[SECURITY RISK] Disables SSL/TLS certificate validation. Required ONLY for
systems with self-signed certificates or broken certificate chains.
WARNING: This flag makes the connection vulnerable to man-in-the-middle
attacks. Only use on isolated networks or when absolutely necessary.
This flag must be explicitly provided - certificate validation is enabled
by default.
.PARAMETER Register
Register this agent with the server.
.EXAMPLE
# Secure installation (recommended)
.\GuruRMM-Agent.ps1 -Register -ServerUrl "https://rmm.example.com" -SiteCode "ACME-CORP-1234"
.EXAMPLE
# Insecure installation (legacy systems with self-signed certs ONLY)
.\GuruRMM-Agent.ps1 -Register -ServerUrl "https://rmm.example.com" -SiteCode "ACME-CORP-1234" -AllowInsecureTLS
.EXAMPLE
# Run the agent
.\GuruRMM-Agent.ps1
.NOTES
Compatible with PowerShell 2.0+ (Windows Server 2008 R2)
Version: 1.1.0
Requires: PowerShell 2.0+
Platforms: Windows Server 2008 R2, Windows 7, and newer
Author: GuruRMM
Version: 1.0.0
#>
param(
@@ -27,18 +64,23 @@ param(
[string]$SiteCode,
[Parameter()]
[string]$ServerUrl = "https://rmm-api.azcomputerguru.com"
[string]$ServerUrl = "https://rmm-api.azcomputerguru.com",
[Parameter()]
[switch]$AllowInsecureTLS
)
# ============================================================================
# Configuration
# ============================================================================
$script:Version = "1.0.0"
$script:Version = "1.1.0"
$script:AgentType = "powershell-legacy"
$script:ConfigDir = "$env:ProgramData\GuruRMM"
$script:LogFile = "$script:ConfigDir\agent.log"
$script:PollInterval = 60 # seconds
$script:AllowInsecureTLS = $AllowInsecureTLS
$script:TLSInitialized = $false
# ============================================================================
# Logging
@@ -67,6 +109,63 @@ function Write-Log {
} catch {}
}
# ============================================================================
# TLS Initialization
# ============================================================================
function Initialize-TLS {
if ($script:TLSInitialized) {
return
}
# Configure TLS - prefer TLS 1.2
try {
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
Write-Log "TLS 1.2 configured successfully" "INFO"
} catch {
Write-Log "TLS 1.2 not available, trying TLS 1.1" "WARN"
try {
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls11
} catch {
Write-Log "TLS 1.1 not available - using system default TLS" "WARN"
try {
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls
} catch {
Write-Log "TLS configuration failed - connection security may be limited" "WARN"
}
}
}
# Certificate validation - ONLY disable if explicitly requested
if ($script:AllowInsecureTLS) {
Write-Log "============================================" "WARN"
Write-Log "[SECURITY WARNING] Certificate validation DISABLED" "WARN"
Write-Log "This makes the connection vulnerable to MITM attacks" "WARN"
Write-Log "Only use on legacy systems with self-signed certificates" "WARN"
Write-Log "============================================" "WARN"
# Log to Windows Event Log for audit trail
try {
$source = "GuruRMM"
if (-not [System.Diagnostics.EventLog]::SourceExists($source)) {
New-EventLog -LogName Application -Source $source -ErrorAction SilentlyContinue
}
Write-EventLog -LogName Application -Source $source -EventId 1001 -EntryType Warning `
-Message "GuruRMM agent started with certificate validation disabled (-AllowInsecureTLS). This is a security risk."
} catch {
Write-Log "Could not write to Windows Event Log: $_" "WARN"
}
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
} else {
Write-Log "Certificate validation ENABLED (secure mode)" "INFO"
# Ensure callback is reset to default (validate certificates)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
}
$script:TLSInitialized = $true
}
# ============================================================================
# HTTP Functions (PS 2.0 compatible)
# ============================================================================
@@ -82,6 +181,9 @@ function Invoke-ApiRequest {
$url = "$($script:Config.ServerUrl)$Endpoint"
try {
# Initialize TLS settings (only runs once)
Initialize-TLS
# Use .NET WebClient for PS 2.0 compatibility
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("Content-Type", "application/json")
@@ -91,17 +193,6 @@ function Invoke-ApiRequest {
$webClient.Headers.Add("Authorization", "Bearer $ApiKey")
}
# Handle TLS (important for older systems)
try {
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
} catch {
# Fallback for systems without TLS 1.2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls
}
# Ignore certificate errors for self-signed certs (optional)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
if ($Method -eq "GET") {
$response = $webClient.DownloadString($url)
} else {

View File

@@ -15,8 +15,20 @@
.PARAMETER ServerUrl
The GuruRMM server URL (default: https://rmm-api.azcomputerguru.com)
.PARAMETER AllowInsecureTLS
[SECURITY RISK] Disables SSL/TLS certificate validation. Required ONLY for
systems with self-signed certificates or broken certificate chains.
WARNING: This flag makes the connection vulnerable to man-in-the-middle
attacks. Only use on isolated networks or when absolutely necessary.
.EXAMPLE
# Secure installation (recommended)
.\Install-GuruRMM.ps1 -SiteCode DARK-GROVE-7839
.EXAMPLE
# Insecure installation (legacy systems with self-signed certs ONLY)
.\Install-GuruRMM.ps1 -SiteCode DARK-GROVE-7839 -AllowInsecureTLS
#>
param(
@@ -24,7 +36,10 @@ param(
[string]$SiteCode,
[Parameter()]
[string]$ServerUrl = "https://rmm-api.azcomputerguru.com"
[string]$ServerUrl = "https://rmm-api.azcomputerguru.com",
[Parameter()]
[switch]$AllowInsecureTLS
)
$ErrorActionPreference = "Stop"
@@ -112,8 +127,15 @@ try {
# Step 3: Register agent
Write-Status "Registering with GuruRMM server..."
if ($AllowInsecureTLS) {
Write-Status "[SECURITY WARNING] Installing with certificate validation DISABLED" "WARN"
Write-Status "This makes the connection vulnerable to MITM attacks" "WARN"
}
try {
$registerArgs = "-ExecutionPolicy Bypass -File `"$destScript`" -SiteCode `"$SiteCode`" -ServerUrl `"$ServerUrl`""
if ($AllowInsecureTLS) {
$registerArgs += " -AllowInsecureTLS"
}
$process = Start-Process powershell.exe -ArgumentList $registerArgs -Wait -PassThru -NoNewWindow
if ($process.ExitCode -ne 0) {
@@ -137,13 +159,19 @@ try {
# Step 5: Create scheduled task
try {
# Create the task to run at startup and every 5 minutes
# Create the task to run at startup
$taskCommand = "powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$destScript`""
if ($AllowInsecureTLS) {
$taskCommand += " -AllowInsecureTLS"
}
# Create task that runs at system startup
schtasks /create /tn $TaskName /tr $taskCommand /sc onstart /ru SYSTEM /rl HIGHEST /f | Out-Null
Write-Status "Scheduled task created: $TaskName" "OK"
if ($AllowInsecureTLS) {
Write-Status "Task configured with -AllowInsecureTLS flag" "WARN"
}
} catch {
Write-Status "Failed to create scheduled task: $($_.Exception.Message)" "ERROR"
Write-Status "You may need to manually create the task" "WARN"