├── STIG-XCCDF2CKL.ps1 ├── ManualXCCDFtoCKL- v28 ISE Version.ps1 ├── README.md └── CheckListToolv2.10.ps1 /STIG-XCCDF2CKL.ps1: -------------------------------------------------------------------------------- 1 | <############### 2 | 3 | Converts Manual STIG XCCDF to CKL 4 | using the STIG Viewer.jar and sendKey 5 | Must be opened in ISE not powershell CL 6 | 7 | Only tested on Viewer version 2.8 8 | 9 | ###############> 10 | 11 | $viewerTitle = "DISA STIG Viewer : 2.8 :" 12 | $viewerTitleExplorer = "DISA STIG Viewer : 2.8 : STIG Explorer" 13 | $viewerTitleOverwrite = "STIG Overwrite Warning!" 14 | $viewerTitleNew = "DISA STIG Viewer : 2.8 : *New Checklist" 15 | 16 | #Adjust the launch wait for Java 17 | $sleepTimer = 10 18 | 19 | # Check if running in ISE 20 | # - Not implemented yet 21 | 22 | # Open File Dialog to choose STIG Viewer (Requires ISE) 23 | $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 24 | InitialDirectory = [Environment]::GetFolderPath('Desktop') 25 | Filter = 'STIG Viewer 2.8 (*.jar)|*.jar' 26 | Title = "Select the STIG Viewer 2.8 applet" 27 | } 28 | if ($FileBrowser.ShowDialog()){ 29 | $stigViewer = $FileBrowser.FileName 30 | } 31 | 32 | # GUI, get starting folder 33 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null 34 | $folder = $null 35 | $foldername = New-Object System.Windows.Forms.FolderBrowserDialog -Property @{ 36 | rootfolder = "MyComputer" 37 | Description = "Choose base folder that contains all of the Manual STIG XML files that you want to scan" 38 | } 39 | 40 | if($foldername.ShowDialog() -eq "OK") { 41 | $folder += $foldername.SelectedPath 42 | } 43 | # Non-recursive .xml file search 44 | $xmlFiles = Get-ChildItem -Path $folder -Filter "*.xml" 45 | 46 | # Setup for active window detection 47 | $code = @' 48 | [DllImport("user32.dll")] 49 | public static extern IntPtr GetForegroundWindow(); 50 | '@ 51 | Add-Type $code -Name Utils -Namespace Win32 52 | $wshell = New-Object -ComObject wscript.shell; 53 | 54 | # Sloppy one-liner but it should work 55 | function Get-ActvieTitle() { 56 | (Get-Process | 57 | Where-Object { $_.mainWindowHandle -eq ([Win32.Utils]::GetForegroundWindow()) } | 58 | Select-Object processName, MainWindowTItle, MainWindowHandle ).MainWindowTitle 59 | } 60 | 61 | # Itterate through 62 | foreach ($xmlFile in $xmlFiles.fullname) { 63 | 64 | # Launch STIG Viewer 65 | & $stigViewer 66 | sleep -Seconds $sleepTimer 67 | # From STIG Explorer delete all listed STIGs 68 | if (Get-ActvieTitle -like "$viewerTitleExplorer"){ 69 | $wshell.SendKeys('{TAB}{TAB}^a+{F10}{ESC}{UP}~') 70 | } 71 | sleep 1 72 | 73 | # STIG Open Menu 74 | if (Get-ActvieTitle -like "$viewerTitleExplorer"){ 75 | $wshell.SendKeys('%') 76 | $wshell.SendKeys('{DOWN}{DOWN}{ENTER}') 77 | sleep 3 78 | # Paste in current STIG file 79 | $wshell.SendKeys("$xmlFile") 80 | $wshell.SendKeys('~') 81 | } 82 | sleep 1.5 83 | 84 | # Check STIG box 85 | if (Get-ActvieTitle -like "$viewerTitleExplorer"){ 86 | $wshell.SendKeys('~+{F10}{ESC}{DOWN}~') 87 | $wshell.SendKeys('%') 88 | $wshell.SendKeys('{RIGHT}{RIGHT}{DOWN}{DOWN}{DOWN}{ENTER}') 89 | } 90 | sleep 1.5 91 | 92 | # Save the file 93 | if (Get-ActvieTitle -like "$viewerTitleNew"){ 94 | $wshell.SendKeys('%') 95 | $wshell.SendKeys('{DOWN}{DOWN}{ENTER}') 96 | sleep 1.5 97 | $wshell.SendKeys("$($xmlFile.TrimEnd('.xml'))") 98 | $wshell.SendKeys('~') 99 | } 100 | sleep 1.5 101 | 102 | # Quit App 103 | if (Get-ActvieTitle -like "$viewerTitle*"){ 104 | $wshell.SendKeys('+{F10}{UP}{UP}~') 105 | } 106 | sleep 1.5 107 | 108 | } # Repeat 109 | -------------------------------------------------------------------------------- /ManualXCCDFtoCKL- v28 ISE Version.ps1: -------------------------------------------------------------------------------- 1 | <############### 2 | 3 | Converts Manual STIG XCCDF to CKL 4 | using the STIG Viewer.jar and sendKey 5 | Must be opened in ISE not powershell CL 6 | 7 | Only tested on Viewer version 2.8 8 | 9 | ###############> 10 | 11 | $viewerTitle = "DISA STIG Viewer : 2.8 :" 12 | $viewerTitleExplorer = "DISA STIG Viewer : 2.8 : STIG Explorer" 13 | $viewerTitleOverwrite = "STIG Overwrite Warning!" 14 | $viewerTitleNew = "DISA STIG Viewer : 2.8 : *New Checklist" 15 | 16 | #Adjust the launch wait for Java 17 | $sleepTimer = 10 18 | 19 | # Check if running in ISE 20 | # - Not implemented yet 21 | 22 | # Open File Dialog to choose STIG Viewer (Requires ISE) 23 | $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 24 | InitialDirectory = [Environment]::GetFolderPath('Desktop') 25 | Filter = 'STIG Viewer 2.8 (*.jar)|*.jar' 26 | Title = "Select the STIG Viewer 2.8 applet" 27 | } 28 | if ($FileBrowser.ShowDialog()){ 29 | $stigViewer = $FileBrowser.FileName 30 | } 31 | 32 | # GUI, get starting folder 33 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null 34 | $folder = $null 35 | $foldername = New-Object System.Windows.Forms.FolderBrowserDialog -Property @{ 36 | rootfolder = "MyComputer" 37 | Description = "Choose base folder that contains all of the Manual STIG XML files that you want to scan" 38 | } 39 | 40 | if($foldername.ShowDialog() -eq "OK") { 41 | $folder += $foldername.SelectedPath 42 | } 43 | # Non-recursive .xml file search 44 | $xmlFiles = Get-ChildItem -Path $folder -Filter "*.xml" 45 | 46 | # Setup for active window detection 47 | $code = @' 48 | [DllImport("user32.dll")] 49 | public static extern IntPtr GetForegroundWindow(); 50 | '@ 51 | Add-Type $code -Name Utils -Namespace Win32 52 | $wshell = New-Object -ComObject wscript.shell; 53 | 54 | # Sloppy one-liner but it should work 55 | function Get-ActvieTitle() { 56 | (Get-Process | 57 | Where-Object { $_.mainWindowHandle -eq ([Win32.Utils]::GetForegroundWindow()) } | 58 | Select-Object processName, MainWindowTItle, MainWindowHandle ).MainWindowTitle 59 | } 60 | 61 | # Itterate through 62 | foreach ($xmlFile in $xmlFiles.fullname) { 63 | 64 | # Launch STIG Viewer 65 | & $stigViewer 66 | sleep -Seconds $sleepTimer 67 | # From STIG Explorer delete all listed STIGs 68 | if (Get-ActvieTitle -like "$viewerTitleExplorer"){ 69 | $wshell.SendKeys('{TAB}{TAB}^a+{F10}{ESC}{UP}~') 70 | } 71 | sleep 1 72 | 73 | # STIG Open Menu 74 | if (Get-ActvieTitle -like "$viewerTitleExplorer"){ 75 | $wshell.SendKeys('%') 76 | $wshell.SendKeys('{DOWN}{DOWN}{ENTER}') 77 | sleep 3 78 | # Paste in current STIG file 79 | $wshell.SendKeys("$xmlFile") 80 | $wshell.SendKeys('~') 81 | } 82 | sleep 1.5 83 | 84 | # Check STIG box 85 | if (Get-ActvieTitle -like "$viewerTitleExplorer"){ 86 | $wshell.SendKeys('~+{F10}{ESC}{DOWN}~') 87 | $wshell.SendKeys('%') 88 | $wshell.SendKeys('{RIGHT}{RIGHT}{DOWN}{DOWN}{DOWN}{ENTER}') 89 | } 90 | sleep 1.5 91 | 92 | # Save the file 93 | if (Get-ActvieTitle -like "$viewerTitleNew"){ 94 | $wshell.SendKeys('%') 95 | $wshell.SendKeys('{DOWN}{DOWN}{ENTER}') 96 | sleep 1.5 97 | $wshell.SendKeys("$($xmlFile.TrimEnd('.xml'))") 98 | $wshell.SendKeys('~') 99 | } 100 | sleep 1.5 101 | 102 | # Quit App 103 | if (Get-ActvieTitle -like "$viewerTitle*"){ 104 | $wshell.SendKeys('+{F10}{UP}{UP}~') 105 | } 106 | sleep 1.5 107 | 108 | } # Repeat 109 | 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Power STIG (Work in progress) 2 | Powershell tools to manage an manipulate STIGs, SCAP scans, XCCDFs, and CLKs 3 | Many things have changes and the readme needs to be updated. 4 | 5 | ## My Definitions 6 | - STIG (Manual XCCDF) - Refers to the full scope of settings required to make a system compliant 7 | - Benchmark - This is a subset of the full STIG but it can be detected with an automated scanning tool. Things like registry entries and GPO settings are in this. 8 | - SCC / SCAP Scanner - This is the automated scanner that uses the Benchmark file 9 | - ACAS - DoD Nessus scanner that can also use the Benchmarks to conduct scans. 10 | - XCCDF - Generally refers to the xccdf.xml generated by the SCAP scanner. 11 | - CKL - Check list files created by DISA STIG Viewer. STIGs are imported into the viewer, then a checklist is created and finally the XCCDF results are imported on top of the new checklist. That will give you a propper checklist for your system. 12 | 13 | 14 | ## Work flows and scrpits to run 15 | 16 | - Download all STIGs and Benchmarks (manually) 17 | - STIG-ZIP2STIG-XCCDF will extract all STIG XCCDF.xml files from the chosen directory 18 | - STIG-XCCDF2CKL will launch STIG Viewer 2.8 and convert each of the STIGs to a CKL file 19 | - STIG-Status will RECURSIVELY look for all CKL files and will: 20 | - Analyze all statistics (CAT1,2,3 Open, Not a Finding, etc.) 21 | - Creates associated reports in CSV 22 | - If multiple versions are detected ie V1R13 and V1R14, it will ask if you want to upgrade the lower CKLs to the higher version. 23 | - Pro-tip, you should scan a folder containing your results AND the newly downloaded STIGs in order to upgrade everything, but your score and STATs will be affected. After the upgrade, scan ONLY your reports folder for accurate stats. 24 | - (In-progress) Ask if you want to import XCCDF results from ACAS or SCC, they will be imported on top of the existing CKLs. If no CKL is found for a system, it will make a new one. 25 | - (Not implemented yet) Rename all files to Hostname - STIG - VxRy 26 | - OneCKL2Many - For any manually STIGed system, most likey your settings will be the same on the other systems as well. So choose the CKL that you finished and then copy the results to all other CKLs of that type/OS. 27 | - ??? 28 | - Profit! 29 | 30 | 31 | ## History of STIGs and SCAP according to u/m00f 32 | 33 | A very abbreviated history, hopefully I get most of this right. 34 | 35 | First there was CVE. The US Government (via NIST and Mitre) created CVE so that vendors could have a common ID for talking about a vulnerability. Overtime, vendors started using CVE instead of BugTraq and other proprietary IDs. 36 | 37 | Then there was FISMA: a US law that required the US government to secure their computers. Everything was manual and audits took years. 38 | 39 | Then there was OVAL. Let by NIST and Mitre and vendors, they came up with a way to describe vulnerabilities in XML so that vendors and government could have a common format to define a vulnerability so that vendors and open source people could automate around this standard. 40 | 41 | At this point the gang at NIST and Mitre had a vision and momentum for defining IDs and standards around computer security. 42 | 43 | We are now in 2007-ish. Millions of man-hours are wasted doing FISMA compliance. Directed by the OMB, NIST is tasked with finding a way to automate all of this. They create SCAP, which uses OVAL to describe configuration compliance conditions (since a vuln definition and a configuration compliance definition are really quite similar), they use CCE to ID the checks (just like CVE IDs a vuln), and they use XCCDF to create a list of checks, aka a checklist or benchmark. They use CPE as an ID for apps and OSes. 44 | 45 | SCAP is just a name for the combination of: OVAL (for compliance checks, not vulns), CCE, XCCDF, CPE. Of course, SCAP is an actual standard written by NIST with the intention of certifying vendors who are compliant with it. And, despite being a pretty poorly run program, many vendors go through the painful process of getting certified (e.g. McAfee, Symantec, Tripwire, etc). 46 | 47 | CIS then starts converting all of their checklists to "SCAP" (meaning OVAL and XCCDF). The DoD starts doing this too with the DISA STIG checklists. So, today, there are now a ton of OS and application security checklists that are "SCAP checklists". 48 | 49 | Now, the funny thing about SCAP validation is that it is not just a protocol for defining how a checklists is created by also blends in the requirement that specific checklists (like the FDCC and USGCB checklists) be correctly executed to become certified. The reason for this is that SCAP was created to help US Government agencies pass FISMA compliance, so there has to be some sort of standard for measuring that compliance. 50 | -------------------------------------------------------------------------------- /CheckListToolv2.10.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | 3 | CheckListTool v2.10 - Made by HungryNomad 4 | 5 | If using this for the first time, make a copy of all of your checklists before running this 6 | tool against them. It can make bulk changes to all of your files. 7 | 8 | Notes: This is a tool that combines many of my random scripts and should hopefully automate 9 | many of the tasks involved in dealing with SCAPs and STIGs. It's far from perfect as I don't 10 | have many people testing my scripts just yet. My error handling could also be improved. 11 | 12 | Change log 13 | 2.9 Added HTML save output on Vuln ID menu 14 | 2.8 POAM filtering added 15 | 2.7 Supports renaming and upgrading from different versions 16 | 2.6 Added multi-select for all menus (for copy and paste) 17 | 18 | To-do list: 19 | - Add weighted score: Score = (F1(W1)+F2(W1)+F3(W3))/(W1+W2+W3) 20 | F1 = CAT1... For each group: F = (NF+NA)/(O+NF+NA+NR) 21 | W1=10, W2=4, W3=1 22 | - Add better overview screen 23 | 24 | 25 | #> 26 | 27 | Add-Type -AssemblyName System.Windows.Forms 28 | [System.Windows.Forms.Application]::EnableVisualStyles() 29 | 30 | $Form = New-Object system.Windows.Forms.Form 31 | $Form.ClientSize = '863,462' 32 | $Form.text = "WPC's Checklist Tool v2.9" 33 | $Form.TopMost = $false 34 | 35 | $ButtonFolderSelect = New-Object system.Windows.Forms.Button 36 | $ButtonFolderSelect.text = "Choose CKL Folder" 37 | $ButtonFolderSelect.width = 180 38 | $ButtonFolderSelect.height = 30 39 | $ButtonFolderSelect.location = New-Object System.Drawing.Point(17,24) 40 | $ButtonFolderSelect.Font = 'Microsoft Sans Serif,10' 41 | 42 | $ButtonScanCKL = New-Object system.Windows.Forms.Button 43 | $ButtonScanCKL.text = "Scan CKL Files" 44 | $ButtonScanCKL.width = 180 45 | $ButtonScanCKL.height = 30 46 | $ButtonScanCKL.enabled = $false 47 | $ButtonScanCKL.location = New-Object System.Drawing.Point(19,162) 48 | $ButtonScanCKL.Font = 'Microsoft Sans Serif,10' 49 | 50 | $TextCklFolder = New-Object system.Windows.Forms.TextBox 51 | $TextCklFolder.multiline = $true 52 | $TextCklFolder.text = "Scan Folder" 53 | $TextCklFolder.width = 180 54 | $TextCklFolder.height = 80 55 | $TextCklFolder.enabled = $false 56 | $TextCklFolder.location = New-Object System.Drawing.Point(18,69) 57 | $TextCklFolder.Font = 'Microsoft Sans Serif,10' 58 | 59 | $ButtonRemoveCKL = New-Object system.Windows.Forms.Button 60 | $ButtonRemoveCKL.text = "Remove CKLs" 61 | $ButtonRemoveCKL.width = 180 62 | $ButtonRemoveCKL.height = 30 63 | $ButtonRemoveCKL.enabled = $false 64 | $ButtonRemoveCKL.location = New-Object System.Drawing.Point(17,252) 65 | $ButtonRemoveCKL.Font = 'Microsoft Sans Serif,10' 66 | 67 | $TextLog = New-Object system.Windows.Forms.TextBox 68 | $TextLog.multiline = $true 69 | $TextLog.text = "Choose a CKL folder to get started" 70 | $TextLog.width = 443 71 | $TextLog.height = 80 72 | $TextLog.enabled = $false 73 | $TextLog.location = New-Object System.Drawing.Point(177,357) 74 | $TextLog.Font = 'Consolas,10,style=Bold' 75 | 76 | $ButtonRemoveDuplicateCKLs = New-Object system.Windows.Forms.Button 77 | $ButtonRemoveDuplicateCKLs.text = "Remove Duplicate CKLs" 78 | $ButtonRemoveDuplicateCKLs.width = 180 79 | $ButtonRemoveDuplicateCKLs.height = 30 80 | $ButtonRemoveDuplicateCKLs.enabled = $false 81 | $ButtonRemoveDuplicateCKLs.location = New-Object System.Drawing.Point(18,207) 82 | $ButtonRemoveDuplicateCKLs.Font = 'Microsoft Sans Serif,10' 83 | 84 | $ButtonXCCDFFolder = New-Object system.Windows.Forms.Button 85 | $ButtonXCCDFFolder.text = "Choose XCCDF Folder" 86 | $ButtonXCCDFFolder.width = 200 87 | $ButtonXCCDFFolder.height = 30 88 | $ButtonXCCDFFolder.enabled = $false 89 | $ButtonXCCDFFolder.location = New-Object System.Drawing.Point(206,24) 90 | $ButtonXCCDFFolder.Font = 'Microsoft Sans Serif,10' 91 | 92 | $ButtonImportXCCDF = New-Object system.Windows.Forms.Button 93 | $ButtonImportXCCDF.text = "Import ACAS XCCDF results" 94 | $ButtonImportXCCDF.width = 200 95 | $ButtonImportXCCDF.height = 30 96 | $ButtonImportXCCDF.enabled = $false 97 | $ButtonImportXCCDF.location = New-Object System.Drawing.Point(207,162) 98 | $ButtonImportXCCDF.Font = 'Microsoft Sans Serif,10' 99 | 100 | $ButtonImportSomeXCCDF = New-Object system.Windows.Forms.Button 101 | $ButtonImportSomeXCCDF.text = "Import some XCCDF results" 102 | $ButtonImportSomeXCCDF.width = 200 103 | $ButtonImportSomeXCCDF.height = 30 104 | $ButtonImportSomeXCCDF.enabled = $false 105 | $ButtonImportSomeXCCDF.location = New-Object System.Drawing.Point(207,207) 106 | $ButtonImportSomeXCCDF.Font = 'Microsoft Sans Serif,10' 107 | 108 | $ButtonNotReviewed = New-Object system.Windows.Forms.Button 109 | $ButtonNotReviewed.text = "Not Reviewed" 110 | $ButtonNotReviewed.width = 180 111 | $ButtonNotReviewed.height = 30 112 | $ButtonNotReviewed.enabled = $false 113 | $ButtonNotReviewed.location = New-Object System.Drawing.Point(419,70) 114 | $ButtonNotReviewed.Font = 'Microsoft Sans Serif,10' 115 | 116 | $ButtonOpenNoComment = New-Object system.Windows.Forms.Button 117 | $ButtonOpenNoComment.text = "Open No Comments" 118 | $ButtonOpenNoComment.width = 180 119 | $ButtonOpenNoComment.height = 30 120 | $ButtonOpenNoComment.enabled = $false 121 | $ButtonOpenNoComment.location = New-Object System.Drawing.Point(419,116) 122 | $ButtonOpenNoComment.Font = 'Microsoft Sans Serif,10' 123 | 124 | $ButtonVulnID = New-Object system.Windows.Forms.Button 125 | $ButtonVulnID.text = "POAM Info by Vuln ID" 126 | $ButtonVulnID.width = 180 127 | $ButtonVulnID.height = 30 128 | $ButtonVulnID.enabled = $false 129 | $ButtonVulnID.location = New-Object System.Drawing.Point(419,206) 130 | $ButtonVulnID.Font = 'Microsoft Sans Serif,10' 131 | 132 | $ButtonOpenHost = New-Object system.Windows.Forms.Button 133 | $ButtonOpenHost.text = "Requesting POAM" 134 | $ButtonOpenHost.width = 180 135 | $ButtonOpenHost.height = 30 136 | $ButtonOpenHost.enabled = $false 137 | $ButtonOpenHost.location = New-Object System.Drawing.Point(419,252) 138 | $ButtonOpenHost.Font = 'Microsoft Sans Serif,10' 139 | 140 | $Button8 = New-Object system.Windows.Forms.Button 141 | $Button8.text = "Export raw info to HTML" 142 | $Button8.width = 180 143 | $Button8.height = 30 144 | $Button8.enabled = $false 145 | $Button8.location = New-Object System.Drawing.Point(419,293) 146 | $Button8.Font = 'Microsoft Sans Serif,10' 147 | 148 | $TextXCCDFFolder = New-Object system.Windows.Forms.TextBox 149 | $TextXCCDFFolder.multiline = $true 150 | $TextXCCDFFolder.text = "XCCDF Folder" 151 | $TextXCCDFFolder.width = 200 152 | $TextXCCDFFolder.height = 80 153 | $TextXCCDFFolder.enabled = $false 154 | $TextXCCDFFolder.location = New-Object System.Drawing.Point(207,69) 155 | $TextXCCDFFolder.Font = 'Microsoft Sans Serif,10' 156 | 157 | $Button9 = New-Object system.Windows.Forms.Button 158 | $Button9.text = "Refresh ?" 159 | $Button9.width = 200 160 | $Button9.height = 30 161 | $Button9.enabled = $false 162 | $Button9.location = New-Object System.Drawing.Point(207,252) 163 | $Button9.Font = 'Microsoft Sans Serif,10' 164 | 165 | $ButtonBlankHostName = New-Object system.Windows.Forms.Button 166 | $ButtonBlankHostName.text = "Blank Host Name" 167 | $ButtonBlankHostName.width = 180 168 | $ButtonBlankHostName.height = 30 169 | $ButtonBlankHostName.enabled = $false 170 | $ButtonBlankHostName.location = New-Object System.Drawing.Point(419,24) 171 | $ButtonBlankHostName.Font = 'Microsoft Sans Serif,10' 172 | 173 | $Button11 = New-Object system.Windows.Forms.Button 174 | $Button11.text = "Clone Master CKL to other CKLs" 175 | $Button11.width = 230 176 | $Button11.height = 30 177 | $Button11.enabled = $false 178 | $Button11.location = New-Object System.Drawing.Point(616,298) 179 | $Button11.Font = 'Microsoft Sans Serif,10' 180 | 181 | $Button12 = New-Object system.Windows.Forms.Button 182 | $Button12.text = "Create Master GPO for a STIG" 183 | $Button12.width = 230 184 | $Button12.height = 30 185 | $Button12.enabled = $false 186 | $Button12.location = New-Object System.Drawing.Point(615,26) 187 | $Button12.Font = 'Microsoft Sans Serif,10' 188 | 189 | $Button = New-Object system.Windows.Forms.Button 190 | $Button.text = "Create GPO from some STIGs" 191 | $Button.width = 230 192 | $Button.height = 30 193 | $Button.enabled = $false 194 | $Button.location = New-Object System.Drawing.Point(616,82) 195 | $Button.Font = 'Microsoft Sans Serif,10' 196 | 197 | $ButtonAllOpen = New-Object system.Windows.Forms.Button 198 | $ButtonAllOpen.text = "All Open Vulnerabilities" 199 | $ButtonAllOpen.width = 180 200 | $ButtonAllOpen.height = 30 201 | $ButtonAllOpen.enabled = $false 202 | $ButtonAllOpen.location = New-Object System.Drawing.Point(419,162) 203 | $ButtonAllOpen.Font = 'Microsoft Sans Serif,10' 204 | 205 | $ButtonHostList = New-Object system.Windows.Forms.Button 206 | $ButtonHostList.text = "Get Host List per STIG" 207 | $ButtonHostList.width = 230 208 | $ButtonHostList.height = 30 209 | $ButtonHostList.enabled = $false 210 | $ButtonHostList.location = New-Object System.Drawing.Point(615,139) 211 | $ButtonHostList.Font = 'Microsoft Sans Serif,10' 212 | 213 | $ButtonSTIGList = New-Object system.Windows.Forms.Button 214 | $ButtonSTIGList.text = "Get STIG List per Host" 215 | $ButtonSTIGList.width = 230 216 | $ButtonSTIGList.height = 30 217 | $ButtonSTIGList.enabled = $false 218 | $ButtonSTIGList.location = New-Object System.Drawing.Point(615,193) 219 | $ButtonSTIGList.Font = 'Microsoft Sans Serif,10' 220 | 221 | $ButtonUpgradeCKL = New-Object system.Windows.Forms.Button 222 | $ButtonUpgradeCKL.text = "Upgrade Checklists" 223 | $ButtonUpgradeCKL.width = 180 224 | $ButtonUpgradeCKL.height = 30 225 | $ButtonUpgradeCKL.enabled = $false 226 | $ButtonUpgradeCKL.location = New-Object System.Drawing.Point(16,295) 227 | $ButtonUpgradeCKL.Font = 'Microsoft Sans Serif,10' 228 | 229 | $Button1 = New-Object system.Windows.Forms.Button 230 | $Button1.text = "Convert Manual STIG to CKL" 231 | $Button1.width = 230 232 | $Button1.height = 30 233 | $Button1.enabled = $false 234 | $Button1.location = New-Object System.Drawing.Point(615,246) 235 | $Button1.Font = 'Microsoft Sans Serif,10' 236 | 237 | $Form.controls.AddRange(@($ButtonFolderSelect,$ButtonScanCKL,$TextCklFolder,$ButtonRemoveCKL,$TextLog,$ButtonRemoveDuplicateCKLs,$ButtonXCCDFFolder,$ButtonImportXCCDF,$ButtonImportSomeXCCDF,$ButtonNotReviewed,$ButtonOpenNoComment,$ButtonVulnID,$ButtonOpenHost,$Button8,$TextXCCDFFolder,$Button9,$ButtonBlankHostName,$Button11,$Button12,$Button,$ButtonAllOpen,$ButtonHostList,$ButtonSTIGList,$ButtonUpgradeCKL,$Button1)) 238 | 239 | $ButtonFolderSelect.Add_Click({ Get-CKLFolder }) 240 | $ButtonScanCKL.Add_Click({ Scan-CLKFolder }) 241 | $ButtonRemoveDuplicateCKLs.Add_Click({ Remove-DupCKLs }) 242 | $ButtonRemoveCKL.Add_Click({ Remove-CKL }) 243 | $ButtonAllOpen.Add_Click({ View-AllOpen }) 244 | $ButtonBlankHostName.Add_Click({ View-BlankHostName }) 245 | $ButtonNotReviewed.Add_Click({ View-NotReviewed }) 246 | $ButtonOpenNoComment.Add_Click({ View-OpenNoComment }) 247 | $ButtonHostList.Add_Click({ View-HostList }) 248 | $ButtonSTIGList.Add_Click({ View-STIGList }) 249 | $ButtonOpenHost.Add_Click({ View-OpenHost }) 250 | $ButtonVulnID.Add_Click({ View-VulnID }) 251 | $ButtonXCCDFFolder.Add_Click({ Get-XCCDFFolder }) 252 | $ButtonImportXCCDF.Add_Click({ Import-XCCDF }) 253 | $ButtonImportSomeXCCDF.Add_Click({ Import-SomeXCCDF }) 254 | $ButtonUpgradeCKL.Add_Click({ Upgrade-CKL }) 255 | 256 | function View-VulnID { 257 | Disable-Buttons 258 | while (1){ 259 | $choice1 = $VIDmenu | Out-GridView -PassThru -Title "All Vulnerabilities by Vuln ID" 260 | if ($choice1){ 261 | $saveData = $ScanDetails | Where-Object {$choice1.VulnID -contains $_.VID} | 262 | Select-Object -Property VID,host,stig,Severity,Title,status,FINDING_DETAILS,COMMENTS,location | 263 | Out-GridView -PassThru -Title "$($choice1.VulnID) $($choice1.Title)" 264 | if ($saveData){ 265 | $SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog 266 | $SaveFileDialog.initialDirectory = $initialDirectory 267 | $SaveFileDialog.filter = “Text files (*.html)|*.html|All files (*.*)|*.*” 268 | $SaveFileDialog.ShowDialog() | Out-Null 269 | $SaveFileDialog.filename 270 | if ($SaveFileDialog.FileName){ 271 | $saveData | ConvertTo-Html | Out-File -FilePath $SaveFileDialog.FileName 272 | $SaveFileDialog.FileName | clip 273 | } 274 | } 275 | 276 | 277 | }else{break} 278 | } 279 | 280 | $TextLog.text = "Reporting finished. " 281 | $TextLog.refresh() 282 | Enable-Buttons 283 | } 284 | 285 | function View-AllOpen { 286 | Disable-Buttons 287 | while (1){ 288 | $choice1 = $AVmenu | Out-GridView -PassThru -Title "All Open Vulnerabilities" 289 | if ($choice1) { 290 | $subMenu = $null 291 | while(1){ 292 | $choice2 = $openVulns | Where-Object { 293 | $choice1.Host -contains $_.Host -and 294 | $choice1.STIG -contains $_.STIG -and 295 | $choice1.Location -contains $_.Location 296 | } | Out-GridView -PassThru -Title "Pick a VulnID to see other affected systems" 297 | 298 | if ($choice2){ 299 | $ScanDetails | Where-Object {$choice2.VID -contains $_.VID} | 300 | Select-Object -Property host,stig,status,FINDING_DETAILS,COMMENTS,location | 301 | Out-GridView -PassThru -Title "$($choice2.VID) $($choice2.Title)" 302 | }else{break} 303 | } 304 | }else{break} 305 | } 306 | 307 | $TextLog.text = "Reporting finished. " 308 | $TextLog.refresh() 309 | Enable-Buttons 310 | 311 | } 312 | 313 | function Upgrade-CKL { 314 | Disable-Buttons 315 | # Display the list and let the user choose 316 | $upgradeList = $upgradableCKL | Out-GridView -OutputMode Multiple -Title "Old checklists detected, which ones do you want to upgrade?" 317 | 318 | # Based on your selection above, upgrade to the latest CKLs 319 | foreach ($upgrade in $upgradeList){ 320 | 321 | # Pull in old CKL 322 | $xmlFile = $upgrade.location 323 | [xml]$xml = gc $xmlFile 324 | 325 | # Rename it as a fallback 326 | Rename-Item -path $upgrade.location -newname "$($upgrade.location).bak" 327 | 328 | # Pull in lasted CKL 329 | $benchXmlFile = $latestCKL | ?{$_.STIG -match $upgrade.STIG} 330 | [xml]$benchXml = gc $benchXmlFile.location 331 | 332 | # Copy Host info into the Benchmark CKL 333 | $benchXml.CHECKLIST.ASSET.HOST_NAME = $xml.CHECKLIST.ASSET.HOST_NAME 334 | $benchXml.CHECKLIST.ASSET.HOST_IP = $xml.CHECKLIST.ASSET.HOST_IP 335 | $benchXml.CHECKLIST.ASSET.HOST_MAC = $xml.CHECKLIST.ASSET.HOST_MAC 336 | $benchXml.CHECKLIST.ASSET.HOST_FQDN = $xml.CHECKLIST.ASSET.HOST_FQDN 337 | 338 | Write-Host -NoNewline "`nUpdating $($upgrade.host) - $($benchXmlFile.STIG) to V$($benchXmlFile.STIG_VER)R$($benchXmlFile.STIG_REV) " 339 | 340 | # Iterate through the vulns and copy over if it matches 341 | for ($i= 0; $i -lt $benchXml.CHECKLIST.STIGS.iSTIG.VULN.Count; $i++){ 342 | 343 | # Vuln-ID 344 | Write-host -NoNewline "." 345 | 346 | # Clear existing settings first then overlay the results, if any. 347 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].STATUS = "Not_Reviewed" 348 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].FINDING_DETAILS = "" 349 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].COMMENTS = "" 350 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].SEVERITY_OVERRIDE = "" 351 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].SEVERITY_JUSTIFICATION = "" 352 | 353 | # Look for this Vuln-ID in the other CKL 354 | $xml.CHECKLIST.STIGS.iSTIG.VULN | 355 | ? {$_.STIG_DATA[0].ATTRIBUTE_DATA -match $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].STIG_DATA[0].ATTRIBUTE_DATA} | 356 | % { $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].STATUS = $_.STATUS 357 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].FINDING_DETAILS = $_.FINDING_DETAILS 358 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].COMMENTS = $_.COMMENTS 359 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].SEVERITY_OVERRIDE = $_.SEVERITY_OVERRIDE 360 | $benchXml.CHECKLIST.STIGS.iSTIG.VULN[$i].SEVERITY_JUSTIFICATION = $_.SEVERITY_JUSTIFICATION 361 | } 362 | } 363 | 364 | $newName = "$(Split-Path $xmlFile)\$($upgrade.host) $($benchXmlFile.STIG) V$($benchXmlFile.STIG_VER)R$($benchXmlFile.STIG_REV) $(date -Format yyyyMMdd).ckl" 365 | 366 | 367 | # Export to XML 368 | $benchXml.Save($newName) 369 | # Grab the raw export 370 | $raw = gc -Raw $newName 371 | # Restack the XML file to be complaint with CKL Schema 372 | $raw2 = $raw -replace "\s*<([a-zA-z_]+)>\s\n\s*<\/([a-zA-z_]+)>\s\n", ("`r`n" + '<$1>' + "`r`n") 373 | $raw2 = $raw2 -replace "`r`n`r`n","`r`n" 374 | # Save using .NET IO to write in UTF8 encoding 375 | [IO.File]::WriteAllLines($newName, $raw2) 376 | 377 | # Make a new line 378 | Write-host " " 379 | $RemoveCKLs += $upgrade 380 | } 381 | 382 | if ($RemoveCKLs) { 383 | Remove-FromDB 384 | Update-DB 385 | } 386 | 387 | 388 | $TextLog.text = "Upgrade finished, rescan the folder to get the most up to date info. Also delete the .bak files if everything worked." 389 | $TextLog.refresh() 390 | Enable-Buttons 391 | 392 | } 393 | 394 | function Import-XCCDF { 395 | 396 | disable-buttons 397 | 398 | # Choose only the ZIPs 399 | $zipFiles = Get-ChildItem -Path $XCCDFFolder -Filter "*.zip" 400 | if ($zipFiles){ 401 | 402 | foreach ($zip in $zipFiles){ 403 | 404 | #Extract all XCCDFs from Zip files and put them in the the main folder 405 | Add-Type -Assembly System.IO.Compression.FileSystem 406 | $workingzip = [IO.Compression.ZipFile]::OpenRead("$($zip.FullName)") 407 | # Only extract XCCDF manual XML files 408 | $workingzip.Entries | where {$_.Name -like '*xccdf*'} | foreach {[System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, "$XCCDFFolder\" + $_.Name, $true)} 409 | $workingzip.Dispose() 410 | 411 | 412 | # Recursively look for xccdf.xml files and rename them 413 | $XCCDFFiles = Get-ChildItem -Path $XCCDFFolder -Filter "**xccdf*.xml" -Recurse 414 | 415 | foreach ($xccdf in $XCCDFFiles){ 416 | $xccdfInfo = $null 417 | 418 | # Grab some basic info and 419 | [xml]$analyze = gc $xccdf.FullName 420 | 421 | # Check if it's SCC format 422 | if ($analyze.'#comment'){ 423 | $xccdfInfo =,[pscustomobject]@{ 424 | name = $analyze.'#comment'.Split(',')[1].split(':')[-1].trimend(' ') 425 | STIG = $analyze.'#comment'.Split(',')[3].split(':')[-1].trimend(' ') 426 | file = $xccdf.FullName 427 | source = "SCC" 428 | } 429 | } 430 | 431 | # Check if it's ACAS format 432 | if ($analyze.TestResult){ 433 | $xccdfInfo =,[pscustomobject]@{ 434 | name = $analyze.TestResult.target.Split('.')[0] # Host name up the the dot 435 | STIG = $analyze.TestResult.id.TrimStart('xccdf_mil.disa.stig_testresult_') #Clean the STIG name 436 | file = $xccdf.FullName 437 | source = "ACAS" 438 | } 439 | } 440 | # Rename file 441 | Rename-Item -Path $xccdf.FullName -NewName "$($xccdfInfo.name) - $($xccdfInfo.STIG) $($xccdfInfo.source) xccdf.xml" -Force 442 | } 443 | 444 | } 445 | 446 | } 447 | 448 | # Scan folders again 449 | $XCCDFFiles = Get-ChildItem -Path $XCCDFFolder -Filter "**xccdf*.xml" -Recurse 450 | $selectedXCCDFFiles = $XCCDFFiles | Out-GridView -PassThru -Title "Which XCCDFs do you want to import?" 451 | 452 | # Stage the vars 453 | $xccdf2CKL = $null 454 | Remove-Variable xccdf -ErrorAction SilentlyContinue 455 | foreach ($xccdf in $selectedXCCDFFiles){ 456 | 457 | # Iterate through each found XCCDF (SCC specific) 458 | $xccdfInfo = $null 459 | 460 | # Grab some basic info and 461 | [xml]$analyze = gc $xccdf.FullName 462 | 463 | 464 | # Check if it's SCC format 465 | if ($analyze.'#comment'){ 466 | $xccdfInfo =,[pscustomobject]@{ 467 | name = $analyze.'#comment'.Split(',')[1].split(':')[-1].trimend(' ') 468 | STIG = $analyze.'#comment'.Split(',')[3].split(':')[-1].trimend(' ').split(' ')[0] 469 | file = $xccdf.FullName 470 | source = "SCC" 471 | } 472 | } 473 | 474 | # Check if it's ACAS format 475 | if ($analyze.TestResult){ 476 | $xccdfInfo =,[pscustomobject]@{ 477 | name = $analyze.TestResult.target.Split('.')[0] # Host name up the the dot 478 | STIG = $analyze.TestResult.id.TrimStart('xccdf_mil.disa.stig_testresult_') #Clean the STIG name 479 | file = $xccdf.FullName 480 | source = "ACAS" 481 | } 482 | } 483 | 484 | 485 | #Write-host "Analyzing $($xccdfInfo.source) XCCDF $($xccdfInfo.name) - $($xccdfInfo.STIG)" 486 | 487 | # Get matches for XCCDF 488 | # Looping though the main list 489 | $CKLOnly | ForEach-Object { 490 | # If matches up with existing... 491 | if ($_.Host -match $xccdfInfo.name -and $_.STIG -match $xccdfInfo.STIG){ 492 | $xccdf2CKL +=,[pscustomobject]@{ 493 | host = $xccdfInfo.name 494 | source = $xccdfInfo.source 495 | xccdf = $xccdfInfo.file 496 | ckl = $_.Location 497 | newName = "$(Split-Path $_.Location)\$([string]$xccdfInfo.name) $($_.STIG) V$($_.STIG_VER)R$($_.STIG_REV) $(date -Format yyyyMMdd).ckl" 498 | } 499 | 500 | } 501 | } # End the Main List check 502 | 503 | # The XCCDF didn't match up with the main list, let's create a new one 504 | 505 | if ($xccdf2CKL -eq $null){$lastCKL = 0} 506 | else {$lastCKL =$xccdf2CKL[-1].xccdf} 507 | 508 | if ($lastCKL -notlike $xccdfInfo.file){ 509 | $latestCKL | ForEach-Object { 510 | # If matches up with latest blank CKL 511 | if ($_.STIG -match $xccdfInfo.STIG){ 512 | $newCKL = "$CKLFolder\$([string]$xccdfInfo.name) $($_.STIG) V$($_.STIG_VER)R$($_.STIG_REV) $(date -Format yyyyMMdd).ckl" 513 | Copy-Item -Path $_.location -Destination $newCKL 514 | $xccdf2CKL +=,[pscustomobject]@{ 515 | host = $xccdfInfo.name 516 | source = $xccdfInfo.source 517 | xccdf = $xccdfInfo.file 518 | ckl = $newCKL 519 | newName = "$($CKLFolder)\$([string]$xccdfInfo.name) $($_.STIG) V$($_.STIG_VER)R$($_.STIG_REV) $(date -Format yyyyMMdd).ckl" 520 | } 521 | Write-Host "Using blank CKL for $(Split-Path $xccdfInfo.file -Leaf)" 522 | 523 | } 524 | } 525 | } # End the List check 526 | 527 | # Copy the unprocessed XCCDF files to the report folder 528 | if ($xccdf2CKL -eq $null){$lastCKL = 0} 529 | else {$lastCKL =$xccdf2CKL[-1].xccdf} 530 | 531 | if ($lastCKL -notlike $xccdfInfo.file){ 532 | # No matching CKL found, moving XCCDFs for later processing 533 | $newXCCDF = "$XCCDFFolder\$($xccdfInfo.name) - $($xccdfInfo.STIG) $($xccdfInfo.source) xccdf.xml" 534 | Copy-Item -Path $xccdfInfo.file -Destination $newXCCDF -ErrorAction SilentlyContinue 535 | Write-Host "Skipped - No similar CKL found for $(Split-Path $xccdfInfo.file -Leaf)" 536 | 537 | } 538 | 539 | # Use the XCCDF2CKL variable and import XCCDF settings into CKL 540 | 541 | } # End loop through XCCDFs 542 | 543 | # Process each XML / CKL 544 | if ($xccdf2CKL){ 545 | $xccdf2CKL | ForEach-Object { 546 | 547 | 548 | #### Change back to $_ 549 | [xml]$xccdf = Get-Content $_.xccdf 550 | [xml]$ckl = Get-Content $_.ckl 551 | if ($_.source -match "ACAS"){ 552 | $xccdfData = $xccdf.TestResult 553 | }else{ 554 | $xccdfData = $xccdf.Benchmark.TestResult 555 | } 556 | 557 | # Set the host info 558 | $ckl.CHECKLIST.ASSET.HOST_NAME = [string]$_.host 559 | $ckl.CHECKLIST.ASSET.HOST_IP = [string]$xccdfData.'target-address' 560 | $ckl.CHECKLIST.ASSET.HOST_MAC = [string]$($xccdfData.'target-facts'.fact | ? {$_.name -match "identifier:mac"} | Select-Object -First 1).'#text' 561 | $ckl.CHECKLIST.ASSET.HOST_FQDN = [string]$xccdfData.target 562 | 563 | $xccdfHost = $_.host 564 | 565 | Write-Host "`nProcessing $xccdfHost $($_.newName) " -NoNewline 566 | 567 | # Loop through results in xccdf 568 | foreach ($xresult in $xccdfData.'rule-result') { 569 | 570 | # Loop though checks in checklist 571 | foreach ($check in $ckl.CHECKLIST.STIGS.iSTIG.VULN ){ 572 | 573 | # Match up the CKL and XCCDF 574 | if ($check.STIG_DATA.ATTRIBUTE_DATA -contains $xresult.version){ 575 | # Pass or fail 576 | if ($xresult.result -like "pass"){ 577 | Write-Host "+" -NoNewline 578 | $check.STATUS = "NotAFinding" 579 | } 580 | 581 | if ($xresult.result -like "fail"){ 582 | Write-Host "-" -NoNewline 583 | $check.STATUS = "Open" 584 | } 585 | } 586 | } 587 | } 588 | 589 | # Export to XML 590 | $updatedCKL= "$($_.newName)" 591 | $ckl.Save($updatedCKL) 592 | Write-Host "`nSaving to $updatedCKL" 593 | # Grab the raw export 594 | $raw = gc -Raw $updatedCKL 595 | # Restack the XML file to be complaint xwith CKL Schema 596 | $raw2 = $raw -replace "\s*<([a-zA-z_]+)>\s\n\s*<\/([a-zA-z_]+)>\s\n", ("`r`n" + '<$1>' + "`r`n") 597 | $raw2 = $raw2 -replace "`r`n`r`n","`r`n" 598 | # Save using .NET IO to write in UTF8 encoding 599 | [IO.File]::WriteAllLines($updatedCKL, $raw2) 600 | 601 | # Delete old CLK 602 | 603 | if ($_.ckl -notlike $updatedCKL){ 604 | Remove-Item -Path $_.ckl 605 | # Write-Host "Renaming old CKL" 606 | # Rename-Item -Path $_.ckl -NewName "$($_.ckl).bak" 607 | } 608 | } 609 | } 610 | 611 | $TextLog.text = "Import finished, check the root of the CKL folder for CKLs that I couldn't match up with. Also rescan the folder to get updated data" 612 | $TextLog.refresh() 613 | Enable-Buttons 614 | } 615 | 616 | function Get-XCCDFFolder { 617 | Disable-Buttons 618 | $TextLog.text = "Working... " 619 | $foldername = New-Object System.Windows.Forms.FolderBrowserDialog 620 | $foldername.rootfolder = "MyComputer" 621 | $foldername.Description = "Choose base folder that contains all of the CKL files that you want to scan" 622 | 623 | if($foldername.ShowDialog() -eq "OK") { 624 | $XCCDFFolder = $foldername.SelectedPath 625 | $TextXCCDFFolder.text = $XCCDFFolder 626 | } 627 | 628 | $TextLog.text = "Changed XCCDF folder, click scan to import the CKLs." 629 | $TextLog.refresh() 630 | Enable-Buttons 631 | } 632 | 633 | function View-STIGList { 634 | Disable-Buttons 635 | while (1){ 636 | $choice1 = $ScanDetails | Select-Object -unique -Property stig,host | 637 | Group-Object host | Out-GridView -OutputMode Multiple -Title "Hosts to STIGs list" 638 | if ($choice1) { 639 | $choice1.Group | Select-Object -unique -Property stig | 640 | Out-GridView -OutputMode Multiple -Title "STIGs to Host list: $($choice1.Group[0].host)" 641 | }else{break} 642 | } 643 | 644 | $TextLog.text = "Reporting finished. " 645 | $TextLog.refresh() 646 | Enable-Buttons 647 | } 648 | 649 | function View-HostList { 650 | Disable-Buttons 651 | while (1){ 652 | $choice1 = $ScanDetails | Select-Object -unique -Property stig,host | 653 | Group-Object stig | Out-GridView -OutputMode Multiple -Title "STIGs to Host list" 654 | if ($choice1) { 655 | $choice1.Group | Select-Object -unique -Property host | 656 | Out-GridView -OutputMode Multiple -Title "STIGs to Host list: $($choice1.Group[0].stig)" 657 | }else{break} 658 | } 659 | 660 | $TextLog.text = "Reporting finished. " 661 | $TextLog.refresh() 662 | Enable-Buttons 663 | } 664 | 665 | function View-OpenNoComment { 666 | Disable-Buttons 667 | while (1){ 668 | $choice1 = $NCmenu | Out-GridView -PassThru -Title "Open and No comments" 669 | if ($choice1) { 670 | $subMenu = $null 671 | while(1){ 672 | $choice2 = $NClist | Where-Object { 673 | $choice1.Host -contains $_.Host -and 674 | $choice1.STIG -contains $_.STIG -and 675 | $choice1.Location -contains $_.Location 676 | } | Out-GridView -PassThru -Title "Pick a VulnID to see other affected systems" 677 | 678 | if ($choice2){ 679 | $ScanDetails | Where-Object {$choice2.VID -contains $_.VID} | 680 | Select-Object -Property host,stig,status,FINDING_DETAILS,COMMENTS,location | 681 | Out-GridView -PassThru -Title "$($choice2.VID) $($choice2.Title)" 682 | }else{break} 683 | } 684 | }else{break} 685 | } 686 | 687 | $TextLog.text = "Reporting finished. " 688 | $TextLog.refresh() 689 | Enable-Buttons 690 | } 691 | 692 | function View-NotReviewed { 693 | Disable-Buttons 694 | while (1){ 695 | $choice1 = $NRmenu | Out-GridView -PassThru -Title "Not Reviewed" 696 | if ($choice1) { 697 | $subMenu = $null 698 | while(1){ 699 | $choice2 = $NRlist | Where-Object { 700 | $choice1.Host -contains $_.Host -and 701 | $choice1.STIG -contains $_.STIG -and 702 | $choice1.Location -contains $_.Location 703 | } | Out-GridView -PassThru -Title "Pick a VulnID to see other affected systems" 704 | 705 | if ($choice2){ 706 | $ScanDetails | Where-Object {$choice2.VID -contains $_.VID} | 707 | Select-Object -Property host,stig,FINDING_DETAILS,COMMENTS,location | 708 | Out-GridView -PassThru -Title "$($choice2.VID) $($choice2.Title)" 709 | }else{break} 710 | } 711 | }else{break} 712 | } 713 | 714 | $TextLog.text = "Reporting finished. " 715 | $TextLog.refresh() 716 | Enable-Buttons 717 | 718 | } 719 | 720 | function View-BlankHostName { 721 | Disable-Buttons 722 | $blankHostList | Out-GridView -PassThru -Title "CLKs with Blank Host Names" 723 | $TextLog.text = "Reporting finished. " 724 | $TextLog.refresh() 725 | Enable-Buttons 726 | } 727 | 728 | function View-OpenByVID { 729 | Disable-Buttons 730 | while (1){ 731 | $choice1 = $openVulns | Group-Object severity | Out-GridView -PassThru 732 | if ($choice1) { 733 | while (1){ 734 | $choice2 = $choice1.Group | Group-Object VID | Out-GridView -OutputMode Multiple 735 | if ($choice2){ 736 | $choice2.Group | Select-Object -Property host,stig,FINDING_DETAILS,COMMENTS,location | 737 | Out-GridView -PassThru -Title "$($choice2.Group[0].VID) $($choice2.Group[0].Title)" 738 | }else{break} 739 | } 740 | }else{break} 741 | } 742 | 743 | $TextLog.text = "Reporting finished. " 744 | $TextLog.refresh() 745 | Enable-Buttons 746 | } 747 | 748 | function Remove-CKL { 749 | Disable-Buttons 750 | $TextLog.text = "Updating DB, please wait..." 751 | $TextLog.refresh() 752 | $RemoveCKLs = $ScanDetails | Select-Object -Unique -Property host,stig,stig_ver,stig_rev,location | 753 | Out-GridView -PassThru -Title "Which one(s) do you want to remove?" 754 | 755 | if ($RemoveCKLs) { 756 | Remove-FromDB 757 | Update-DB 758 | } 759 | $TextLog.text = "Remove finished. " 760 | $TextLog.refresh() 761 | Enable-Buttons 762 | 763 | } 764 | 765 | function Remove-DupCKLs { 766 | Disable-Buttons 767 | $TextLog.text = "Updating DB, please wait..." 768 | $TextLog.refresh() 769 | 770 | while (1){ 771 | $choice1 = $ScanDetails | Select-Object -Unique -Property host,stig,stig_ver,stig_rev,location | Group-Object host,stig | 772 | ? {$_.count -gt 1} | Out-GridView -Title "Multiple CKLs per Host/STIG detected. Which do you want to look at?" -PassThru 773 | if ($choice1) { 774 | $RemoveCKLs = $choice1.Group | Out-GridView -Title "Which one(s) do you want to remove?" -PassThru 775 | if ($RemoveCKLs) { 776 | Remove-FromDB 777 | Update-DB 778 | } 779 | }else{break} 780 | } 781 | $TextLog.text = "Dupe Check done. " 782 | $TextLog.refresh() 783 | Enable-Buttons 784 | } 785 | 786 | function Scan-CLKFolder { 787 | Disable-Buttons 788 | $TextLog.text = "Working... " 789 | # Clear it out 790 | $checkLists = $null 791 | $newScanDetails = $null 792 | 793 | # If the folder is blank, then it will skip the checklist scan 794 | if ($cklFolder -notlike ""){ 795 | $checkLists = Get-ChildItem -Path $cklFolder -Filter "*.ckl" -Recurse 796 | } 797 | 798 | # Won't run if $checklist is empty 799 | foreach ($checklist in $checklists){ 800 | 801 | [xml]$analyze = gc $checkList.FullName 802 | $logText = "Analyzing $($checkList.FullName)" 803 | #$logText = "Analyzing $($analyze.CHECKLIST.ASSET.HOST_NAME) - $($analyze.CHECKLIST.STIGS.iSTIG.STIG_INFO.SI_DATA[3].SID_DATA.trimstart('xccdf_mil.disa.stig_benchmark_')) - $($checkList.FullName)" 804 | write-host $logText 805 | $TextLog.text = $logText 806 | $TextLog.refresh() 807 | 808 | # Stats is cleared on each system, details is not 809 | $stats = $null 810 | foreach ($vuln in $analyze.CHECKLIST.STIGS.iSTIG.VULN){ 811 | 812 | $stats += ,[pscustomobject]@{ 813 | VID = $vuln.STIG_DATA[0].ATTRIBUTE_DATA 814 | Severity = $vuln.STIG_DATA[1].ATTRIBUTE_DATA 815 | Status = $vuln.STATUS 816 | } 817 | 818 | $newScanDetails += ,[pscustomobject]@{ 819 | VID = $vuln.STIG_DATA[0].ATTRIBUTE_DATA 820 | Severity = $vuln.STIG_DATA[1].ATTRIBUTE_DATA 821 | Status = $vuln.STATUS 822 | stig = $analyze.CHECKLIST.STIGS.iSTIG.STIG_INFO.SI_DATA[3].SID_DATA.trimstart('xccdf_mil.disa.stig_benchmark_') 823 | STIG_VER = [int]$analyze.CHECKLIST.STIGS.iSTIG.STIG_INFO.SI_DATA[0].SID_DATA.split('.')[0].trimstart('0') 824 | STIG_REV = [int]$analyze.CHECKLIST.STIGS.iSTIG.STIG_INFO.SI_DATA[6].SID_DATA.split(' ')[1].split('.')[-1].trimstart('0') 825 | FINDING_DETAILS = $vuln.FINDING_DETAILS 826 | COMMENTS = $vuln.COMMENTS 827 | host = $analyze.CHECKLIST.ASSET.HOST_NAME 828 | location = $checkList.FullName 829 | Title = $vuln.STIG_DATA[5].ATTRIBUTE_DATA 830 | Discussion = $vuln.STIG_DATA[6].ATTRIBUTE_DATA 831 | Fix = $vuln.STIG_DATA[9].ATTRIBUTE_DATA 832 | CCIRef = $vuln.STIG_DATA[24].ATTRIBUTE_DATA 833 | } 834 | } 835 | } 836 | 837 | $comboList = $scanDetails | Select-Object -Unique -Property host,stig,stig_ver,stig_rev,location 838 | $comboList += $newScanDetails | Select-Object -Unique -Property host,stig,stig_ver,stig_rev,location 839 | 840 | 841 | $RemoveCKLs = $($comboList | Group-Object -Property location | ? {$_.count -gt 1}).group | Select-Object -Unique -Property host,stig,location 842 | Remove-FromDB 843 | 844 | $scanDetails += $newScanDetails 845 | 846 | 847 | # Logic for combining records 848 | if ($CKLDetails -eq $null){ 849 | $CKLDetails += $scanDetails 850 | } 851 | 852 | Update-DB 853 | $TextLog.text = "Done importing CKLs to the database." 854 | $TextLog.refresh() 855 | Enable-Buttons 856 | } 857 | 858 | 859 | 860 | 861 | function Get-CKLFolder { 862 | Disable-Buttons 863 | $TextLog.text = "Working... " 864 | $foldername = New-Object System.Windows.Forms.FolderBrowserDialog 865 | $foldername.rootfolder = "MyComputer" 866 | $foldername.Description = "Choose base folder that contains all of the CKL files that you want to scan" 867 | 868 | if($foldername.ShowDialog() -eq "OK") { 869 | $CKLFolder = $foldername.SelectedPath 870 | $TextCklFolder.text = $cklFolder 871 | } 872 | $TextLog.text = "Changed CLK folder, click scan to import the CKLs." 873 | $TextLog.refresh() 874 | Enable-Buttons 875 | } 876 | 877 | 878 | #Write your logic code here 879 | 880 | Set-Variable -Name CKLFolder -Value $null -Option AllScope 881 | #Set-Variable -Name CKLDetails -Value $null -Option AllScope # Remove, not needed 882 | Set-Variable -Name CKLOnly -Value $null -Option AllScope 883 | Set-Variable -Name upgradableCKL -Value $null -Option AllScope 884 | Set-Variable -Name latestCKL -Value $null -Option AllScope 885 | Set-Variable -Name XCCDFFolder -Value $null -Option AllScope 886 | Set-Variable -Name XCCDFFiles -Value $null -Option AllScope 887 | Set-Variable -Name ScanDetails -Value $null -Option AllScope 888 | Set-Variable -Name RemoveCKLs -Value $null -Option AllScope 889 | Set-Variable -Name openVulns -Value $null -Option AllScope 890 | Set-Variable -Name dupeVulns -Value $null -Option AllScope 891 | Set-Variable -Name NRVulns -Value $null -Option AllScope 892 | Set-Variable -Name xccdf2CKL -Value $null -Option AllScope # Remove? Used for testing 893 | Set-Variable -Name NRmenu -Value $null -Option AllScope 894 | Set-Variable -Name NRlist -Value $null -Option AllScope 895 | Set-Variable -Name NCmenu -Value $null -Option AllScope 896 | Set-Variable -Name NClist -Value $null -Option AllScope 897 | Set-Variable -Name VIDmenu -Value $null -Option AllScope 898 | Set-Variable -Name VIDlist -Value $null -Option AllScope 899 | Set-Variable -Name AVmenu -Value $null -Option AllScope 900 | Set-Variable -Name blankHostList -Value $null -Option AllScope 901 | 902 | function Remove-FromDB{ 903 | # If anything was chosen to be removed, then pipe out $scanDetails and remove those entries 904 | if ($RemoveCKLs){ 905 | $ScanDetails = $ScanDetails | Where-Object { 906 | ($RemoveCKLs.host -notcontains $_.host) -or 907 | ($RemoveCKLs.stig -notcontains $_.stig) -or 908 | ($RemoveCKLs.location -notcontains $_.location) 909 | } 910 | } 911 | $RemoveCKLs = $null 912 | } 913 | 914 | function Disable-Buttons{ 915 | $ButtonFolderSelect.enabled = $false 916 | $ButtonScanCKL.enabled = $false 917 | $ButtonRemoveCKL.enabled = $false 918 | $ButtonRemoveDuplicateCKLs.enabled = $false 919 | $ButtonBlankHostName.enabled = $false 920 | $ButtonNotReviewed.enabled = $false 921 | $ButtonOpenNoComment.enabled = $false 922 | $ButtonHostList.enabled = $false 923 | $ButtonSTIGList.enabled = $false 924 | $ButtonXCCDFFolder.enabled = $false 925 | $ButtonNotReviewed.enabled = $false 926 | $ButtonAllOpen.enabled = $false 927 | $ButtonVulnID.enabled = $false 928 | 929 | } 930 | 931 | function Update-DB { 932 | 933 | # Probably need to refactor this whole section 934 | Write-host "Updating DB, please be patient, watch the task manager to see how hard I'm working." 935 | 936 | Write-host -nonewline "Updating: DupeVuln" 937 | $dupeVulns = $ScanDetails | Select-Object -Unique -Property host,stig,location | group host,stig | ? {$_.count -gt 1} 938 | Write-host -nonewline ", OpenVuln" 939 | $openVulns = $ScanDetails | Where-Object {($_.Status -match "Open")} | 940 | Select-Object -unique -Property host,stig,severity,VID,Title,FINDING_DETAILS,COMMENTS,location 941 | # $NRVulns = $ScanDetails | Where-Object { $_.Status -match "Not_Reviewed"} 942 | 943 | Write-host -nonewline ", CKLOnly" 944 | $CKLOnly = $ScanDetails | Select-Object -unique -Property host,STIG,STIG_VER,STIG_REV,Location 945 | 946 | # Sort by ID,VER,REV and take the most recent one 947 | Write-host -nonewline ", LatestCKL" 948 | $latestCKL = $CKLOnly | 949 | Group-Object -Property STIG | 950 | ForEach-Object{$_.Group | 951 | Sort-Object -Property STIG_VER,STIG_REV -Descending -Unique | 952 | Select-Object -First 1} 953 | 954 | # Grab a list of systems that don't match the above list 955 | Write-host -nonewline ", UpgradeableCKL" 956 | $upgradableCKL = ($CKLOnly | 957 | Group-Object STIG,STIG_VER,STIG_REV | 958 | ? {(($latestCKL | Group-Object STIG,STIG_VER,STIG_REV).Name) -notcontains $_.name}).group 959 | 960 | # Not reviewed menu builder 961 | Write-host -nonewline ", NRList" 962 | $NRmenu = $null 963 | $NRlist = $ScanDetails | Where-Object { $_.Status -match "Not_Reviewed"} | 964 | Select-Object -unique -Property host,stig,status,severity,VID,Title,location 965 | 966 | $NRList | Group-Object stig,host | ForEach-Object { 967 | 968 | $NRmenu +=,[pscustomobject]@{ 969 | CAT1 = [int]$($_.group | Where-Object {$_.severity -match "high"} | Measure-Object).Count 970 | CAT2 = [int]$($_.group | Where-Object {$_.severity -match "medium"} | Measure-Object).Count 971 | CAT3 = [int]$($_.group | Where-Object {$_.severity -match "low"} | Measure-Object).Count 972 | STIG = $_.group[0].stig 973 | Host = $_.group[0].host 974 | Location = $_.group[0].Location 975 | } 976 | } 977 | 978 | # No Comment menu builder 979 | Write-host -nonewline ", NCList" 980 | $NCmenu = $null 981 | $NClist = $openVulns | Where-Object {($_.FINDING_DETAILS -like "") -and ($_.COMMENTS -like "")} | 982 | Select-Object -unique -Property host,stig,severity,VID,Title,location 983 | 984 | $NCList | Group-Object stig,host | ForEach-Object { 985 | 986 | $NCmenu +=,[pscustomobject]@{ 987 | CAT1 = [int]$($_.group | Where-Object {$_.severity -match "high"} | Measure-Object).Count 988 | CAT2 = [int]$($_.group | Where-Object {$_.severity -match "medium"} | Measure-Object).Count 989 | CAT3 = [int]$($_.group | Where-Object {$_.severity -match "low"} | Measure-Object).Count 990 | STIG = $_.group[0].stig 991 | Host = $_.group[0].host 992 | Location = $_.group[0].Location 993 | } 994 | } 995 | 996 | # All Vulnerability menu builder 997 | Write-host -nonewline ", AllVuln" 998 | $AVmenu = $null 999 | $openVulns | Group-Object stig,host | ForEach-Object { 1000 | $AVmenu +=,[pscustomobject]@{ 1001 | CAT1 = [int]$($_.group | Where-Object {$_.severity -match "high"} | Measure-Object).Count 1002 | CAT2 = [int]$($_.group | Where-Object {$_.severity -match "medium"} | Measure-Object).Count 1003 | CAT3 = [int]$($_.group | Where-Object {$_.severity -match "low"} | Measure-Object).Count 1004 | STIG = $_.group[0].stig 1005 | Host = $_.group[0].host 1006 | Location = $_.group[0].Location 1007 | } 1008 | } 1009 | 1010 | # VID List for POAMs menu builder 1011 | Write-host -nonewline ", VulnByID" 1012 | $VIDmenu = $null 1013 | $openVulns | Group-Object vid | ForEach-Object { 1014 | $VIDmenu +=,[pscustomobject]@{ 1015 | VulnID = $_.name 1016 | NoComment = [int]$($_.group | Where-Object {($_.FINDING_DETAILS -like "") -and ($_.COMMENTS -like "")} | Measure-Object).Count 1017 | POAM_Needed = [int]$($_.group | Where-Object {($_.FINDING_DETAILS -like "*POAM Needed*") -or ($_.COMMENTS -like "*POAM Needed*")} | Measure-Object).Count 1018 | Policy_Needed = [int]$($_.group | Where-Object {($_.FINDING_DETAILS -like "*Policy Needed*") -or ($_.COMMENTS -like "*Policy Needed*")} | Measure-Object).Count 1019 | Exemption_Needed = [int]$($_.group | Where-Object {($_.FINDING_DETAILS -like "*Exemption Needed*") -or ($_.COMMENTS -like "*Exemption Needed*")} | Measure-Object).Count 1020 | Total_Open = [int]$_.count 1021 | Severity = $_.group[0].severity 1022 | Title = $_.group[0].title 1023 | } 1024 | } 1025 | 1026 | Write-host -nonewline ", BlankHost" 1027 | $blankHostList = $ScanDetails | Where-Object {$_.host -like ""} | Select-Object -Unique -Property stig,location 1028 | Write-host ". Done!" 1029 | 1030 | } 1031 | 1032 | function Enable-Buttons{ 1033 | $ButtonFolderSelect.enabled = $true 1034 | if ($CKLFolder){$ButtonScanCKL.enabled = $true} 1035 | 1036 | 1037 | if ($NRVulns){ 1038 | $ButtonNotReviewed.enabled = $true 1039 | } 1040 | 1041 | 1042 | # If there are duplicate files found 1043 | if ($DupeVulns){ 1044 | $ButtonRemoveDuplicateCKLs.enabled = $true 1045 | $TextLog.text += "`n Duplicate CKLs found, please remove the extras." 1046 | $TextLog.refresh() 1047 | } 1048 | 1049 | if ($upgradableCKL){ 1050 | $ButtonUpgradeCKL.enabled = $true 1051 | } 1052 | 1053 | if ($XCCDFFolder -and (-not $dupeVulns)){ 1054 | $ButtonImportXCCDF.enabled = $true 1055 | } 1056 | 1057 | if ($openVulns){ 1058 | # $ButtonOpenSTIG.enabled = $true 1059 | # $ButtonOpenHost.enabled = $true 1060 | # $ButtonOpenVID.enabled = $true 1061 | } 1062 | 1063 | # If there is scan info, then enable these buttons 1064 | if ($scanDetails) { 1065 | $ButtonRemoveCKL.enabled = $true 1066 | $ButtonBlankHostName.enabled = $true 1067 | $ButtonHostList.enabled = $true 1068 | $ButtonSTIGList.enabled = $true 1069 | $ButtonXCCDFFolder.enabled = $true 1070 | $ButtonOpenNoComment.enabled = $true 1071 | $ButtonNotReviewed.enabled = $true 1072 | $ButtonAllOpen.enabled = $true 1073 | $ButtonVulnID.enabled = $true 1074 | } 1075 | 1076 | } 1077 | 1078 | [void]$Form.ShowDialog() 1079 | --------------------------------------------------------------------------------