Functions/Private/Artifacts/IIS/Discover_IIS.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
function Discover_IIS {
<#
.SYNOPSIS
Scans for presence of the Internet Information Services (IIS) Web Server
 
.PARAMETER MountPath
The path where the Windows image was mounted to.
 
.PARAMETER OutputPath
The filesystem path where the discovery manifest will be emitted.
 
.PARAMETER ArtifactParam
Optional - one or more Website names to include in the output.
#>

[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess",'')]
[CmdletBinding()]
param (
    [Parameter(Mandatory = $true)]
    [string] $MountPath,

    [Parameter(Mandatory = $true)]
    [string] $OutputPath,

    [Parameter(Mandatory = $false)]
    [string[]] $ArtifactParam
)

$ArtifactName = Split-Path -Path $PSScriptRoot -Leaf
Write-Verbose -Message ('Started discovering {0} artifact' -f $ArtifactName)

### Path to the manifest
$Manifest = '{0}\{1}.json' -f $OutputPath, $ArtifactName

### Create a HashTable to store the results (this will get persisted to JSON)
$ManifestResult = @{
    FeatureName = ''
    Status = ''
}

$WindowsFeatures = Get-WindowsOptionalFeature -Path $MountPath
$IIS = $WindowsFeatures.Where{$_.FeatureName -eq 'IIS-WebServer'}
$EnabledFeatures = $WindowsFeatures.Where{$_.State -eq 'Enabled'}
$FeaturesToExport = $EnabledFeatures.Where{$_.FeatureName -match 'IIS'-or 
                                           $_.FeatureName -match 'ASPNET' -or 
                                           $_.FeatureName -match 'Asp-Net' -and 
                                           $_.FeatureName -NotMatch 'Management'} | Sort-Object FeatureName | Select-Object -ExpandProperty FeatureName

if ($IIS.State -eq 'Enabled') {

    $IISConfig = [xml](Get-Content -Path $MountPath\Windows\System32\inetsrv\config\applicationHost.config)
    
    $AllSites = $IISConfig | Select-Xml -XPath "//sites" | Select-Object -ExpandProperty Node
    $siteDefaults = $AllSites.siteDefaults
    $applicationDefaults = $AllSites.applicationDefaults
    $virtualDirectoryDefaults = $AllSites.virtualDirectoryDefaults
    $sites = $AllSites.site
    if ($ArtifactParam) {
        $sites = $sites.where{$_.name -in $ArtifactParam }
    }
    $Websites = New-Object System.Collections.ArrayList
    ForEach ($site in $sites) {        
       $Websites.add([PSCustomObject]@{ 
                    Name = $site.name;
                    ID = $site.id;
                    ApplicationPool = $site.application.ApplicationPool
                    PhysicalPath = $site.application.virtualDirectory.physicalPath.replace('%SystemDrive%\','\').replace('C:\','\').Replace('c:\','\');
                    Binding = [PSCustomObject]@{ Protocol = $site.bindings.binding.Protocol;
                                                 BindingInformation = $site.bindings.binding.bindingInformation } }) | Out-Null
        }

    $AllApplicationPools = $IISConfig | Select-Xml -XPath "//applicationPools" | Select-Object -ExpandProperty Node
    $ApplicationPools = $AllApplicationPools.add.name
    $ApplicationPoolDefaults = $allApplicationPools.applicationPoolDefaults
    $appPools = [PSCustomObject]@{
                        applicationPools = $ApplicationPools
                        applicationPoolDefaults = [PSCustomObject]@{managedRuntimeVersion = $ApplicationPoolDefaults.managedRuntimeVersion;
                                                                    processModel = [PSCustomObject]@{ identityType = $ApplicationPoolDefaults.processModel.identityType }
                }
        }
    $HandlerList = $IISConfig | Select-Xml -XPath "//handlers" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty add

    $DefaultHandlers = [xml](Get-Content $PSScriptRoot\DefaultHandlers.xml) | Select-Xml -XPath "//handlers" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty add
    $handlers = New-object System.Collections.ArrayList
        
    foreach ($Handler in $HandlerList) {
        if (-not $DefaultHandlers.name -match $handler.Name) {

     $handlers.Add([PSCustomObject]@{
            Name = $Handler.name
            Path = $Handler.path
            Verb = $Handler.verb
            }) | Out-Null
    }
}
    Write-Verbose -Message 'IIS service is present on the system'
    $ManifestResult.FeatureName = $FeaturesToExport  -join ';'    
    $ManifestResult.Status = 'Present'
    $ManifestResult.Websites = $Websites
    $ManifestResult.ApplicationPools = $appPools
    $ManifestResult.HttpHandlers = $handlers
    $ManifestResult.SiteDefaults = $siteDefaults
    $ManifestResult.ApplicationDefaults = $applicationDefaults
    $ManifestResult.VirtualDirectoryDefaults = $virtualDirectoryDefaults

    if ($ManifestResult.FeatureName -like '*ASPNET*' -or $ManifestResult.FeatureName -like '*Asp-Net*'){
        Write-Verbose -Message 'ASP.NET is present on the system'
        $ManifestResult.AspNetStatus = 'Present'
    }
    else {
        Write-Verbose -Message 'ASP.NET is NOT present on the system'
        $ManifestResult.AspNetStatus = 'Absent'
    }
}
else {
    Write-Verbose -Message 'IIS service is NOT present on the system'
    $ManifestResult.Status = 'Absent'
    $ManifestResult.AspNetStatus = 'Absent'
}

### Write the result to the manifest file
$ManifestResult | ConvertTo-Json -Depth 3 | Set-Content -Path $Manifest

Write-Verbose -Message ('Finished discovering {0} artifact' -f $ArtifactName)
}