Custom Mitigation QID Scripts 

The Mitigation QID Script mitigates or remediates the risk of an active vulnerability identified in your environment. This feature is beneficial in case of zero-day vulnerabilities, where mitigation logic evolves rapidly. It allows you to quickly deploy custom responses and reduce risk without waiting for a patch.

Custom Mitigation QID scripts are managed in CAR. It serves as the central place to create, edit, clone, export, and deprecate these scripts.

Mitigation QID scripts are executed from the TruRisk™ Eliminate module. CAR is used only to manage these scripts.

Implication and Impact of Mitigation QID Scripts

Each mitigation includes an Implication and an Impact Factor to describe the nature and extent of its effect on a QID.

Implication

The implication indicates whether the impact of the mitigation on a QID is Permanent or Temporary. A temporary implication means the QID is mitigated, while a permanent implication indicates that the QID is remediated permanently.

Impact Factor

The impact factor indicates the level of impact the mitigation has on the QID. Based on the implication, you can define the impact factor:

  • Temporary: The impact factor value should be between 1-99. This indicates that the QID has been mitigated till the provided value, with 1 representing the lowest impact and 99 representing the highest impact on the vulnerability.
  • Permanent: The impact factor value is 100. This indicates that the QID has been remediated.

Mitigate a QID using Custom Mitigation Script

Once a custom Mitigation QID script is created in CAR, the mitigation becomes available for the corresponding QID in Qualys Vulnerability Management, Detection, and Response (VMDR) under the Vulnerabilities tab. You can search QIDs with available mitigations using the following query: vulnerabilities.qualysMitigable: TRUE

These custom Mitigation QID scripts are then executed through TruRisk™ Eliminate/Patch Management.

After a mitigation is successfully applied, the QIDs are marked as Fully Mitigated or Partially Mitigated in VMDR. You can view these mitigated vulnerabilities on the Vulnerabilities tab using the following query: vulnerabilities.mitigated: TRUE

Create Custom Mitigation QID Scripts

You can configure the Mitigation QID script to perform the following actions:

  • Mitigation: Used to reduce the risk of a vulnerability.
  • Detection: Used to detect a vulnerability.
  • Rollback: Used to revert changes made by a mitigation script.

To create a Custom Mitigation QID script, follow these steps:

  1. Navigate to Scripts > Scripts > CreateNew Script.

    The Create New Script page is displayed. 

  2. Enter a Name and Description for the script.

    script basic information.

  3. Click Next to view the Script Details page.
  4. Select the Type of Script as Mitigation QID.
  5. Select Platform (Windows or Linux).
  6. Complete the following Mitigation QID Details:
    Fields Description
    QID Number Provide a QID number.
    QID Severity It is a QID Severity. You can select from values 1 (minimum) to 5 (urgent).
    Implication The implication indicates whether the impact of the script on a vulnerability is permanent or temporary.

    Select the Implication value as Temporary or Permanant.

    Impact Factor Provide a value to determine the impact of the script on a vulnerability based on the Implication:
    • Temporary: The Impact Factor value should be between 1-99. This indicates that the vulnerability has been mitigated till the provided value.
    • Permanant: The Impact Factor value is 100.
    CVE IDs Provide CVE IDs that are associated with a specific QID.
    Mitigation Type Provide a text related to the mitigation type.

  7. Select the Scripting Language from the list in which you want to write the script.

    The list of scripting languages for Windows and Linux are different. 

    Platform Supported Scripting Language
    Windows PowerShell-Script, Python, and VBScript
    Linux Lua, Perl, Python, and Shell
  8. Select a script Category from the list.
  9. Specify the Timeout Limit in seconds, minutes, or hours.

    The Timeout Limit lets you define how long a script must be in execution.

    The Timeout Limit for all Windows and Linux assets ranges from one second to 48 hours. The default value is 300 seconds.

    Add script.

  10. Provide the following scripts by entering the script manually.
    • Mitigation Script: This script reduces the risk of an active vulnerability.

      Example Mitigation ScriptExample Mitigation Script

      # MITIGATION SCRIPT
      # Purpose: Generic security hardening script
      # This script applies common security best practices

      function Apply-SecurityHardening {
          # Set error action preference
          $ErrorActionPreference = "SilentlyContinue"
          
          $backupFolder = "C:\ProgramData\SecurityBackups\Generic"
          $actionsPerformed = 0
          $report = @()
          
          # Create backup folder
          if (-not (Test-Path $backupFolder)) {
              New-Item -Path $backupFolder -ItemType Directory -Force | Out-Null
              $report += "Created backup directory: $backupFolder"
          }
          
          # Backup current security settings
          $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
          $report += "Creating security settings backup..."
          
          # Backup firewall settings
          $firewallSettings = Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction
          $firewallSettings | Export-Clixml -Path "$backupFolder\firewall_$timestamp.xml"
          $report += "Firewall settings backed up"
          
          # Backup services status
          $servicesStatus = Get-Service | Select-Object Name, DisplayName, Status, StartType
          $servicesStatus | Export-Clixml -Path "$backupFolder\services_$timestamp.xml"
          $report += "Services status backed up"
          
          # Enable all firewall profiles
          $report += "`nSecuring firewall settings:"
          $firewallProfiles = Get-NetFirewallProfile
          foreach ($profile in $firewallProfiles) {
              if ($profile.Enabled -eq $false) {
                  $profileName = $profile.Name
                  Set-NetFirewallProfile -Name $profileName -Enabled True
                  $report += "  - Enabled $profileName firewall profile"
                  $actionsPerformed++
              }
          }
          
          # Disable insecure services
          $report += "`nDisabling insecure services:"
          $insecureServices = @(
              "Telnet",
              "ftpsvc",
              "MSFTPSVC",
              "TlntSvr"
          )
          
          foreach ($service in $insecureServices) {
              $svc = Get-Service -Name $service -ErrorAction SilentlyContinue
              if ($svc) {
                  if ($svc.Status -eq "Running") {
                      Stop-Service -Name $service -Force
                      $report += "  - Stopped service: $service"
                      $actionsPerformed++
                  }
                  
                  if ($svc.StartType -ne "Disabled") {
                      Set-Service -Name $service -StartupType Disabled
                      $report += "  - Disabled service: $service"
                      $actionsPerformed++
                  }
              }
          }
          
          # Set secure password policy
          $report += "`nStrengthening password policy:"
          try {
              $currentLength = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SAM").MinimumPasswordLength
              if ($currentLength -lt 12) {
                  Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SAM" -Name "MinimumPasswordLength" -Value 12
                  $report += "  - Set minimum password length to 12 characters"
                  $actionsPerformed++
              }
          } catch {
              $report += "  - Failed to update password policy: $($_.Exception.Message)"
          }
          
          # Disable SMBv1
          $report += "`nDisabling outdated protocols:"
          try {
              $smbSettings = Get-SmbServerConfiguration
              if ($smbSettings.EnableSMB1Protocol) {
                  Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
                  $report += "  - Disabled SMBv1 protocol"
                  $actionsPerformed++
              }
          } catch {
              $report += "  - Failed to disable SMBv1: $($_.Exception.Message)"
          }
          
          # Enable UAC
          $report += "`nEnhancing system protections:"
          $uacRegistry = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
          $uacEnabled = (Get-ItemProperty -Path $uacRegistry).EnableLUA
          
          if ($uacEnabled -eq 0) {
              Set-ItemProperty -Path $uacRegistry -Name "EnableLUA" -Value 1
              $report += "  - Enabled User Account Control (UAC)"
              $actionsPerformed++
          }
          
          # Create a flag file to indicate hardening was applied
          "Security hardening applied on $(Get-Date)" | Out-File "$backupFolder\hardening_applied_$timestamp.txt"
          
          # Output report
          $report | ForEach-Object { Write-Output $_ }
          
          Write-Output "`nMitigation Summary: $actionsPerformed security improvements applied"
          return 0  # Return success
      }

      # Execute mitigation function
      $mitigationResult = Apply-SecurityHardening
      exit $mitigationResult
    • Detection Script: This script detects vulnerabilities in the system.

      Example Detection ScriptExample Detection Script

      # DETECTION SCRIPT
      # Purpose: Generic vulnerability detection script
      # This script checks for common security misconfigurations

      function Detect-SecurityVulnerabilities {
          # Set error action preference
          $ErrorActionPreference = "SilentlyContinue"
          
          $vulnerabilitiesFound = 0
          $report = @()
          
          # Check Windows Firewall status
          $firewallStatus = Get-NetFirewallProfile | Select-Object Name, Enabled
          $report += "Firewall Status:"
          foreach ($profile in $firewallStatus) {
              $report += "  - $($profile.Name): $($profile.Enabled)"
              if ($profile.Enabled -eq $false) {
                  $vulnerabilitiesFound++
                  $report += "    [VULNERABLE] Firewall profile disabled"
              }
          }
          
          # Check for missing Windows updates
          $report += "`nWindows Updates:"
          try {
              $updateSession = New-Object -ComObject Microsoft.Update.Session
              $updateSearcher = $updateSession.CreateUpdateSearcher()
              $searchResult = $updateSearcher.Search("IsInstalled=0 and Type='Software'")
              
              if ($searchResult.Updates.Count -gt 0) {
                  $vulnerabilitiesFound++
                  $report += "  [VULNERABLE] Missing updates: $($searchResult.Updates.Count)"
                  $criticalUpdates = $searchResult.Updates | Where-Object { $_.MsrcSeverity -eq "Critical" } | Measure-Object
                  if ($criticalUpdates.Count -gt 0) {
                      $report += "  [HIGH RISK] Missing critical updates: $($criticalUpdates.Count)"
                  }
              } else {
                  $report += "  System is up to date"
              }
          } catch {
              $report += "  Unable to check for Windows updates"
          }
          
          # Check for weak password policy
          $report += "`nPassword Policy:"
          $passwordPolicy = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters"
          $minPasswordLength = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SAM").MinimumPasswordLength
          
          if ($minPasswordLength -lt 8) {
              $vulnerabilitiesFound++
              $report += "  [VULNERABLE] Minimum password length ($minPasswordLength) is less than recommended (8)"
          } else {
              $report += "  Minimum password length: $minPasswordLength"
          }
          
          # Check for insecure services
          $report += "`nInsecure Services:"
          $insecureServices = @(
              "Telnet",
              "ftpsvc",
              "MSFTPSVC"
          )
          
          foreach ($service in $insecureServices) {
              $svc = Get-Service -Name $service -ErrorAction SilentlyContinue
              if ($svc -and $svc.Status -eq "Running") {
                  $vulnerabilitiesFound++
                  $report += "  [VULNERABLE] Insecure service running: $service"
              }
          }
          
          # Output report
          $report | ForEach-Object { Write-Output $_ }
          
          Write-Output "`nScan Summary: $vulnerabilitiesFound vulnerabilities detected"
          return $vulnerabilitiesFound
      }

      # Execute detection function
      $detectionResult = Detect-SecurityVulnerabilities
      exit $detectionResult
    • Rollback Script: This script reverts any changes made by the mitigation script if needed. It provides a safety mechanism to restore systems to their previous state if the mitigation causes unexpected issues.

      Example Rollback ScriptExample Rollback Script

      # ROLLBACK SCRIPT
      # Purpose: Revert security hardening changes
      # This script restores original settings if mitigation needs to be undone

      function Rollback-SecurityHardening {
          # Set error action preference
          $ErrorActionPreference = "SilentlyContinue"
          
          $backupFolder = "C:\ProgramData\SecurityBackups\Generic"
          $actionsPerformed = 0
          $report = @()
          
          # Check if backup folder exists
          if (-not (Test-Path $backupFolder)) {
              $report += "No backup folder found at $backupFolder. Cannot perform rollback."
              $report | ForEach-Object { Write-Output $_ }
              return 1  # Return error
          }
          
          # Find most recent hardening flag file
          $latestFlag = Get-ChildItem -Path $backupFolder -Filter "hardening_applied_*.txt" | 
                       Sort-Object LastWriteTime -Descending | 
                       Select-Object -First 1
          
          if (-not $latestFlag) {
              $report += "No hardening flag found. Cannot determine which settings to roll back."
              $report | ForEach-Object { Write-Output $_ }
              return 1  # Return error
          }
          
          # Extract timestamp from flag filename
          $timestamp = $latestFlag.Name -replace "hardening_applied_", "" -replace ".txt", ""
          $report += "Rolling back security hardening applied on $timestamp"
          
          # Restore firewall settings
          $firewallBackup = "$backupFolder\firewall_$timestamp.xml"
          if (Test-Path $firewallBackup) {
              $report += "`nRestoring firewall settings:"
              $firewallSettings = Import-Clixml -Path $firewallBackup
              
              foreach ($profile in $firewallSettings) {
                  Set-NetFirewallProfile -Name $profile.Name -Enabled $profile.Enabled
                  $report += "  - Restored $($profile.Name) firewall profile: Enabled=$($profile.Enabled)"
                  $actionsPerformed++
              }
          } else {
              $report += "`nNo firewall backup found for timestamp $timestamp"
          }
          
          # Restore services
          $servicesBackup = "$backupFolder\services_$timestamp.xml"
          if (Test-Path $servicesBackup) {
              $report += "`nRestoring service settings:"
              $serviceSettings = Import-Clixml -Path $servicesBackup
              
              # Focus on previously modified services
              $targetServices = @("Telnet", "ftpsvc", "MSFTPSVC", "TlntSvr")
              
              foreach ($service in $targetServices) {
                  $originalService = $serviceSettings | Where-Object { $_.Name -eq $service }
                  if ($originalService) {
                      # Restore startup type
                      Set-Service -Name $service -StartupType $originalService.StartType
                      $report += "  - Restored service $service startup type to $($originalService.StartType)"
                      
                      # Restore running state if it was running
                      if ($originalService.Status -eq "Running") {
                          Start-Service -Name $service
                          $report += "  - Started service $service"
                      }
                      
                      $actionsPerformed++
                  }
              }
          } else {
              $report += "`nNo services backup found for timestamp $timestamp"
          }
          
          # Reset UAC to previous state
          # Note: We don't have a specific backup of this value, but including this for completeness
          # In a real script, you'd want to backup these specific values too
          $report += "`nRestoring system protections to default values:"
          $uacRegistry = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
          Set-ItemProperty -Path $uacRegistry -Name "EnableLUA" -Value 1
          $report += "  - Reset User Account Control (UAC) to default enabled state"
          $actionsPerformed++
          
          # Move the flag file to indicate it's been rolled back
          $rolledBackPath = $latestFlag.FullName -replace ".txt", "_ROLLED_BACK.txt"
          Move-Item -Path $latestFlag.FullName -Destination $rolledBackPath -Force
          $report += "`nMarked hardening as rolled back"
          
          # Output report
          $report | ForEach-Object { Write-Output $_ }
          
          Write-Output "`nRollback Summary: $actionsPerformed settings restored to original values"
          return 0  # Return success
      }

      # Execute rollback function
      $rollbackResult = Rollback-SecurityHardening
      exit $rollbackResult

    You can also upload the script from your local machine. For more details, refer to Upload Script.

  11. Select the Create Script in the approved state checkbox to create the script in the approved state.

    This option is available only for the manager role.

     Users with any other role must obtain script approval from an authorized user.
    For more details, refer to Qualys CAR RBAC

    Approved script.

  12. Click Next to view the Review and Confirm page.
  13. Review the details and click Confirm & Save.

The Mitigation QID script is created and displayed on the Scripts tab.

As CAR is used as a repository for storing the Mitigation QID script, you can only View Details, Edit, Clone, Export Script, and Deprecate.

Upload Script

You can upload a script from your local machine. 

The script size limit for any asset on both Windows and Linux platforms is 500 KB.

To upload a script, follow these steps:

  1. Select the Upload Script option.

  2. Click Browse to navigate and upload the required script.

    Once you upload all scripts, the script content is displayed in the Script text box. You can make changes to the script if required.

    If you are using a signed script, always use the browse mechanism to select it. This ensures that the signed script remains intact and can be executed on assets if the execution policy is set to AllSigned.

  3. Click Next.

    The Review and Confirm page displays the selections you have made for the script. It also highlights if the script you have entered contains any commands that may potentially impact the system's behavior and performance.

Edit the Mitigation QID Script

To modify the approved script, follow these steps:

  1. Navigate to the Scripts tab.
  2. To edit a script, select an approved QID script and click Edit on the Quick Actions menu.

    The Basic Information page is displayed.

  3. Modify the details as required and click Next to view the Scripts Details page.

  4. Modify the editable content as required.

  5. Provide the Reason for Edit.

  6. Click Next to view the Review and Confirm page.
  7. Review the script and click Update to save the changes to the script.

Related Topics

Cloning Scripts

Exporting Scripts

Deprecating Scripts