{"id":353773,"date":"2024-09-02T13:47:08","date_gmt":"2024-09-02T13:47:08","guid":{"rendered":"https:\/\/www.ninjaone.com\/script-hub\/listar-extensiones-del-navegador\/"},"modified":"2024-10-13T19:05:37","modified_gmt":"2024-10-13T19:05:37","slug":"listar-extensiones-del-navegador","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/es\/script-hub\/listar-extensiones-del-navegador\/","title":{"rendered":"C\u00f3mo usar PowerShell para listar las extensiones del navegador en Windows"},"content":{"rendered":"<p>La gesti\u00f3n de las extensiones del navegador en m\u00faltiples usuarios y sistemas es un reto com\u00fan en la gesti\u00f3n de TI. Las extensiones del navegador, aunque \u00fatiles, pueden plantear importantes riesgos de seguridad si no se controlan adecuadamente. Pueden introducir vulnerabilidades, espiar las actividades de los usuarios o convertirse en puntos de entrada de <a href=\"https:\/\/www.ninjaone.com\/blog\/5-steps-for-removing-malware-from-your-computer\/\" target=\"_blank\" rel=\"noopener\">malware<\/a>.<\/p>\n<p>Este script ofrece una soluci\u00f3n s\u00f3lida para que los profesionales de TI y los <a href=\"https:\/\/www.ninjaone.com\/es\/que-es-un-msp\" target=\"_blank\" rel=\"noopener\">proveedores de servicios gestionados (MSP)<\/a> <strong>realicen un inventario de las extensiones del navegador instaladas en navegadores populares<\/strong> como Chrome, Firefox y Edge.<\/p>\n<h2>Contexto<\/h2>\n<p>A medida que las organizaciones dependen cada vez m\u00e1s de las aplicaciones basadas en web, el papel de las extensiones de navegador ha ido creciendo. Sin embargo, esto tambi\u00e9n aumenta la necesidad de supervisi\u00f3n para garantizar que las extensiones sean seguras y cumplan las pol\u00edticas de la organizaci\u00f3n. Este script responde a estas necesidades proporcionando un informe completo sobre todas las extensiones de navegador instaladas para los principales navegadores, lo que lo convierte en una herramienta esencial para los profesionales de TI y los MSP que necesitan mantener la seguridad y el cumplimiento.<\/p>\n<h2>El script para listar las extensiones del navegador en Windows<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 5.1\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    Reports on all installed browser extensions for Chrome, Firefox and Edge.\r\n.DESCRIPTION\r\n    Reports on all installed browser extensions for Chrome, Firefox and Edge.\r\n.EXAMPLE\r\n    (No Parameters)\r\n\r\n    A Google Chrome installation was detected. Searching Chrome for browser extensions...\r\n    A Microsoft Edge installation was detected. Searching Microsoft Edge for browser extensions...\r\n    A Firefox installation was detected. Searching Firefox for browser extensions...\r\n    Attempting to set Custom Field 'Multiline'.\r\n    WARNING: 10,000 Character Limit has been reached! Trimming output until the character limit is satisfied...\r\n    Successfully set Custom Field 'Multiline'!\r\n    Attempting to set Custom Field 'WYSIWYG'.\r\n    Successfully set Custom Field 'WYSIWYG'!\r\n    Browser extensions were detected.\r\n\r\n\r\n    Browser      : Chrome\r\n    User         : cheart\r\n    Name         : askBelynda | Sustainable Shopping\r\n    Extension ID : pcmbjnfbjkeieekkahdfgchcbjfhhgdi\r\n    Description  : Sustainable shopping made simple with askBelynda. Choose ethical products o(...)\r\n\r\n    Browser      : Chrome\r\n    User         : cheart\r\n    Name         : Beni - Your secondhand shopping assistant\r\n    Extension ID : efdgbhncnligcbloejoaemnfhjihkccj\r\n    Description  : The easiest way to shop secondhand.  Beni finds the best resale alternative(...)\r\n\r\n    Browser      : Chrome\r\n    User         : cheart\r\n    Name         : Bonjourr \u00c3\u201a\u00c2\u00b7 Minimalist Startpage\r\n    Extension ID : dlnejlppicbjfcfcedcflplfjajinajd\r\n    Description  : Improve your web browsing experience with Bonjourr, a beautiful, customizab(...)\r\n\r\n    Browser      : Chrome\r\n    User         : cheart\r\n    Name         : Boxel 3D\r\n    Extension ID : mjjgmlmpeaikcaajghilhnioimmaibon\r\n    Description  : Boxel 3D is the 3rd release of your favorite box jumping game made by the d(...)\r\n\r\n    ...\r\n\r\nPARAMETER: -MultilineCustomField \"ReplaceMeWithNameOfAMultilineCustomField\"\r\n    Specify the name of a multiline custom field to optionally store the search results in. Leave blank to not set a multiline field.\r\n\r\nPARAMETER: -WysiwygCustomField \"ReplaceMeWithAnyWYSIWYGCustomField\"\r\n    Specify the name of a WYSIWYG custom field to optionally store the search results in. Leave blank to not set a WYSIWYG field.\r\n\r\n.NOTES\r\n    Minimum OS Architecture Supported: Windows 10, Windows Server 2016\r\n    Release Notes: Initial Release\r\nBy using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaone.com\/terms-of-use.\r\n    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. \r\n    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. \r\n    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. \r\n    Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. \r\n    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. \r\n    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. \r\n    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n#&gt;\r\n\r\n[CmdletBinding()]\r\nparam (\r\n    [Parameter()]\r\n    [String]$MultilineCustomField,\r\n    [Parameter()]\r\n    [String]$WysiwygCustomField\r\n)\r\n\r\nbegin {\r\n    # Replace parameters with the dynamic script variables.\r\n    if ($env:multilineCustomFieldName -and $env:multilineCustomFieldName -notlike \"null\") { $MultilineCustomField = $env:multilineCustomFieldName }\r\n    if ($env:wysiwygCustomFieldName -and $env:wysiwygCustomFieldName -notlike \"null\") { $WysiwygCustomField = $env:wysiwygCustomFieldName }\r\n\r\n    # Check if $MultilineCustomField and $WysiwygCustomField are both not null and have the same value\r\n    if ($MultilineCustomField -and $WysiwygCustomField -and $MultilineCustomField -eq $WysiwygCustomField) {\r\n        Write-Host \"[Error] Custom Fields of different types cannot have the same name.\"\r\n        Write-Host \"https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/360060920631-Custom-Fields-Configuration-Device-Role-Fields\"\r\n        exit 1\r\n    }\r\n\r\n    # Function to get user registry hives based on the type of account\r\n    function Get-UserHives {\r\n        param (\r\n            [Parameter()]\r\n            [ValidateSet('AzureAD', 'DomainAndLocal', 'All')]\r\n            [String]$Type = \"All\",\r\n            [Parameter()]\r\n            [String[]]$ExcludedUsers,\r\n            [Parameter()]\r\n            [switch]$IncludeDefault\r\n        )\r\n    \r\n        # Patterns for user SID depending on account type\r\n        $Patterns = switch ($Type) {\r\n            \"AzureAD\" { \"S-1-12-1-(\\d+-?){4}$\" }\r\n            \"DomainAndLocal\" { \"S-1-5-21-(\\d+-?){4}$\" }\r\n            \"All\" { \"S-1-12-1-(\\d+-?){4}$\" ; \"S-1-5-21-(\\d+-?){4}$\" } \r\n        }\r\n    \r\n        # Fetch user profiles whose SIDs match the defined patterns and prepare objects with their details\r\n        $UserProfiles = Foreach ($Pattern in $Patterns) { \r\n            Get-ItemProperty \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\*\" |\r\n                Where-Object { $_.PSChildName -match $Pattern } | \r\n                Select-Object @{Name = \"SID\"; Expression = { $_.PSChildName } },\r\n                @{Name = \"UserName\"; Expression = { \"$($_.ProfileImagePath | Split-Path -Leaf)\" } }, \r\n                @{Name = \"UserHive\"; Expression = { \"$($_.ProfileImagePath)\\NTuser.dat\" } }, \r\n                @{Name = \"Path\"; Expression = { $_.ProfileImagePath } }\r\n        }\r\n    \r\n        # Handle inclusion of the default user profile if requested\r\n        switch ($IncludeDefault) {\r\n            $True {\r\n                $DefaultProfile = \"\" | Select-Object UserName, SID, UserHive, Path\r\n                $DefaultProfile.UserName = \"Default\"\r\n                $DefaultProfile.SID = \"DefaultProfile\"\r\n                $DefaultProfile.Userhive = \"$env:SystemDrive\\Users\\Default\\NTUSER.DAT\"\r\n                $DefaultProfile.Path = \"C:\\Users\\Default\"\r\n    \r\n                $DefaultProfile | Where-Object { $ExcludedUsers -notcontains $_.UserName }\r\n            }\r\n        }\r\n\r\n        # Return user profiles, excluding any specified users\r\n        $UserProfiles | Where-Object { $ExcludedUsers -notcontains $_.UserName }\r\n    }\r\n\r\n    # Function to check if the current PowerShell session is running with elevated permissions\r\n    function Test-IsElevated {\r\n        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n        $p = New-Object System.Security.Principal.WindowsPrincipal($id)\r\n        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)\r\n    }\r\n\r\n    function Set-NinjaProperty {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True)]\r\n            [String]$Name,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            $Value,\r\n            [Parameter()]\r\n            [String]$DocumentName\r\n        )\r\n    \r\n        $Characters = $Value | Out-String | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n        if ($Characters -ge 200000) {\r\n            throw [System.ArgumentOutOfRangeException]::New(\"Character limit exceeded; the value is greater than or equal to 200,000 characters.\")\r\n        }\r\n        \r\n        # If requested to set the field value for a Ninja document, we'll specify it here.\r\n        $DocumentationParams = @{}\r\n        if ($DocumentName) { $DocumentationParams[\"DocumentName\"] = $DocumentName }\r\n        \r\n        # This is a list of valid fields that can be set. If no type is specified, it is assumed that the input does not need to be changed.\r\n        $ValidFields = \"Attachment\", \"Checkbox\", \"Date\", \"Date or Date Time\", \"Decimal\", \"Dropdown\", \"Email\", \"Integer\", \"IP Address\", \"MultiLine\", \"MultiSelect\", \"Phone\", \"Secure\", \"Text\", \"Time\", \"URL\", \"WYSIWYG\"\r\n        if ($Type -and $ValidFields -notcontains $Type) { Write-Warning \"$Type is an invalid type! Please check here for valid types: https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality\" }\r\n        \r\n        # The field below requires additional information to be set.\r\n        $NeedsOptions = \"Dropdown\"\r\n        if ($DocumentName) {\r\n            if ($NeedsOptions -contains $Type) {\r\n                # Redirect error output to the success stream to make it easier to handle errors if nothing is found or if something else goes wrong.\r\n                $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n            }\r\n        }\r\n        else {\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2&gt;&amp;1\r\n            }\r\n        }\r\n        \r\n        # If an error is received with an exception property, the function will exit with that error information.\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n        \r\n        # The below types require values not typically given in order to be set. The below code will convert whatever we're given into a format ninjarmm-cli supports.\r\n        switch ($Type) {\r\n            \"Checkbox\" {\r\n                # Although it's highly likely we were given a value like \"True\" or a boolean datatype, it's better to be safe than sorry.\r\n                $NinjaValue = [System.Convert]::ToBoolean($Value)\r\n            }\r\n            \"Date or Date Time\" {\r\n                # Ninjarmm-cli expects the GUID of the option to be selected. Therefore, the given value will be matched with a GUID.\r\n                $Date = (Get-Date $Value).ToUniversalTime()\r\n                $TimeSpan = New-TimeSpan (Get-Date \"1970-01-01 00:00:00\") $Date\r\n                $NinjaValue = $TimeSpan.TotalSeconds\r\n            }\r\n            \"Dropdown\" {\r\n                # Ninjarmm-cli is expecting the guid of the option we're trying to select. So we'll match up the value we were given with a guid.\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selection = $Options | Where-Object { $_.Name -eq $Value } | Select-Object -ExpandProperty GUID\r\n        \r\n                if (-not $Selection) {\r\n                    throw [System.ArgumentOutOfRangeException]::New(\"Value is not present in dropdown options.\")\r\n                }\r\n        \r\n                $NinjaValue = $Selection\r\n            }\r\n            default {\r\n                # All the other types shouldn't require additional work on the input.\r\n                $NinjaValue = $Value\r\n            }\r\n        }\r\n        \r\n        # We'll need to set the field differently depending on if its a field in a Ninja Document or not.\r\n        if ($DocumentName) {\r\n            $CustomField = Ninja-Property-Docs-Set -AttributeName $Name -AttributeValue $NinjaValue @DocumentationParams 2&gt;&amp;1\r\n        }\r\n        else {\r\n            $CustomField = $NinjaValue | Ninja-Property-Set-Piped -Name $Name 2&gt;&amp;1\r\n        }\r\n        \r\n        if ($CustomField.Exception) {\r\n            throw $CustomField\r\n        }\r\n    }\r\n\r\n    # Function to find installation keys based on the display name, optionally returning uninstall strings\r\n    function Find-InstallKey {\r\n        [CmdletBinding()]\r\n        param (\r\n            [Parameter(ValueFromPipeline = $True)]\r\n            [String]$DisplayName,\r\n            [Parameter()]\r\n            [Switch]$UninstallString,\r\n            [Parameter()]\r\n            [String]$UserBaseKey\r\n        )\r\n        process {\r\n            # Initialize an empty list to hold installation objects\r\n            $InstallList = New-Object System.Collections.Generic.List[Object]\r\n\r\n            # If no user base key is specified, search in the default system-wide uninstall paths\r\n            if (!$UserBaseKey) {\r\n                # Search for programs in 32-bit and 64-bit locations. Then add them to the list if they match the display name\r\n                $Result = Get-ChildItem -Path \"HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*\" | Get-ItemProperty | Where-Object { $_.DisplayName -like \"*$DisplayName*\" }\r\n                if ($Result) { $InstallList.Add($Result) }\r\n\r\n                $Result = Get-ChildItem -Path \"HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*\" | Get-ItemProperty | Where-Object { $_.DisplayName -like \"*$DisplayName*\" }\r\n                if ($Result) { $InstallList.Add($Result) }\r\n            }\r\n            else {\r\n                # If a user base key is specified, search in the user-specified 64-bit and 32-bit paths.\r\n                $Result = Get-ChildItem -Path \"$UserBaseKey\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*\" | Get-ItemProperty | Where-Object { $_.DisplayName -like \"*$DisplayName*\" }\r\n                if ($Result) { $InstallList.Add($Result) }\r\n    \r\n                $Result = Get-ChildItem -Path \"$UserBaseKey\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*\" | Get-ItemProperty | Where-Object { $_.DisplayName -like \"*$DisplayName*\" }\r\n                if ($Result) { $InstallList.Add($Result) }\r\n            }\r\n    \r\n            # If the UninstallString switch is specified, return only the uninstall strings; otherwise, return the full installation objects.\r\n            if ($UninstallString) {\r\n                $InstallList | Select-Object -ExpandProperty UninstallString -ErrorAction SilentlyContinue\r\n            }\r\n            else {\r\n                $InstallList\r\n            }\r\n        }\r\n    }\r\n\r\n    if (!$ExitCode) {\r\n        $ExitCode = 0\r\n    }\r\n}\r\nprocess {\r\n    # Check if the script is running with elevated permissions (administrator rights)\r\n    if (!(Test-IsElevated)) {\r\n        Write-Host -Object \"[Error] Access Denied. Please run with Administrator privileges.\"\r\n        exit 1\r\n    }\r\n\r\n    # Search for Chrome installations on the system and enable chrome extension search if found.\r\n    Find-InstallKey -DisplayName \"Chrome\" | ForEach-Object {\r\n        $ChromeInstallations = $True\r\n    }\r\n\r\n    # Search for Firefox installations on the system and enable firefox extension search if found.\r\n    Find-InstallKey -DisplayName \"Firefox\" | ForEach-Object {\r\n        $FireFoxInstallations = $True\r\n    }\r\n\r\n    # Search for Edge installations on the system and flag if found and enable edge extension search if found.\r\n    Find-InstallKey -DisplayName \"Edge\" | ForEach-Object {  \r\n        $EdgeInstallations = $True\r\n    }\r\n\r\n    # Retrieve all user profiles from the system\r\n    $UserProfiles = Get-UserHives -Type \"All\"\r\n    # Loop through each profile on the machine\r\n    Foreach ($UserProfile in $UserProfiles) {\r\n        # Load User ntuser.dat if it's not already loaded\r\n        If (($ProfileWasLoaded = Test-Path Registry::HKEY_USERS\\$($UserProfile.SID)) -eq $false) {\r\n            Start-Process -FilePath \"cmd.exe\" -ArgumentList \"\/C reg.exe LOAD HKU\\$($UserProfile.SID) `\"$($UserProfile.UserHive)`\"\" -Wait -WindowStyle Hidden\r\n        }\r\n\r\n        # Repeat search for installations of browsers but in the user's registry context\r\n        Find-InstallKey -UserBaseKey \"Registry::HKEY_USERS\\$($UserProfile.SID)\" -DisplayName \"Chrome\" | ForEach-Object { \r\n            $ChromeInstallations = $True\r\n        }\r\n        Find-InstallKey -UserBaseKey \"Registry::HKEY_USERS\\$($UserProfile.SID)\" -DisplayName \"Firefox\" | ForEach-Object { \r\n            $FireFoxInstallations = $True\r\n        }\r\n        Find-InstallKey -UserBaseKey \"Registry::HKEY_USERS\\$($UserProfile.SID)\" -DisplayName \"Edge\" | ForEach-Object { \r\n            $EdgeInstallations = $True\r\n        }\r\n\r\n        # Unload NTuser.dat\r\n        If ($ProfileWasLoaded -eq $false) {\r\n            [gc]::Collect()\r\n            Start-Sleep 1\r\n            Start-Process -FilePath \"cmd.exe\" -ArgumentList \"\/C reg.exe UNLOAD HKU\\$($UserProfile.SID)\" -Wait -WindowStyle Hidden | Out-Null\r\n        }\r\n    }\r\n\r\n    # Initialize a list to store details of detected browser extensions\r\n    $BrowserExtensions = New-Object System.Collections.Generic.List[object]\r\n\r\n    # If Chrome was found, search for Chrome extensions in each user's profile\r\n    if ($ChromeInstallations) {\r\n        Write-Host -Object \"A Google Chrome installation was detected. Searching Chrome for browser extensions...\"\r\n        $UserProfiles | ForEach-Object {\r\n            if (!(Test-Path -Path \"$($_.Path)\\AppData\\Local\\Google\\Chrome\\User Data\" -ErrorAction SilentlyContinue)) {\r\n                return\r\n            }\r\n\r\n            if(Test-Path -Path \"$($_.Path)\\AppData\\Local\\Google\\Chrome\\User Data\\Local State\" -ErrorAction SilentlyContinue){\r\n                $AllProfiles = Get-Content -Path \"$($_.Path)\\AppData\\Local\\Google\\Chrome\\User Data\\Local State\" | ConvertFrom-JSON\r\n            }\r\n\r\n            $PreferenceFiles = Get-ChildItem \"$($_.Path)\\AppData\\Local\\Google\\Chrome\\User Data\\*\\Preferences\" -Exclude \"System Profile\" | Select-Object -ExpandProperty Fullname\r\n\r\n            foreach ($PreferenceFile in $PreferenceFiles) {\r\n\r\n                $GooglePreferences = Get-Content -Path $PreferenceFile | ConvertFrom-Json\r\n                if($AllProfiles){\r\n                    $ProfileLocation = $PreferenceFile | Get-Item | Select-Object -ExpandProperty Directory | Split-Path -Leaf\r\n                    $ProfileName = $AllProfiles.profile.info_cache | Select-Object -ExpandProperty $ProfileLocation | Select-Object -ExpandProperty Name\r\n                }else{\r\n                    $ProfileName = $GooglePreferences.profile.name\r\n                }\r\n\r\n                foreach ($Extension in $GooglePreferences.extensions.settings.PSObject.Properties) {\r\n                    $BrowserExtensions.Add(\r\n                        [PSCustomObject]@{\r\n                            Browser        = \"Chrome\"\r\n                            User           = $_.UserName\r\n                            Profile        = $ProfileName\r\n                            Name           = $Extension.Value.manifest.name\r\n                            \"Extension ID\" = $Extension.name\r\n                            Description    = $Extension.Value.manifest.description\r\n                        }\r\n                    )\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    # If Edge was found, search for Edge extensions in each user's profile\r\n    if ($EdgeInstallations) {\r\n        Write-Host -Object \"A Microsoft Edge installation was detected. Searching Microsoft Edge for browser extensions...\"\r\n        $UserProfiles | ForEach-Object {\r\n            if (!(Test-Path -Path \"$($_.Path)\\AppData\\Local\\Microsoft\\Edge\\User Data\" -ErrorAction SilentlyContinue)) {\r\n                return\r\n            }\r\n\r\n            if(Test-Path -Path \"$($_.Path)\\AppData\\Local\\Microsoft\\Edge\\User Data\\Local State\" -ErrorAction SilentlyContinue){\r\n                $AllProfiles = Get-Content -Path \"$($_.Path)\\AppData\\Local\\Microsoft\\Edge\\User Data\\Local State\" | ConvertFrom-JSON\r\n            }\r\n\r\n            $PreferenceFiles = Get-ChildItem \"$($_.Path)\\AppData\\Local\\Microsoft\\Edge\\User Data\\*\\Preferences\" -Exclude \"System Profile\" | Select-Object -ExpandProperty Fullname\r\n\r\n            foreach ($PreferenceFile in $PreferenceFiles) {\r\n\r\n                $EdgePreferences = Get-Content -Path $PreferenceFile | ConvertFrom-Json\r\n                if($AllProfiles){\r\n                    $ProfileLocation = $PreferenceFile | Get-Item | Select-Object -ExpandProperty Directory | Split-Path -Leaf\r\n                    $ProfileName = $AllProfiles.profile.info_cache | Select-Object -ExpandProperty $ProfileLocation | Select-Object -ExpandProperty Name\r\n                }else{\r\n                    $ProfileName = $EdgePreferences.profile.name\r\n                }\r\n\r\n                foreach ($Extension in $EdgePreferences.extensions.settings.PSObject.Properties) {\r\n                    if ($Extension.Value.active_bit -like \"False\" ) { continue }\r\n                    if (!$Extension.Value.manifest.name) { continue }\r\n                    $BrowserExtensions.Add(\r\n                        [PSCustomObject]@{\r\n                            Browser        = \"Edge\"\r\n                            User           = $_.UserName\r\n                            Profile        = $ProfileName\r\n                            Name           = $Extension.Value.manifest.name\r\n                            \"Extension ID\" = $Extension.name\r\n                            Description    = $Extension.Value.manifest.description\r\n                        }\r\n                    )\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    # If Firefox was found, search for Firefox extensions in each user's profile\r\n    if ($FireFoxInstallations) {\r\n        Write-Host -Object \"A Firefox installation was detected. Searching Firefox for browser extensions...\" \r\n        $UserProfiles | ForEach-Object {\r\n            if (!(Test-Path -Path \"$($_.Path)\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\" -ErrorAction SilentlyContinue)) {\r\n                return\r\n            }\r\n\r\n            $FirefoxProfileFolders = Get-ChildItem -Path \"$($_.Path)\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\" -Directory | Where-Object { $_.Name -match \"\\.default-release$\" } | Select-Object -ExpandProperty Fullname\r\n\r\n            foreach ( $FirefoxProfile in $FirefoxProfileFolders ) {\r\n\r\n                if (!(Test-Path -Path \"$FirefoxProfile\\extensions.json\")) {\r\n                    continue\r\n                }\r\n\r\n                $Extensions = Get-Content -Path \"$FirefoxProfile\\extensions.json\" | ConvertFrom-Json\r\n\r\n                foreach ($Extension in $Extensions.addons) {\r\n                    $BrowserExtensions.Add(\r\n                        [PSCustomObject]@{\r\n                            Browser        = \"Firefox\"\r\n                            User           = $_.UserName\r\n                            Profile        = \"N\/A\"\r\n                            Name           = $Extension.defaultlocale.name\r\n                            \"Extension ID\" = $Extension.id\r\n                            Description    = $Extension.defaultlocale.description\r\n                        }\r\n                    )\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    # Check if there are any browser extensions to process\r\n    if ($BrowserExtensions.Count -gt 0) {\r\n        # Format the BrowserExtensions list to include a shortened description if the description is too long.\r\n        $BrowserExtensions = $BrowserExtensions | Select-Object Browser, User, Profile, Name, \"Extension ID\", @{\r\n            Name       = \"Description\"\r\n            Expression = {\r\n                $Characters = $_.Description | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n                if ($Characters -gt 75) {\r\n                    \"$(($_.Description).SubString(0,75))(...)\"\r\n                }\r\n                else {\r\n                    $_.Description\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    # Check if extensions were found and if we were requested to set a multiline custom field\r\n    if ($BrowserExtensions.Count -gt 0 -and $MultilineCustomField) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$MultilineCustomField'.\"\r\n            $CustomFieldValue = New-Object System.Collections.Generic.List[string]\r\n\r\n            # Sort and format the list of extensions for output\r\n            $CustomFieldList = $BrowserExtensions | Sort-Object Browser, User, Profile, Name | Select-Object Browser, User, Profile, Name, \"Extension ID\", Description\r\n            $CustomFieldValue.Add(($CustomFieldList | Format-List | Out-String))\r\n\r\n            # Measure the total character count of the formatted string\r\n            $Characters = $CustomFieldValue | Out-String | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n            if ($Characters -ge 9500) {\r\n                Write-Warning \"10,000 Character Limit has been reached! Trimming output until the character limit is satisfied...\"\r\n                    \r\n                # If it doesn't comply with the limits we'll need to recreate it with some adjustments.\r\n                $i = 0\r\n                do {\r\n                    # Recreate the custom field output starting with a warning that we truncated the output.\r\n                    $CustomFieldValue = New-Object System.Collections.Generic.List[string]\r\n                    $CustomFieldValue.Add(\"This info has been truncated to accommodate the 10,000 character limit.\")\r\n                    \r\n                    # Flip the array so that the last entry is on top.\r\n                    [array]::Reverse($CustomFieldList)\r\n    \r\n                    # Remove the next item.\r\n                    $CustomFieldList[$i] = $null\r\n                    $i++\r\n    \r\n                    # We'll flip the array back to right side up.\r\n                    [array]::Reverse($CustomFieldList)\r\n    \r\n                    # Add it back to the output.\r\n                    $CustomFieldValue.Add(($CustomFieldList | Format-List | Out-String))\r\n    \r\n                    # Check that we now comply with the character limit. If not restart the do loop.\r\n                    $Characters = $CustomFieldValue | Out-String | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n                }while ($Characters -ge 9500)\r\n            }\r\n\r\n            Set-NinjaProperty -Name $MultilineCustomField -Value $CustomFieldValue\r\n            Write-Host \"Successfully set Custom Field '$MultilineCustomField'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Exception.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    # Check if extensions were found and if we were requested to set a WYSIWYG custom field.\r\n    if ($BrowserExtensions.Count -gt 0 -and $WysiwygCustomField) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$WysiwygCustomField'.\"\r\n    \r\n            # Prepare the custom field output.\r\n            $CustomFieldValue = New-Object System.Collections.Generic.List[string]\r\n    \r\n            # Convert the matching events into an html report.\r\n            $htmlTable = $BrowserExtensions | Sort-Object Browser, User, Profile, Name | Select-Object Browser, User, Profile, Name, \"Extension ID\", Description | ConvertTo-Html -Fragment\r\n    \r\n            # Add the newly created html into the custom field output.\r\n            $CustomFieldValue.Add($htmlTable)\r\n    \r\n            # Check that the output complies with the hard character limits.\r\n            $Characters = $CustomFieldValue | Out-String | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n            if ($Characters -ge 199500) {\r\n                Write-Warning \"200,000 Character Limit has been reached! Trimming output until the character limit is satisfied...\"\r\n                    \r\n                # If it doesn't comply with the limits we'll need to recreate it with some adjustments.\r\n                $i = 0\r\n                do {\r\n                    # Recreate the custom field output starting with a warning that we truncated the output.\r\n                    $CustomFieldValue = New-Object System.Collections.Generic.List[string]\r\n                    $CustomFieldValue.Add(\"&lt;h1&gt;This info has been truncated to accommodate the 200,000 character limit.&lt;\/h1&gt;\")\r\n    \r\n                    # Flip the array so that the last entry is on top.\r\n                    [array]::Reverse($htmlTable)\r\n                    # If the next entry is a row we'll delete it.\r\n                    if ($htmlTable[$i] -match '&lt;tr&gt;&lt;td&gt;' -or $htmlTable[$i] -match '&lt;tr class=') {\r\n                        $htmlTable[$i] = $null\r\n                    }\r\n                    $i++\r\n                    # We'll flip the array back to right side up.\r\n                    [array]::Reverse($htmlTable)\r\n    \r\n                    # Add it back to the output.\r\n                    $CustomFieldValue.Add($htmlTable)\r\n    \r\n                    # Check that we now comply with the character limit. If not restart the do loop.\r\n                    $Characters = $CustomFieldValue | Out-String | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n                }while ($Characters -ge 199500)\r\n            }\r\n    \r\n            # Set the custom field.\r\n            Set-NinjaProperty -Name $WysiwygCustomField -Value $CustomFieldValue\r\n            Write-Host \"Successfully set Custom Field '$WysiwygCustomField'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Exception.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    if ($BrowserExtensions.Count -gt 0) {\r\n        Write-Host \"Browser extensions were detected.\"\r\n        $BrowserExtensions | Sort-Object Browser, User, Profile, Name | Format-List | Out-String | Write-Host\r\n    }\r\n    else {\r\n        Write-Host \"No browser extensions were found!\"\r\n    }\r\n\r\n    exit $ExitCode\r\n}\r\nend {\r\n    \r\n    \r\n    \r\n}<\/pre>\n<p>&nbsp;<\/p>\n\n<div class=\"blog-cta-new blog-cta-style-1\"><div class=\"cta-left\"><h2><\/h2><p><\/p><\/div><div class=\"cta-right\"><a class=\"button\" href=\"\"><\/a><\/div><\/div>\n<h2>An\u00e1lisis detallado<\/h2>\n<p>Este script para listar las extensiones del navegador en Windows est\u00e1 escrito en PowerShell y requiere la versi\u00f3n 5.1 o superior. Aqu\u00ed tienes un desglose paso a paso de c\u00f3mo funciona:<\/p>\n<h3>1. Inicializaci\u00f3n y par\u00e1metros<\/h3>\n<ul>\n<li>El script para listar las extensiones del navegador en Windows comienza comprobando los par\u00e1metros requeridos, $MultilineCustomField y $WysiwygCustomField, que pueden establecerse mediante variables de entorno o pasarse directamente.<\/li>\n<li>Valida que estos campos, si ambos se proporcionan, no sean iguales para evitar conflictos.<\/li>\n<\/ul>\n<h3>2. Recuperaci\u00f3n de colmenas de usuarios<\/h3>\n<ul>\n<li>La funci\u00f3n Get-UserHives identifica los perfiles de usuario en el sistema, incluidas las cuentas AzureAD y Domain.<\/li>\n<li>Esta funci\u00f3n es crucial para asegurar que el script escanea todos los directorios de usuario relevantes para los datos del navegador.<\/li>\n<\/ul>\n<h3>3. Comprobaci\u00f3n de permisos<\/h3>\n<ul>\n<li>La funci\u00f3n Test-IsElevated garantiza que el script se ejecuta con privilegios administrativos, necesarios para acceder a archivos comprimidos y directorios del registro espec\u00edficos del usuario.<\/li>\n<\/ul>\n<h3>4. Detecci\u00f3n del navegador<\/h3>\n<ul>\n<li>El script busca instalaciones de Chrome, Firefox y Edge mediante la funci\u00f3n Find-InstallKey, que analiza tanto las claves de registro de todo el sistema como las espec\u00edficas del usuario.<\/li>\n<\/ul>\n<h3>5. Carga del perfil<\/h3>\n<ul>\n<li>Para cada navegador detectado, el script itera a trav\u00e9s de los perfiles de usuario, carga las colmenas de registro necesarias y busca los datos de extensi\u00f3n del navegador.<\/li>\n<li>Esto implica comprobar directorios espec\u00edficos y archivos de configuraci\u00f3n donde los navegadores almacenan informaci\u00f3n sobre extensiones del navegador.<\/li>\n<\/ul>\n<h3>6. Recogida de datos<\/h3>\n<ul>\n<li>Recopila una lista de las extensiones instaladas, incluyendo detalles como nombre del navegador, usuario, perfil, nombre de la extensi\u00f3n, ID y descripci\u00f3n.<\/li>\n<\/ul>\n<h3>7. Actualizaciones de campos personalizados<\/h3>\n<ul>\n<li>Si se encuentran extensiones, el script intenta establecer campos personalizados en un sistema de documentaci\u00f3n utilizando Set-NinjaProperty. Gestiona los posibles l\u00edmites de caracteres recortando la salida seg\u00fan sea necesario.<\/li>\n<\/ul>\n<h3>8. Output:<\/h3>\n<ul>\n<li>El resultado final es una lista ordenada de las extensiones del navegador, que puede mostrarse o almacenarse en campos personalizados para su posterior an\u00e1lisis.<\/li>\n<\/ul>\n<h2>Posibles casos de uso<\/h2>\n<p>Imagina a un profesional de TI que gestiona la infraestructura inform\u00e1tica de una empresa mediana. Debe asegurarse de que todas las extensiones del navegador instaladas en los equipos de los usuarios cumplen las pol\u00edticas de la empresa. Ejecutando este script, puede inventariar r\u00e1pidamente todas las extensiones en Chrome, Firefox y Edge, identificar cualquier extensi\u00f3n no autorizada o de riesgo y tomar medidas correctivas.<\/p>\n<p>Por ejemplo, si una nueva pol\u00edtica proh\u00edbe extensiones que no han sido examinadas por el departamento de TI, este script permite al administrador de TI generar una lista completa de las extensiones actuales. A continuaci\u00f3n, el administrador puede cotejar esta lista con las extensiones del navegador aprobadas y eliminar a distancia las que supongan un riesgo.<\/p>\n<h2>Comparaciones<\/h2>\n<p>En comparaci\u00f3n con los m\u00e9todos manuales de comprobaci\u00f3n individual de cada navegador y perfil de usuario, este script es significativamente m\u00e1s eficaz y exhaustivo. Otros enfoques podr\u00edan implicar el uso de herramientas espec\u00edficas del navegador o la inspecci\u00f3n manual, ambos m\u00e9todos requieren mucho tiempo y son propensos a errores humanos. Este script automatiza el proceso, garantizando la coherencia y ahorrando un tiempo valioso.<\/p>\n<h2>FAQ<\/h2>\n<h3>P: \u00bfEste script se puede ejecutar a distancia?<\/h3>\n<p>R: S\u00ed, siempre que tengas los permisos administrativos necesarios y acceso a las m\u00e1quinas remotas.<\/p>\n<h3>P: \u00bfQu\u00e9 ocurre si la descripci\u00f3n de una extensi\u00f3n supera el l\u00edmite de caracteres?<\/h3>\n<p>R: El script recorta la descripci\u00f3n para ajustarla al l\u00edmite de caracteres, garantizando que la salida siga siendo manejable.<\/p>\n<h3>P: \u00bfEl script funciona en todas las versiones de Windows?<\/h3>\n<p>R: El script requiere Windows 10 o Windows Server 2016 y posteriores, ya que depende de funciones disponibles en estas versiones.<\/p>\n<h3>P: \u00bfSe puede modificar el script para que sea compatible con otros navegadores?<\/h3>\n<p>R: S\u00ed, con las modificaciones adecuadas en la l\u00f3gica de detecci\u00f3n y recopilaci\u00f3n de datos, se puede a\u00f1adir compatibilidad con navegadores adicionales.<\/p>\n<h2>Implicaciones<\/h2>\n<p>Los resultados de este script para listar las extensiones del navegador en Windows pueden tener importantes implicaciones para la seguridad inform\u00e1tica. Al identificar todas las extensiones del navegador instaladas, los profesionales de TI pueden detectar posibles riesgos para la seguridad y garantizar el cumplimiento de las pol\u00edticas de la organizaci\u00f3n. Este enfoque proactivo ayuda a <a href=\"https:\/\/www.ninjaone.com\/es\/blog\/mejores-soluciones-de-proteccion-contra-malware\/\" target=\"_blank\" rel=\"noopener\">mitigar el riesgo de infecciones por malware<\/a> y violaciones de datos asociadas a extensiones maliciosas o mal mantenidas.<\/p>\n<h2>Recomendaciones<\/h2>\n<p>Cuando utilices este script para listar las extensiones del navegador en Windows, ten en cuenta las siguientes pr\u00e1cticas recomendadas:<\/p>\n<ul>\n<li>Ejecuta el script regularmente como parte de tu programa de mantenimiento inform\u00e1tico.<\/li>\n<li>Revisa la lista de extensiones del navegador detectadas y comp\u00e1ralas con tu lista de extensiones del navegador aprobada.<\/li>\n<li>Conciencia a los usuarios sobre los riesgos asociados a las extensiones del navegador y an\u00edmalos a instalar s\u00f3lo extensiones aprobadas.<\/li>\n<\/ul>\n<h2>Reflexiones finales<\/h2>\n<p>La gesti\u00f3n de las extensiones del navegador es un aspecto cr\u00edtico del mantenimiento de la seguridad inform\u00e1tica. Este script proporciona una forma automatizada y <a href=\"https:\/\/www.ninjaone.com\/es\/eficiencia\" target=\"_blank\" rel=\"noopener\">eficaz<\/a> de inventariar y supervisar las extensiones del navegador en varios usuarios y navegadores. Al integrar esta herramienta en sus procesos de gesti\u00f3n de TI, puedes mejorar la postura de seguridad de tu organizaci\u00f3n y garantizar el cumplimiento de las pol\u00edticas.<\/p>\n<p><a href=\"https:\/\/www.ninjaone.com\/es\/\" target=\"_blank\" rel=\"noopener\">NinjaOne<\/a> ofrece una serie de herramientas y funciones que complementan este script, proporcionando una soluci\u00f3n integral para la gesti\u00f3n y la seguridad de TI. Con NinjaOne, puedes automatizar las tareas rutinarias, supervisar los endpoints y garantizar que tu entorno de TI sea seguro y cumpla las normativas.<\/p>\n","protected":false},"author":35,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"","_lmt_disable":""},"operating_system":[4212],"use_cases":[4264,4263],"class_list":["post-353773","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows","use_cases-seguridad-de-redes","use_cases-supervision"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub\/353773","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/comments?post=353773"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/media?parent=353773"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/operating_system?post=353773"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/use_cases?post=353773"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}