Skip to content

Security

Ed Mozley edited this page Jun 4, 2026 · 11 revisions

Security

FreeITSM ships with several layers of defence covering authentication, sensitive-data storage, and brute-force resistance. This page is the security reference for evaluators and administrators.

Authentication

Analyst login

  • Username + password stored as bcrypt hashes in analysts.password_hash
  • Minimum password length: 8 characters (enforced on change and reset)
  • Default admin: admin / freeitsm β€” change this immediately on first login

Multi-Factor Authentication (TOTP)

  • Pure-PHP implementation of RFC 6238 (TOTP) and RFC 4226 (HOTP)
  • No external dependencies β€” uses PHP's hash_hmac() and random_bytes()
  • 6-digit codes, 30-second time step, Β±1 window tolerance (90s)
  • Compatible with any standard authenticator: Google Authenticator, Microsoft Authenticator, Authy, 1Password, Bitwarden
  • Setup: account menu β†’ MFA β†’ scan QR (or paste secret) β†’ verify a code β†’ enabled
  • Secrets encrypted at rest with AES-256-GCM in analysts.totp_secret

Password reset by email

  • "Forgot password" sends a single-use token via email (configurable mail provider)
  • Token expires after a short window
  • Token comparison uses hash_equals() (timing-safe)

Single sign-on (SSO / OIDC)

  • Optional OpenID Connect SSO alongside local login β€” works with Keycloak, Microsoft Entra ID, Okta, Google Workspace, Authentik, etc.
  • Authorization Code + PKCE (S256), with state and nonce validation; ID-token signature verified against the provider's JWKS (vendored firebase/php-jwt)
  • Client secrets encrypted at rest; local login retained as a break-glass fallback so a down IdP can't lock anyone out
  • Full details: Single Sign-On (SSO / OIDC)

IP-based brute-force protection

  • Repeated failed login attempts from the same IP are throttled
  • Both username and IP-level lockouts to defend against credential stuffing
  • Login attempts (success + failure) logged with IP and user agent in the Reporting module

Authorisation

Module access control

  • Per-analyst module access matrix at System β†’ Modules
  • Permissions enforced both on the homepage cards and in the waffle menu
  • API endpoints check $_SESSION['analyst_id'] and (where applicable) $_SESSION['allowed_modules']
  • The System module cannot be disabled β€” it's always accessible to active analysts

Team-based filtering

  • Tickets module filters department visibility by analyst's team membership
  • See get_my_departments.php vs get_departments.php

Encryption at Rest

AES-256-GCM authenticated encryption for sensitive database values.

  • Key file: stored outside web root at C:\wamp64\encryption_keys\sdtickets.key
  • Format: ENC: + base64(IV + auth tag + ciphertext) β€” auth tag prevents tampering
  • Migration-safe: values without ENC: prefix pass through unchanged for gradual rollout
  • Key generation: one-click from System β†’ Encryption (or php -r "echo bin2hex(random_bytes(32));")
  • No regenerate button β€” preventing accidental key destruction is more important than convenience

Encrypted columns

system_settings:

  • vcenter_server, vcenter_user, vcenter_password
  • knowledge_ai_api_key, knowledge_openai_api_key
  • intune_tenant_id, intune_client_id, intune_client_secret
  • (Per-feature AI keys β€” <ns>_api_key for knowledge_ai, cmdb_ai, workflow_ai, forms_ai, tickets_reply_cleanup, plus RFP Builder β€” each encrypted and masked separately; see AI Providers)

target_mailboxes:

  • azure_tenant_id, azure_client_id, azure_client_secret
  • oauth_redirect_uri, imap_server, target_mailbox

analysts:

  • totp_secret

Masked API responses

A subset of true secrets listed in MASKED_SETTING_KEYS are returned as ****<last4> rather than plaintext by api/settings/get_system_settings.php. The corresponding save endpoints treat blank or asterisk-prefixed submissions as "leave unchanged" so the user can re-save the settings form without re-typing the secret each time.

Session Management

  • Standard PHP sessions (session_start())
  • Session key: $_SESSION['analyst_id'] for analyst auth, $_SESSION['ss_user_id'] for self-service portal users (separate auth domains)
  • Password-expiry guard in includes/waffle-menu.php β€” if $_SESSION['password_expired'] is set, every page redirects to force_password_change.php until resolved

Email Security

  • OAuth 2.0 for Microsoft 365 and Google Workspace mailboxes β€” no plaintext mailbox passwords
  • Mailbox whitelist: per-mailbox domain and email-address whitelisting; non-whitelisted senders are rejected and logged
  • Rejection actions: configurable per-mailbox actions for rejected emails (delete, move to Deleted Items, mark as read)
  • Import actions: configurable post-import actions (delete, move to folder) with folder existence verified via Graph API before saving

File Uploads

  • Module-specific upload folders (e.g. tickets/attachments/, lms/content/, forms/uploads/) β€” each is gitignored
  • Generated filenames; original names stored in DB for display
  • Served via PHP endpoints that check session auth before serving the file

API Keys (External Access)

For the browser extension and external integrations (e.g. PowerShell asset inventory):

  • API keys generated at Software β†’ Settings β†’ API Keys
  • Rate limited: 60 requests per minute per key (configurable in System Settings)
  • Bearer-token style header
  • Revocable per-key with last-used tracking

Going Live Checklist

When moving from evaluation to production:

  1. Change the default admin password
  2. Delete the /setup folder β€” it contains diagnostic info useful only during install
  3. Generate a unique encryption key if you used a sample one
  4. Back up the encryption key file β€” losing it makes encrypted columns unrecoverable
  5. Configure OAuth for any mailboxes β€” avoid IMAP/password where possible
  6. Enable MFA on the admin account
  7. Restrict module access per analyst at System β†’ Modules
  8. Configure the password reset email so analysts can recover access without admin intervention
  9. Review whitelist entries for each mailbox to limit who can create tickets via email

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally