Tag: Zero Trust

  • CIS Hardening Standards in M365 (With Examples)

    Title:

    CIS for Microsoft 365 — Practical Hardening You Can Apply Today

    Introduction

    CIS (Center for Internet Security) publishes best-practice security baselines. In M365, CIS basically means:

    • Hardening Azure AD
    • Enforcing access control
    • Strengthening authentication
    • Improving logging
    • Locking down Exchange, SharePoint, and Teams
    • Using Conditional Access correctly
    • Reducing attack surface

    Below is the real-world version, not the theoretical one.


    1. Require MFA (CIS Level 1 Control)

    CIS Recommendation: MFA for all accounts.

    How to apply:
    Use Conditional Access:

    • Include: All users
    • Exclude: Break-glass admin
    • Require MFA
    • State: On

    2. Disable Legacy Authentication

    CIS Control: Block Basic Auth.

    Azure Example:
    CA Policy → Block legacy protocols
    Exchange → Disable POP/IMAP/SMTP AUTH


    3. Passwordless Authentication

    CIS: Prefer passwordless.

    Implementation:
    Enable:

    • Windows Hello
    • Authenticator App
    • FIDO2 keys

    4. Limit Global Admin Roles

    CIS: Admin roles must be minimized.

    How to do it:
    Assign:

    • GA = 2 accounts
    • Use PIM (Privileged Identity Management)
    • Require MFA + justification

    5. Require Compliant Devices

    CIS: Block unmanaged devices.

    Apply with Conditional Access:
    Grant → Require device to be:

    • Compliant
    • Hybrid joined
    • Or require approved apps

    6. Exchange Online Protections

    CIS: Anti-phishing, anti-malware, safe links, safe attachments.


    7. Audit Logging

    CIS: Must be enabled.

    Check:

    Get-AdminAuditLogConfig
    Get-AdminAuditLogConfig | FL UnifiedAuditLogIngestionEnabled
    

    8. Session Control

    Use Conditional Access → Session Limits

    • 8 hour max
    • Force reauthentication

    Conclusion

    CIS is not complicated.
    It’s just applying security baselines consistently using tools already built into M365:

    • Conditional Access
    • Defender
    • PIM
    • MFA
    • Logging

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Quick “Reflexes” Using PowerShell to Block Bad Actors: Emergency Transport Rules + Layer 3/7 Firewall Controls

    In modern cloud environments, threats don’t wait for meetings, approvals, or planning sessions.
    Sometimes an attack hits so fast that your only advantage is instinct, experience, and the ability to act immediately.

    Last month, I experienced exactly that — a coordinated impersonation attempt from multiple bad actors in Europe using public cloud hosting (GCP) as their relay. They created their own connectors and attempted to impersonate internal executives and accounting contacts.

    The attack bypassed standard controls because:

    • They used legitimate cloud IP ranges
    • They generated perfect SPF/DKIM passes
    • Their mail flow looked “clean” until you read the headers
    • They used crafted envelope senders + forged display names

    The only way to stop them instantly — before users were tricked — was to drop two transport rules at highest priority using PowerShell.
    These acted as “circuit breakers” until perimeter firewall rules could be deployed.

    Below is the exact PowerShell approach, redacted and rewritten for general use.


    🚨 Reflex Script #1 — Emergency “Kill Switch” Rule

    Purpose: If attackers are impersonating an internal address like [email protected], this rule blocks any external sender who uses that address in the envelope from or header from.

    # Connect to Exchange Online
    Connect-ExchangeOnline
    
    # Create emergency kill-switch rule
    New-TransportRule -Name "KILL SWITCH: Block external spoofing of noreply" `
    -FromScope External `
    -HeaderContainsMessageHeader "From" `
    -HeaderContainsWords "noreply@" `
    -SetSCL 9 `
    -StopRuleProcessing $true `
    -Priority 0
    

    What this rule does instantly:

    • Stops external senders pretending to be noreply@
    • Sets SCL=9 so the message is quarantined or rejected (depending on policy)
    • Stops evaluation of all other rules — making it hit within milliseconds

    🚨 Reflex Script #2 — Block ALL External Senders Using a Protected Address

    Attackers often rotate payloads or try other internal addresses.
    This second rule blocks all attempts — even if they change tactics.

    New-TransportRule -Name "BLOCK ALL External From Protected Address" `
    -FromScope External `
    -SenderAddressMatchesPatterns "noreply@", "billing@", "alerts@" `
    -SetSCL 9 `
    -StopRuleProcessing $true `
    -Priority 1
    

    You can modify the patterns depending on the address being abused.


    🛡️ Why This Worked Instantly

    These scripts bypass the UI delay and:

    • Apply before EOP content filters
    • Hit prior to Safe Links/Safe Attachments
    • Trigger even if messages pass SPF/DKIM/DMARC
    • Intercept mail before it reaches the user’s mailbox
    • Provide time to analyze, trace, and escalate

    This is why reflex PowerShell is critical for senior-level engineers — the GUI is too slow during live attacks.


    🔐 Permanent Fix: Layer 3 / Layer 7 Firewall Enforcement

    Once the immediate threat was stopped with PowerShell, the permanent fix required:

    Layer 3 (IP-based blocklists)

    Blocking:

    • Abused GCP IP ranges
    • Known threat actor networks
    • Anonymous compute nodes

    Layer 7 (Application-layer filtering)

    Policies included:

    • Block SMTP traffic from unknown hosts
    • Block unauthorized connector-based submissions
    • Strict URL filtering for phishing redirectors
    • Geo-blocking regions with no business presence

    Once these firewall measures were active, the PowerShell Kill Switch rules were safely disabled to avoid unnecessary mail flow impact.


    💡 Lessons Learned

    1. Bad actors are fast — you must be faster.
    2. Transport rules + PowerShell are your instant “circuit breakers.”
    3. SPF/DKIM/DMARC are not enough when attackers leverage cloud infrastructure.
    4. Layer 3 and Layer 7 controls create the “permanent seal.”
    5. Instant response + longer-term architecture = real protection.

    This is the type of real-world, battle-tested example that hiring panels want to hear.
    Not theory — lived experience.


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Secure Azure setup with Entra ID, Bastion, and private VM


    Scope

    Stand up a fresh Azure landing zone with a minimal but secure baseline: Entra ID (Azure AD) hardening, management structure, logging, networking, a Windows/Linux VM without public exposure, and safe access (Bastion + Entra sign-in).

    Placeholders to replace:
    TENANT_NAME · MG_ROOT · SUB_NAME · RG_CORE · RG_NET · RG_VM · LOCATION · VNET_NAME · SUBNET_APP · BASTION_SUBNET · VM_NAME · VM_SIZE · ADMIN_GROUP_OBJECTID


    0) Prereqs

    • Azure tenant & subscription created (via portal/Commerce).
    • Azure CLI logged in: az login az account set --subscription "SUB_NAME"
    • Optional SKUs: Entra ID P1/P2 for Conditional Access, PIM, Identity Protection.

    1) Entra ID (Tenant) Baseline

    • Create two break-glass cloud-only Global Admin accounts; long passwords; exclude from CA; store offline.
    • Turn on Security Defaultsor implement baseline Conditional Access:
      • Require MFA for admins.
      • Disable legacy/basic auth.
      • Require MFA for all users or at least privileged roles.
    • Enable SSPR, passwordless Authenticator (and FIDO2 keys if available).
    • Use PIM for role activation (P2).
    • Create AAD groups for RBAC (e.g., Azure-VM-Admins).

    (Portal-driven; no commands included to keep this redacted.)


    2) Management Structure & Tags

    • Create management group root and place the subscription under it.
    • Standardize tags (Owner, CostCenter, Env, DataClass).
    az account management-group create -n MG_ROOT
    az account management-group subscription add --name MG_ROOT --subscription "SUB_NAME"
    

    3) Core Resource Groups & Logging

    az group create -n RG_CORE -l LOCATION
    az group create -n RG_NET  -l LOCATION
    az group create -n RG_VM   -l LOCATION
    
    # Log Analytics workspace
    az monitor log-analytics workspace create -g RG_CORE -n LAW-CORE -l LOCATION
    LAW_ID=$(az monitor log-analytics workspace show -g RG_CORE -n LAW-CORE --query id -o tsv)
    
    # Send Activity Logs to LAW
    az monitor diagnostic-settings create \
      --name "activity-to-law" \
      --resource "/subscriptions/$(az account show --query id -o tsv)" \
      --workspace $LAW_ID \
      --logs '[{"categoryGroup":"allLogs","enabled":true}]'
    

    4) Guardrails with Azure Policy (minimal starter)

    # Require tags
    az policy assignment create -g RG_CORE -n require-tags \
      --policy "Require a tag and its value on resources" \
      --params '{"tagName":{"value":"Owner"},"tagValue":{"value":"REDACTED"}}'
    
    # Allowed locations
    az policy assignment create -g RG_CORE -n allowed-locations \
      --policy "Allowed locations" \
      --params '{"listOfAllowedLocations":{"value":["LOCATION"]}}'
    

    Enable Microsoft Defender for Cloud and auto-provision agents (portal) to get JIT VM access recommendations and secure score.


    5) Networking (no public RDP/SSH)

    # VNet + subnets
    az network vnet create -g RG_NET -n VNET_NAME -l LOCATION \
      --address-prefixes 10.10.0.0/16 \
      --subnet-name SUBNET_APP --subnet-prefix 10.10.10.0/24
    
    # Dedicated Bastion subnet (must be exactly AzureBastionSubnet)
    az network vnet subnet create -g RG_NET --vnet-name VNET_NAME \
      -n AzureBastionSubnet --address-prefixes 10.10.254.0/27
    
    # NSG and rules (deny inbound by default; allow vnet)
    az network nsg create -g RG_NET -n NSG-APP
    az network nsg rule create -g RG_NET --nsg-name NSG-APP -n Allow-VNet \
      --priority 100 --access Allow --direction Inbound --protocol '*' \
      --source-address-prefixes VirtualNetwork --source-port-ranges '*' \
      --destination-address-prefixes VirtualNetwork --destination-port-ranges '*'
    
    # Associate NSG to the app subnet
    az network vnet subnet update -g RG_NET --vnet-name VNET_NAME -n SUBNET_APP \
      --network-security-group NSG-APP
    

    6) Bastion (safe console access)

    # Public IP for Bastion
    az network public-ip create -g RG_NET -n pip-bastion -l LOCATION --sku Standard --zone 1 2 3
    
    # Bastion host
    az network bastion create -g RG_NET -n bas-VNET_NAME -l LOCATION \
      --public-ip-address pip-bastion --vnet-name VNET_NAME
    

    7) VM (managed identity, no public IP, Entra login)

    Windows example:

    # NIC (no public IP)
    az network nic create -g RG_VM -n nic-VM_NAME \
      --vnet-name VNET_NAME --subnet SUBNET_APP
    
    # VM
    az vm create -g RG_VM -n VM_NAME \
      --image Win2022Datacenter --size VM_SIZE \
      --nics nic-VM_NAME --assign-identity \
      --admin-username "localadmin" --admin-password "GENERATE-STRONG-PASSWORD" \
      --enable-agent true --os-disk-size-gb 128
    
    # Enable AAD login extension (Windows)
    az vm extension set -g RG_VM -n AADLoginForWindows --publisher Microsoft.Azure.ActiveDirectory \
      --vm-name VM_NAME
    
    # Grant Entra groups the VM login roles
    VM_ID=$(az vm show -g RG_VM -n VM_NAME --query id -o tsv)
    az role assignment create --assignee-object-id ADMIN_GROUP_OBJECTID \
      --role "Virtual Machine Administrator Login" --scope $VM_ID
    

    Linux example (SSH keys + AAD login):

    az vm create -g RG_VM -n VM_NAME \
      --image Ubuntu2204 --size VM_SIZE \
      --nics nic-VM_NAME --assign-identity \
      --authentication-type ssh --ssh-key-values ~/.ssh/id_rsa.pub
    
    # Enable AAD SSH login (Linux)
    az vm extension set -g RG_VM -n AADSSHLoginForLinux --publisher Microsoft.Azure.ActiveDirectory \
      --vm-name VM_NAME
    
    # RBAC for login
    az role assignment create --assignee-object-id ADMIN_GROUP_OBJECTID \
      --role "Virtual Machine Administrator Login" --scope $VM_ID
    

    Accessing the VM (no public IP):

    • Portal → Resource → ConnectBastion → Open session (RDP for Windows, SSH for Linux).
    • Optionally enable Just-In-Time in Defender for Cloud; keep NSG closed otherwise.

    8) Backup, Patching, and Keys

    # Recovery Services vault + VM backup
    az backup vault create -g RG_CORE -n rsv-core -l LOCATION
    az backup protection enable-for-vm -g RG_CORE -v rsv-core --vm VM_NAME --policy-name "DefaultPolicy"
    
    # VM guest patching (Update Manager) – enable in portal for the RG/VM
    
    • Store secrets/keys in Azure Key Vault; use managed identity from the VM to fetch secrets.
    • Use Server-side encryption (SSE) with platform-managed keys (default) or customer-managed keys (CMK) via Key Vault if required.

    9) Monitoring (Guest + Platform)

    # Enable VM Insights / Diagnostics to LAW
    az monitor diagnostic-settings create \
      --name "vm-to-law" \
      --resource $VM_ID --workspace $LAW_ID \
      --metrics '[{"category":"AllMetrics","enabled":true}]' \
      --logs '[{"categoryGroup":"allLogs","enabled":true}]'
    

    10) Cost Guardrails

    • Create a Budget in Cost Management with email alerts at 50/80/100%.
    • Consider Reservations and Auto-shutdown on dev/test VMs.

    11) Access Patterns to Prefer

    • Bastion or Private endpoints; avoid public RDP/SSH.
    • Entra sign-in to VMs with RBAC (Virtual Machine User/Administrator Login).
    • PIM + MFA for privileged roles.
    • JIT for any temporary inbound need.

    Minimal Tear-down (lab)

    # Danger: deletes resources
    az group delete -n RG_VM  -y
    az group delete -n RG_NET -y
    az group delete -n RG_CORE -y
    

    Notes & Deviations

    • For domain-join scenarios, use Entra ID DS (managed domain) or a full AD DS in Azure; keep DCs on a separate subnet with restricted NSG.
    • For Intune/MDM of servers, consider Azure Arc + Defender for Endpoint.
    • Replace all placeholders and remove screenshots/IDs before publishing externally.

    For more info:
    Microsoft Entra ID overview/service description. Microsoft Learn
    • Connect to a VM using Azure Bastion (private IP). Microsoft Learn
    • Private Endpoint / Private Link overview & quickstart. Microsoft Learn+1


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

error: Content is protected !!