BrowserExtensionRisk.psm1



<#
.Synopsis
   Get Specific Extension Risk Rating.
.DESCRIPTION
   Get Specific Extension Risk Rating using crxcavator.io API. Reference: https://crxcavator.io/docs.html#/report_breakdown
.EXAMPLE
   Get-ExtensionRiskRating -ExtensionID "{33730d30-3c0a-46f7-be41-3e0cda806b94}" -ExtensionVersion "1.2.1" -ExtensionPlatform "Firefox" -Verbose
 
VERBOSE: Performing the operation "Get-ExtensionRiskRating" on target "ExtensionID={33730d30-3c0a-46f7-be41-3e0cda806b94}, ExtensionVersion=1.2.1 for Firefox platform using crxcavator.io API".
VERBOSE: GET https://api.crxcavator.io/v1/report/{33730d30-3c0a-46f7-be41-3e0cda806b94}/1.2.1?platform=Firefox with 0-byte payload
VERBOSE: received -byte response of content type application/json
 
RiskLevel RiskScore RiskDetails
--------- --------- -----------
High 644 {Webstore, RetireJS, ContentSecurityPolicy, Permissions}
 
#>

function Get-ExtensionRiskRating
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    [Alias("ExtensionRisk")]
    Param
    (
        # Specific Extension ID
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $ExtensionID,

        # Specific Extension Version
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=1)]
        $ExtensionVersion,

        # Specific Extension Platform
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=2)]
        [ValidateSet("FireFox","Chrome","Edge")]
        $ExtensionPlatform
    )

    Begin
    {
    }
    Process
    {
        if ($pscmdlet.ShouldProcess("ExtensionID=$ExtensionID, ExtensionVersion=$ExtensionVersion for $ExtensionPlatform platform using crxcavator.io API", "Get-ExtensionRiskRating"))
        {
            try {
                $Uri="https://api.crxcavator.io/v1/report/$ExtensionID/$($ExtensionVersion)?platform=$ExtensionPlatform"
                $CRXResponse=Invoke-WebRequest $Uri
                $CRXRiskDetails=$CRXResponse | ConvertFrom-Json
                $RiskDetailProps=@{
                    ContentSecurityPolicy=$CRXRiskDetails.data.risk.csp.total        
                    Permissions=$CRXRiskDetails.data.risk.permissions.total
                    RetireJS=$CRXRiskDetails.data.risk.retire.total    
                    Webstore =$CRXRiskDetails.data.risk.webstore.total
                }
                $p=@{
                    RiskScore=$CRXRiskDetails.data.risk.total
                    RiskLevel=switch ($CRXRiskDetails.data.risk.total) {
                        {$_ -le 377} { "Low" }
                        {$_ -gt 377 -and $_ -le 478} { "Medium" }
                        {$_ -gt 478} { "High" }
                        Default {"N/A"}
                    }
                    RiskDetails=$RiskDetailProps
                }

                $RiskScoreObj=New-Object -TypeName psobject -Property $p
                $RiskScoreObj    
            }
            catch {
                #Catch Exception
                Write-Verbose "Something Bad Happened. Please read exception message for more details."
                Write-Output "Catched Exception: $_"   
            }
        }

    }
    End
    {
    }
}

<#
.Synopsis
   Get installed Mozilla Firefox browser extensions for specific user.
.DESCRIPTION
   Get installed Mozilla Firefox browser extensions for specific user. Gets all enabled extensions from all Firefox profiles.
.EXAMPLE
PS > Get-FirefoxInstalledExtension -Username andys -Verbose
 
VERBOSE: Performing the operation "Get-FirefoxInstalledExtension" on target "Username=andys".
 
User : andys
Browser : Firefox
Profile : 9kb82iec.default-release-1585665124484
Id : {33730d30-3c0a-46f7-be41-3e0cda806b94}
Name : Resting
Version : 1.2.1
Type : extension
Description :
Creator : Mirko Perillo
HomepageURL : https://github.com/mirkoperillo/resting
Visible : True
Active : True
InstallDate : 7/20/2021 8:18:24 AM
UpdateDate : 7/20/2021 8:18:24 AM
Path : C:\Users\andys\AppData\Roaming\Mozilla\Firefox\Profiles\9kb82iec.default-release-1585665124484\extensions\{33730d30
                      -3c0a-46f7-be41-3e0cda806b94}.xpi
UserPermissions : @{permissions=System.Object[]; origins=System.Object[]}
OptionalPermissions : @{permissions=System.Object[]; origins=System.Object[]}
 
User : andys
Browser : Firefox
Profile : 9kb82iec.default-release-1585665124484
Id : {73a6fe31-595d-460b-a920-fcc0f8843232}
Name : NoScript
Version : 11.2.11
Type : extension
Description :
Creator :
HomepageURL :
Visible : True
Active : True
InstallDate : 3/31/2020 2:32:58 PM
UpdateDate : 8/2/2021 11:06:34 AM
Path : C:\Users\andys\AppData\Roaming\Mozilla\Firefox\Profiles\9kb82iec.default-release-1585665124484\extensions\{73a6fe31
                      -595d-460b-a920-fcc0f8843232}.xpi
UserPermissions : @{permissions=System.Object[]; origins=System.Object[]}
OptionalPermissions : @{permissions=System.Object[]; origins=System.Object[]}
 
 
#>

function Get-FirefoxInstalledExtension
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    [Alias("FirefoxExtension","gfie")]
    Param
    (
        # Username(s) to get installed browser extensions from
        [Parameter(ValueFromPipelineByPropertyName=$true,
        Mandatory=$true,
        Position=0)]      
        [string[]]$Username
    )

    Begin
    {
    }
    Process
    {
        if ($pscmdlet.ShouldProcess("Username=$Username", "Get-FirefoxInstalledExtension"))
        {
            try {
                $origin = New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0
                $ExtensionsList=New-Object 'System.Collections.Generic.List[psobject]'
                
                foreach($u in $Username){
                    #Get Firefox Extension Json
                    $Path="C:\Users\$u\AppData\Roaming\Mozilla\Firefox\Profiles\"
                    $ExtFile=Get-ChildItem -path $Path -File  -Filter "extensions.json" -Recurse
                    
                    foreach($ef in $ExtFile){
                        $ExtensionList=(Get-Content -Path $ef.FullName | ConvertFrom-Json).addons | Where-Object {$_.active -eq $true}
                        foreach($e in $ExtensionList){
                            
                            $p=[ordered]@{
    
                                User=$u
                                Browser="Firefox"
                                Profile=$ef.Directory.Name
                                Id=$e.Id
                                Name=$e.defaultLocale.Name
                                Version=$e.version
                                Type=$e.Type
                                Description=$e.defaultLocale.Descripiton
                                Creator=$e.defaultLocale.Creator
                                HomepageURL=$e.defaultLocale.homepageURL
                                Active=$e.active
                                InstallDate=$origin.AddMilliseconds($e.installDate)
                                UpdateDate=$origin.AddMilliseconds($e.updateDate)
                                Path=$e.path
                                UserPermissions=$e.UserPermissions
                                OptionalPermissions=$e.OptionalPermissions
    
                            }
                            $ExtObj=New-Object psobject -Property $p
                            $ExtensionsList.add($ExtObj) | Out-Null
                            
                            
                            
                            
                        }
                    }
                    
                }
    
                $ExtensionsList
            }
            catch {
                #Catch Exception
                Write-Verbose "Something Bad Happened. Please read exception message for more details."
                Write-Output "Catched Exception: $_"
            }


            
        }
    }
    End
    {
    }
}

<#
.Synopsis
   Get installed Chrome like browser(s) extensions for specific user.
.DESCRIPTION
   Get installed Google Chrome and Microsoft Edge browser extensions for specific user. Gets all enabled extensions from all Chrome and Edge profiles.
.EXAMPLE
PS> Get-ChromeInstalledExtension -Username andys -Verbose
 
VERBOSE: Performing the operation "Get-ChromeInstalledExtension" on target "Username=andys".
 
User : andys
Browser : Chrome
Profile : Default
Id : aapocclcgogkmnckokdopfmhonfmgoek
Name : Slides
Version : 0.10
Type : app
Description : Create and edit presentations
Creator :
HomepageURL :
Active : True
InstallDate : 3/31/2020 10:44:03 AM
UpdateDate : 3/31/2020 10:44:03 AM
Path : C:\Users\andys\AppData\Local\Google\Chrome\User Data\Default\Extensions\aapocclcgogkmnckokdopfmhonfmgoek\0.10_0
UserPermissions :
OptionalPermissions :
 
User : andys
Browser : Chrome
Profile : Default
Id : aohghmighlieiainnegkcijnfilokake
Name : Docs
Version : 0.10
Type : app
Description : Create and edit documents
Creator :
HomepageURL :
Active : True
InstallDate : 3/31/2020 10:44:04 AM
UpdateDate : 3/31/2020 10:44:04 AM
Path : C:\Users\andys\AppData\Local\Google\Chrome\User Data\Default\Extensions\aohghmighlieiainnegkcijnfilokake\0.10_0
UserPermissions :
OptionalPermissions :
 
.EXAMPLE
Get-ChromeInstalledExtension -Username andys -Verbose -Edge
 
VERBOSE: Performing the operation "Get-ChromeInstalledExtension" on target "Username=andys".
VERBOSE: Getting Extensions for Default profile
VERBOSE: Getting Extensions for Profile 1 profile
VERBOSE: There are no installed extensions for Profile 1 profile.
 
User : andys
Browser : Edge
Profile : Default
Id : bhmdjpobkcdcompmlhiigoidknlgghfo
Name : Boomerang - SOAP & REST Client
Version : 7.4.4
Type : extension
Description : Seamlessly integrate and test SOAP & REST services.
Creator : Ashwin K
HomepageURL :
Active : True
InstallDate : 11/17/2021 7:34:00 AM
UpdateDate : 11/17/2021 7:34:00 AM
Path : C:\Users\andys\AppData\Local\Microsoft\Edge\User Data\Default\Extensions\bhmdjpobkcdcompmlhiigoidknlgghfo\7.4.4_0
UserPermissions : {<all_urls>, contextMenus, http://*/, https://*/…}
OptionalPermissions :
 
User : andys
Browser : Edge
Profile : Default
Id : ndcileolkflehcjpmjnfbnaibdcgglog
Name :
Version : 4.40.0
Type : app
Description :
Creator : BetaFish
HomepageURL :
Active : True
InstallDate : 11/17/2021 7:33:34 AM
UpdateDate : 11/17/2021 7:33:34 AM
Path : C:\Users\andys\AppData\Local\Microsoft\Edge\User Data\Default\Extensions\ndcileolkflehcjpmjnfbnaibdcgglog\4.40.0_0
UserPermissions : {tabs, <all_urls>, contextMenus, webRequest…}
OptionalPermissions :
#>

function Get-ChromeInstalledExtension
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    [Alias("ChromeExtension","gcie")]
    Param
    (
        # Username(s) to get installed browser extensions from
        [Parameter(ValueFromPipelineByPropertyName=$true,
        Mandatory=$true,
        Position=0)]      
        [string[]]$Username,

        [switch]$Edge


    )

    Begin
    {
    }
    Process
    {
        if ($pscmdlet.ShouldProcess("Username=$Username", "Get-ChromeInstalledExtension"))
        {
            try {
                $ExtensionsList=New-Object 'System.Collections.Generic.List[psobject]'
                if($Edge){
                    $SpecificPath="Microsoft\Edge"
                    $Browser="Edge"
                }else{
                    
                    $SpecificPath="Google\Chrome"
                    $Browser="Chrome"
                }
                foreach($u in $Username){
                    $LocalState=Get-content "C:\Users\$Username\AppData\Local\$SpecificPath\User Data\Local State" | ConvertFrom-Json
                    $ChromeProfiles=$LocalState.profile.info_cache | Get-Member | Where-Object {$_.MemberType -eq "NoteProperty"} | Select-Object -ExpandProperty Name
                    foreach ($profile in $ChromeProfiles) {
                        Write-Verbose "Getting Extensions for $profile profile"
                        if(Test-Path -Path "C:\Users\$Username\AppData\Local\$SpecificPath\User Data\$profile\Extensions"){
                            $ExtensionFolders = Get-ChildItem -Path "C:\Users\$Username\AppData\Local\$SpecificPath\User Data\$profile\Extensions" | Where-Object {$_.name -ne "Temp"}
                            foreach ($e in $ExtensionFolders) {
                                $ExtensionVersions = Get-ChildItem -Path "$($e.FullName)" | Select-Object -First 1
                                $Manifest=Get-Content -Raw -Path "$($ExtensionVersions.FullName)\manifest.json" | ConvertFrom-Json
                                $ExtensionName=$Manifest.name
                                $ExtensionDescr=$Manifest.Description
                                $ExtensionType="extension"
                                if($ExtensionName -like "*MSG*")
                                {
                                    $MessagesPath=Get-ChildItem "$($ExtensionVersions.FullName)\_locales\en*" | Select-Object -First 1
                                    $Messages=Get-Content -Raw -Path "$MessagesPath\messages.json" | ConvertFrom-Json
                                    $ExtensionName=$Messages.appName.Message
                                    $ExtensionDescr=$Messages.appDesc.Message
                                    $ExtensionType="app"
                                }
                                    
                                $p=[ordered]@{
        
                                    User=$u
                                    Browser=$Browser
                                    Profile=$profile
                                    Id=$e.Name
                                    Name=$ExtensionName
                                    Version=$Manifest.version
                                    Type=$ExtensionType
                                    Description=$ExtensionDescr
                                    Creator=$Manifest.author
                                    HomepageURL=""
                                    Active=$true
                                    InstallDate=$e.CreationTime
                                    UpdateDate=$e.LastWriteTime
                                    Path=$($ExtensionVersions.FullName)
                                    UserPermissions=$Manifest.permissions
                                    OptionalPermissions=""
        
                                }
                                $ExtObj=New-Object psobject -Property $p
                                $ExtensionsList.Add($ExtObj) | Out-Null  
                            }
                        }else {
                            Write-Verbose "There are no installed extensions for $profile profile."
                        }
                    }
                }
                $ExtensionsList
            }
            catch {
                #Catch Exception
                Write-Verbose "Something Bad Happened. Please read exception message for more details."
                Write-Output "Catched Exception: $_"
            }


            
        }
    }
    End
    {
    }
}



<#
.Synopsis
   Get Installed Browser Extensions and analyzing Risk Rating.
.DESCRIPTION
   Get Installed Browser Extensions and analyzing Risk Rating using crxcavator.io API. Supported browsers: Firefox, Chrome and Edge.
.EXAMPLE
   PS > Get-InstalledBrowserExtension -Browser FireFox,Edge,Chrome -Verbose
 
VERBOSE: Performing the operation "Get-InstalledBrowserExtension" on target "Username=*, Browser=FireFox Edge Chrome, RiskScore Skipped - False".
VERBOSE: Getting Local Users
VERBOSE: Getting Mozilla Firefox Installed Extensions
VERBOSE: There are 17 Firefox active extensions.
VERBOSE: Getting Edge Installed Extensions
VERBOSE: Getting Extensions for Default profile
VERBOSE: Getting Extensions for Profile 1 profile
VERBOSE: There are no installed extensions for Profile 1 profile.
VERBOSE: There are 2 Edge active extensions.
VERBOSE: Getting Google Chrome Installed Extensions
VERBOSE: Getting Extensions for Default profile
VERBOSE: Getting Extensions for Profile 1 profile
VERBOSE: Getting Extensions for Profile 2 profile
VERBOSE: There are 23 Chrome active extensions.
VERBOSE: Getting Risk Score for Installed Extensions
VERBOSE: There are 4 browser profiles.
VERBOSE: There are 42 installed extensions identified.
VERBOSE:
                    Extension Risk Ratings Summary:
 
                        High Risk - 4 (10%)
                        Medium Risk - 4 (10%)
                        Low Risk - 34 (81%)
 
 
User : andys
Browser : Firefox
Profile : 9kb82iec.default-release-1585665124484
Id : {33730d30-3c0a-46f7-be41-3e0cda806b94}
Name : Resting
Version : 1.2.1
Type : extension
Description :
Creator : Mirko Perillo
HomepageURL : https://github.com/mirkoperillo/resting
Active : True
InstallDate : 7/20/2021 8:18:24 AM
UpdateDate : 7/20/2021 8:18:24 AM
Path : C:\Users\andys\AppData\Roaming\Mozilla\Firefox\Profiles\9kb82iec.default-release-1585665124484\extensions\{33730d30-3c0a-46f7-be41-3e0cda806b94
                      }.xpi
UserPermissions : @{permissions=System.Object[]; origins=System.Object[]}
OptionalPermissions : @{permissions=System.Object[]; origins=System.Object[]}
RiskRating : @{RiskLevel=High; RiskScore=644; RiskDetails=System.Collections.Hashtable}
 
User : andys
Browser : Firefox
Profile : 9kb82iec.default-release-1585665124484
Id : {73a6fe31-595d-460b-a920-fcc0f8843232}
Name : NoScript
Version : 11.2.11
Type : extension
Description :
Creator :
HomepageURL :
Active : True
InstallDate : 3/31/2020 2:32:58 PM
UpdateDate : 8/2/2021 11:06:34 AM
Path : C:\Users\andys\AppData\Roaming\Mozilla\Firefox\Profiles\9kb82iec.default-release-1585665124484\extensions\{73a6fe31-595d-460b-a920-fcc0f8843232
                      }.xpi
UserPermissions : @{permissions=System.Object[]; origins=System.Object[]}
OptionalPermissions : @{permissions=System.Object[]; origins=System.Object[]}
RiskRating : @{RiskLevel=High; RiskScore=513; RiskDetails=System.Collections.Hashtable}
 
User : andys
Browser : Firefox
Profile : 9kb82iec.default-release-1585665124484
Id : {d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}
Name : Adblock Plus - free ad blocker
Version : 3.11.2
Type : extension
Description :
Creator : eyeo GmbH
HomepageURL :
Active : True
InstallDate : 3/31/2020 2:33:17 PM
UpdateDate : 9/1/2021 1:23:48 PM
Path : C:\Users\andys\AppData\Roaming\Mozilla\Firefox\Profiles\9kb82iec.default-release-1585665124484\extensions\{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d
                      }.xpi
UserPermissions : @{permissions=System.Object[]; origins=System.Object[]}
OptionalPermissions : @{permissions=System.Object[]; origins=System.Object[]}
RiskRating : @{RiskLevel=Low; RiskScore=; RiskDetails=System.Collections.Hashtable}
#>

function Get-InstalledBrowserExtension
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    [Alias("gibe")]
    Param
    (
        # Username to get installed browser extensions from
        [Parameter(ValueFromPipelineByPropertyName=$true,
        Position=0)]      
        $Username="*",

        # Browser to get installed extensions from
        [Parameter(ValueFromPipelineByPropertyName=$true,
                   Position=1)]
        [ValidateSet("FireFox","Chrome","Edge")]
        $Browser=@("FireFox","Chrome","Edge"),

        # Do not perform Risc Score Check for installed browser extensions
        [Parameter(ValueFromPipelineByPropertyName=$true,
        Position=2)]  
        [switch]    
        $NoRiskScore=$false


    )

    Begin
    {
    }
    Process
    {
        if ($pscmdlet.ShouldProcess("Username=$Username, Browser=$($Browser), RiskScore Skipped - $NoRiskScore", "Get-InstalledBrowserExtension"))
        {

            try {
                Write-Verbose "Getting Local Users"
                $Users=Get-LocalUser | Where-Object {$_.Enabled -eq $true}
                if($Username -ne "*"){
                    Write-Verbose "Checking if '$($Username)' exists on local machine"
                    $Users=$Users | Where-Object {$_.name -eq "$Username"} | Select-Object -ExpandProperty Name
                    if($Users.count -eq 0){
                        Write-Error "User '$($Username)' cannot be found."
                        break
                    }
                }
                $ExtensionList=$null
                foreach ($u in $Users){
                    #Get respective function for selected browser
                    switch ($Browser) {
                        "Firefox" { 
                            Write-Verbose "Getting Mozilla Firefox Installed Extensions"
                            $FirefoxExtensions=Get-FirefoxInstalledExtension -UserName $u
                            $ExtensionList+=$FirefoxExtensions
                            Write-Verbose "There are $($FirefoxExtensions.count) Firefox active extensions."
    
                            }
                        
                        "Chrome" { 
                            Write-Verbose "Getting Google Chrome Installed Extensions" 
                            $ChromeExtensions=Get-ChromeInstalledExtension -Username $u
                            $ExtensionList+=$ChromeExtensions
                            Write-Verbose "There are $($ChromeExtensions.count) Chrome active extensions."
                        }
                        
                        "Edge" { 
                            Write-Verbose "Getting Edge Installed Extensions" 
                            $EdgeExtensions=Get-ChromeInstalledExtension -Edge -Username $u
                            $ExtensionList+=$EdgeExtensions
                            Write-Verbose "There are $($EdgeExtensions.count) Edge active extensions."
                        }
                        
                        Default {}
                    }
                    
                    #Merge all functions output into one

                    if(!$NoRiskScore){
                        Write-Verbose "Getting Risk Score for Installed Extensions"
                        foreach($e in $ExtensionList){
                            $RiskScoreObj=Get-ExtensionRiskRating -ExtensionID $e.Id -ExtensionVersion $e.version -ExtensionPlatform $e.Browser
                            $e | Add-Member  -NotePropertyName "RiskRating" -NotePropertyValue $RiskScoreObj
                        }
                    }
                    Write-Verbose "There are $($ExtensionList| Select-Object -ExpandProperty User -Unique | Measure-Object | Select-Object -ExpandProperty Count) users."
                    Write-Verbose "There are $($ExtensionList| Select-Object -ExpandProperty Profile -Unique | Measure-Object | Select-Object -ExpandProperty Count) browser profiles."
                    
                    Write-Verbose "There are $($ExtensionList.count) installed extensions identified."
                    $HighRiskExtensions=$ExtensionList| Where-Object {$_.RiskRating.RiskLevel -eq "High"} | Measure-Object | Select-Object -ExpandProperty Count
                    $MediumRiskExtensions=$ExtensionList| Where-Object {$_.RiskRating.RiskLevel -eq "Medium"} | Measure-Object | Select-Object -ExpandProperty Count
                    $LowRiskExtensions=$ExtensionList| Where-Object {$_.RiskRating.RiskLevel -eq "Low"} | Measure-Object | Select-Object -ExpandProperty Count
                    
                    Write-Verbose "
                    Extension Risk Ratings Summary:
 
                        High Risk - $($HighRiskExtensions) ($([Math]::Round(($HighRiskExtensions*100)/$($ExtensionList.Count)))%)
                        Medium Risk - $($MediumRiskExtensions) ($([Math]::Round(($MediumRiskExtensions*100)/$($ExtensionList.Count)))%)
                        Low Risk - $($LowRiskExtensions) ($([Math]::Round(($LowRiskExtensions*100)/$($ExtensionList.Count)))%)
                    "

                    $ExtensionList
    
                }

                

            }
            catch {
                #Catch Exception
                Write-Verbose "Something Bad Happened. Please read exception message for more details."
                Write-Output "Catched Exception: $_"   
            }
        }
    }
    End
    {
    }
}