Securing the Java plug-in in Internet Explorer

The recent epic vulnerabilities in the Oracle Java Runtime Environment (JRE) 1.7 and how fast malware authors integrate exploits code into their kits confirm and highlight that Java is for sure the most popular attack vector used by malware authors.
I won’t expose the timeline of the recent vulnerabilities but I’ll instead provide some more fundamental readings that help understand why Java is the favorite target of malware authors:

In my opinion, we have now reach the point where just ‘keeping the JRE up-to-date’ isn’t enough anymore. Of course keeping software up-to-date is a good practice and still strongly required.
But not having a JRE currently installed is somehow more secure than just having the latest installed without a hardened configuration.
So, I’ll try to show and discuss the various ways to secure it for those who just can’t unplug it from the network as they have LOB applications running on Java in their coroporate environment.

  • Either keep it up-to-date or uninstall it
  • I’ll quote Brian Krebs who says (source) :

    If you don’t need Java, get rid of it

    If you really need to have Java, the download page is http://www.oracle.com/technetwork/java/javase/downloads/index.html

    You can use the Get-MSIZapInfo function I’ve provided in this post to find out all the JRE installed on a computer, list their version and their uninstall command

    Invoke-Command -ComputerName RemoteComputer -FilePath .\Get-MSIzap.ps1 |             
      Where-Object  {$_.Displayname -match "Java" } |             
      Select-Object -Property Displayname,UninstallString

    For each UninstallString returned, you can invoke the Windows Installer (msiexec.exe /x or msiexec.exe /uninstall) responsible for uninstalling MSI based piece of software.

  • Only execute digitally signed applets
  • To harden the Java Runtime, you can make it only load digitally signed applets as malicious java applets are probably not signed.
    This won’t be always true. The Flame malware has shown us that certificates can be brute forced. They can also be forged and stolen….
    This may not be the easiest approach as you’ll need to sign corporate applets with a publicly recognised and trusted certificate (you’ve to pay for it) and even some applets provided by Oracle are only self-signed 😦

    To achieve this, you’ll need to modify the following 4 settings:
    JRE digital signature behavior

    I’ve created a deployment.config file under C:\Windows\Sun\Java\Deployment\
    It contains the following 2 lines:

    deployment.system.config=file\:C\:/WINDOWS/Sun/Java/Deployment/deployment.properties
    deployment.system.config.mandatory=true
    

    I’ve created a deployment.properties file under C:\Windows\Sun\Java\Deployment\

    # Allow user to grant permissions to signed content
    # (true by default)
    deployment.security.askgrantdialog.show=true
    deployment.security.askgrantdialog.show.locked
     
    # Allow user to grant permissions to content from an untrusted authority.
    # (true by default)
    deployment.security.askgrantdialog.notinca=false
    deployment.security.askgrantdialog.notinca.locked
    
    # Check publisher certificate for revocation 
    # (false by default)
    deployment.security.validation.crl=true
    deployment.security.validation.crl.locked
    
    # Enable online certificate validation
    # (false by default)
    deployment.security.validation.ocsp=true
    deployment.security.validation.ocsp.locked
    

    I’ve found this configuration on this page.

  • Prevent Java from running in Internet Explorer or partially disable the JRE in the browser (if appropriate)
  • Many actors in the security field first provided a way where you needed to untick the ‘Default for Java for Browsers’
    UseJava2IExplorer

    Function Get-JREinBrowser            
    {            
    [CmdletBinding()]            
    param(            
                
        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]                        
        [Alias("CN","__SERVER","IPAddress")]                        
        [system.string[]]$ComputerName = ".",            
                
        [parameter()]            
        [System.Management.Automation.PSCredential]$Credential            
                    
    )            
    Begin {            
        # Make sure we run as admin                        
        $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()                        
        $IsAdmin = $usercontext.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")                                           
        if (-not($IsAdmin))                        
        {                        
            Write-Warning "Must run powerShell as Administrator to perform these actions"                        
            return                        
        }            
        # Define some registry constants                        
        $HKLM = 2147483650            
        $x86MainKey = 'SOFTWARE\Wow6432Node\JavaSoft\Java Plug-in'            
        $x64MainKey = 'SOFTWARE\JavaSoft\Java Plug-in'            
    }                
    Process {            
        $ComputerName | ForEach-Object -Process {            
            $TargetComputer = $_            
            # Prepare a default HT                        
            $wmiHT = @{                        
                ErrorAction = "Stop";                        
            }                        
            Switch ($TargetComputer)            
            {            
                {$_ -eq ($Env:Computername)} {$IsRemoteComputer = $false ; break}            
                {$_ -eq "."}                 {$IsRemoteComputer = $false ; break}            
                {$_ -eq "::1"}               {$IsRemoteComputer = $false ; break}            
                {$_ -eq "127.0.0.1"}         {$IsRemoteComputer = $false ; break}            
                {$_ -eq "localhost"}         {$IsRemoteComputer = $false ; break}            
                default {            
                    $IsRemoteComputer = $true            
                }                        
            }            
            if($IsRemoteComputer)            
            {            
                Write-Verbose -Message "Detecting $TargetComputer as a remote computer"            
                $wmiHT += @{             
                    Authentication = 6;            
                    Impersonation  = 3;            
                    Computername   = $TargetComputer;            
                }            
                if ($Credential)            
                {            
                    $wmiHT += @{ Credential = $Credential }            
                }            
                            
            } else {            
                Write-Verbose -Message "Detecting $TargetComputer as a local computer"            
            }            
                        
            # Enumerate            
            $x64MainKey,$x86MainKey | ForEach-Object -Process {            
                $Key = $_            
                try            
                {            
                    Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name EnumKey -ArgumentList $HKLM,$Key @wmiHT            
                } catch {            
                    Write-Warning -Message "Failed to query WMI on $TargetComputer because $($_.Exception.Message)"            
                }            
            }  | ForEach-Object -Process {            
                if ($_.ReturnValue -eq 0)            
                {            
                    # The key exists            
                    $_.sNames | ForEach-Object -Process {            
                        $Version = $_            
                        $Key = "$Key\$Version"            
                        Write-Verbose -Message "Attempting to get version under $Key on $TargetComputer"            
                                    
                        try {            
                            Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name GetDWORDValue -ArgumentList $HKLM,$Key,"UseJava2IExplorer" @wmiHT             
                        } catch {            
                            Write-Warning -Message "Failed to get the browser flag for $Verion under $Key on $TargetComputer because $($_.Exception.Message)"            
                        }            
                    } | ForEach-Object -Process {            
                        $result = $_.ReturnValue            
                        $value  = $_.uValue            
                        Switch ($result)            
                        {            
                            0 {            
                                switch ($value)            
                                {            
                                    0 {            
                                        New-Object -TypeName PSObject -Property @{            
                                            Version = $Version            
                                            Key = $Key            
                                            ComputerName = $TargetComputer            
                                            Status = 'Disabled'            
                                        }            
                                    }            
                                    1 {            
                                        New-Object -TypeName PSObject -Property @{            
                                            Version = $Version            
                                            Key = $Key            
                                            ComputerName = $TargetComputer            
                                            Status = 'Enabled'            
                                        }            
                                    }            
                                    default {            
                                        New-Object -TypeName PSObject -Property @{            
                                            Version = $Version            
                                            Key = $Key            
                                            ComputerName = $TargetComputer            
                                            Status = 'Unknown'            
                                        }            
                                    }            
                                }            
                            }            
                            2 {            
                                Write-Warning -Message "DWORD value UseJava2IExplorer doesn't exist under $Key on $TargetComputer"            
                            }            
                            default {            
                                Write-Warning -Message "Querying DWORD value UseJava2IExplorer under $Key on $TargetComputer returned $result"            
                            }            
                        }            
                    }            
                } elseif ($_.ReturnValue -eq 2) {            
                    # The key doesn't exist            
                    Write-Warning -Message "$Key not found on $TargetComputer"            
                } else {            
                    Write-Warning -Message "Quering $Key on $TargetComputer returned $($_.ReturnValue)"            
                }            
            }            
        }                      
    }            
    End {}            
    }            
                
    Function Set-JREinBrowser            
    {            
    [CmdletBinding()]            
    param(            
                
        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]                        
        [Alias("CN","__SERVER","IPAddress")]                        
        [system.string[]]$ComputerName = ".",            
                
        [parameter()]            
        [System.Management.Automation.PSCredential]$Credential,            
                    
        [parameter(ParameterSetName="Enable")]            
        [switch]$Enable=$false,            
                    
        [parameter(ParameterSetName='Disable')]            
        [switch]$Disable=$false                
                
    )            
    Begin {            
                
        switch ($PsCmdlet.ParameterSetName)            
        {            
            Enable {            
                if ($Enable) { $Action = 'Enable' ; break}            
            }            
            Disable {            
                if ($Disable) { $Action = 'Disable' ; break}            
            }            
            default {             
                # We will never get here because if both parametersets/switch are specified or missing            
                # it will throw an error saying: 'Parameter set cannot be resolved using the specified named parameters.'            
            }            
        }            
        # Make sure we run as admin                        
        $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()                        
        $IsAdmin = $usercontext.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")                                           
        if (-not($IsAdmin))                        
        {                        
            Write-Warning "Must run powerShell as Administrator to perform these actions"                        
            return                        
        }            
        # Define some registry constants                        
        $HKLM = 2147483650            
        $x86MainKey = 'SOFTWARE\Wow6432Node\JavaSoft\Java Plug-in'            
        $x64MainKey = 'SOFTWARE\JavaSoft\Java Plug-in'            
    }                
    Process {            
        $ComputerName | ForEach-Object -Process {            
            $TargetComputer = $_            
            # Prepare a default HT                        
            $wmiHT = @{                        
                ErrorAction = "Stop";                        
            }                        
            Switch ($TargetComputer)            
            {            
                {$_ -eq ($Env:Computername)} {$IsRemoteComputer = $false ; break}            
                {$_ -eq "."}                 {$IsRemoteComputer = $false ; break}            
                {$_ -eq "::1"}               {$IsRemoteComputer = $false ; break}            
                {$_ -eq "127.0.0.1"}         {$IsRemoteComputer = $false ; break}            
                {$_ -eq "localhost"}         {$IsRemoteComputer = $false ; break}            
                default {            
                    $IsRemoteComputer = $true            
                    Write-Verbose -Message "Computer is a remote target" -Verbose            
                }                        
            }            
            if($IsRemoteComputer)            
            {            
                Write-Verbose -Message "Detecting $TargetComputer as a remote computer"            
                $wmiHT += @{             
                    Authentication = 6;            
                    Impersonation  = 3;            
                    Computername   = $TargetComputer;            
                }            
                if ($Credential)            
                {            
                    $wmiHT += @{ Credential = $Credential }            
                }            
            } else {            
                Write-Verbose -Message "Detecting $TargetComputer as a local computer"            
            }            
                        
            # Enumerate            
            $x64MainKey,$x86MainKey | ForEach-Object -Process {            
                $Key = $_            
                try            
                {            
                    Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name EnumKey -ArgumentList $HKLM,$Key @wmiHT            
                } catch {            
                    Write-Warning -Message "Failed to query WMI on $TargetComputer because $($_.Exception.Message)"            
                }            
            }  | ForEach-Object -Process {            
                if ($_.ReturnValue -eq 0)            
                {            
                    # The key exists            
                    $_.sNames | ForEach-Object -Process {            
                        $Version = $_            
                        $Key = "$Key\$Version"            
                        Write-Verbose "Attempting to change values under $Key on $TargetComputer"            
                        Switch ($Action)            
                        {            
                            Enable { $Value = [int32]1}            
                            Disable { $Value = [int32]0}            
                            default {}            
                        }            
                        Write-Verbose -Message "Action is $action so value to set is $Value"            
                        try {            
                            $result = Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name SetDWORDValue -ArgumentList $HKLM,$Key,"UseJava2IExplorer",$Value @wmiHT            
                        } catch {            
                            Write-Warning -Message "Failed to set $Value on valuename UseJava2IExplorer under $Key on $TargetComputer"            
                        }                                  
                        if ($result)            
                        {            
                            if ($result.ReturnValue -eq 0)            
                            {            
                                    'Successfully changed Java RunTime browser integration on {0}' -f $TargetComputer            
                            } else {            
                                    'Failed to change Java RunTime browser integration on {0}' -f $TargetComputer            
                                    'Returned value was {0}' -f ($result.ReturnValue)            
                            }            
                
                        } else {            
                            Write-Warning -Message "Failed"            
                        }            
                    }            
                } elseif ($_.ReturnValue -eq 2) {            
                    # The key doesn't exist            
                    Write-Warning -Message "$Key not found on $TargetComputer"                            
                } else {            
                    Write-Warning -Message "Quering $Key on $TargetComputer returned $($_.ReturnValue)"            
                }            
            }            
        }                      
    }            
    End {}            
    }

    Here’s how to use the 2 above functions

    $cred = (Get-Credential)            
    "RemotePC" | Get-JREinBrowser -Credential $cred -Verbose            
    "RemotePC" | Set-JREinBrowser -Enable -Verbose -Credential $cred            
    "RemotePC" | Set-JREinBrowser -Disable -Verbose -Credential $cred            
    

    However the above step wasn’t enough as there are various ways of invoking Java inside Internet Explorer.

    Microsoft provided the recommended guidance on how to disable the Java web plug-in in Internet Explorer

    Java is a unique form of extensibility because it can be invoked in two ways:
    By using an applet element
    By using an object element that has a CLSID of a Java Virtual Machine (JVM)
    These two invocation methods are subject to different security controls.

    The first step consists in disabling Applets by setting the Java permissions to ‘Disable’

    URL action flag name: URLACTION_JAVA_PERMISSIONS
    Security setting UI : Java permissions (not visible by default in the UI)
    Numeric name : 1C00
    Possible values are:
    “High safety”=0x00010000
    “Medium safety”=0x00020000
    “Low safety”=0x00030000
    “Custom”=0x00800000
    “Disable Java”=0x00000000

    Microsoft recommends to set it to 0x0 on the Internet zone (#3)

    To understand security zones and from where the URLACTION_JAVA_PERMISSIONS flag (1C00) is being read and applied, I recommend to read the following 2 pages:

    Setting it on the CurrentUser hive (HKCU) can be a non sense if you’re in a corporate environment and already use Group policy to control zone templates and settings.

    The second step consists in setting the kill-bit on Java Plug-in CLSIDs to block OBJECT tag invocation.

    Before setting kill-bits I recommend reviewing the following setting, especially in the Internet zone (3) as the following KB article states that:

    after the kill bit is set for an ActiveX control, that control is not called by Internet Explorer at all unless the Initialize and script ActiveX controls not marked as safe option is enabled in Internet Explorer.

    URL action flag name: URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY
    Security setting UI : Initialize and script ActiveX controls not marked as safe
    Numeric name : 1201
    Possible values:
    “Enable”=0x00000000
    “Disable”=0x00000003
    “Prompt”=0x00000001

    Note that the URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY flag is disabled(0x3) in the Internet zone. This prevents bypassing killbits. So, Killbits set are actually enforced in the Internet zone.

    Then we need to identify all the CLSIDs related to the Java Plug-in, so we do:

    (Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Classes\CLSID -Recurse) | ForEach-Object -Process {            
        if ($_.PSIsContainer -and ($_.PSChildName -match [regex]'(?^\{[A-Za-z0-9]{8}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{12}\})'))            
        {            
            try            
            {            
                (Get-ItemProperty $_.PSPath -Name '(default)' -ErrorAction Stop)            
            } catch {            
            }            
        }            
    } | ForEach-Object -Process {            
        if ($_.'(default)' -match "Java Plug-in")            
        {            
            $_            
        }            
    } | Format-Table -AutoSize -Wrap -Property @{l='CLSID';e={$_.PSChildName}},@{l='DisplayName';e={$_.'(default)'}}

    We end up with the following long list…
    All JRE CLSID

    I’ve also written 3 helper functions to get, set or clear the kill-bit on a specific set of CLSIDs

    Function Get-KillBit             
    {            
    [CmdletBinding()]            
    param(            
    # By GUID            
    [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]                        
    [string[]]$GUID            
    )            
    Begin{            
        $x86='Software\Wow6432Node'            
        $x64='Software'            
    }            
    Process{            
        $GUID | ForEach-Object -Process {            
            $GUIDitem = $_            
            Write-Verbose "Testing GUID $GUIDitem"            
            $x86,$x64 | ForEach-Object {            
                Write-Verbose "Testing Hive $_"            
                $HiveLocation = $_            
                $flag = $null            
                try {            
                    $flag = Get-ItemProperty -Path "HKLM:\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem" -Name 'Compatibility Flags' -ErrorAction Stop            
                } catch {            
                    Write-Warning "Failed because $($_.Exception.Message)"            
                    return            
                }            
                New-Object -TypeName PSobject -Property @{            
                    GUID = $GUIDitem            
                    Path = $flag.PSPath            
                    Value = $flag.'Compatibility Flags'            
                    HexValue = -join ('0x',('{0:X0}' -f $flag.'Compatibility Flags'))            
                    DisplayName = (Get-ItemProperty -Path "HKLM:\$HiveLocation\Classes\CLSID\$GUIDitem" -Name '(default)' -ErrorAction Silentlycontinue).'(default)'            
                }            
            }            
        }            
    }            
    End{}            
    }            
                
    Function Set-KillBit             
    {            
    [CmdletBinding()]            
    param(            
    # By GUID            
    [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]                        
    [string[]]$GUID=$null            
    )            
    Begin{            
        # Make sure we run as admin                        
        $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()                        
        $IsAdmin = $usercontext.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")                                           
        if (-not($IsAdmin))                        
        {                        
            Write-Warning "Must run powerShell as Administrator to perform these actions"                        
            return                        
        }            
        $x86='Software\Wow6432Node'            
        $x64='Software'            
    }            
    Process{            
        $GUID | ForEach-Object -Process {            
            $GUIDitem = $_            
            Write-Verbose "Handling GUID $GUIDitem"            
            $x86,$x64 | ForEach-Object {            
                Write-Verbose "Setting it in hive $_"            
                $HiveLocation = $_            
                $flagged = $null            
                try {            
                                
                    if (-not(Test-Path "HKLM:\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem"))            
                    {            
                        New-Item -Path "HKLM:\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility" -Name $GUIDitem -Force -ErrorAction Stop | Out-Null            
                        New-ItemProperty -Path "HKLM:\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem" -PropertyType DWORD -Name 'Compatibility Flags' -Value 1024 -Force | Out-Null            
                    } else {            
                        Set-ItemProperty -Path "HKLM:\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem" -Name 'Compatibility Flags' -Value 1024 -Type DWORD -Force -ErrorAction Stop            
                    }            
                    $flagged = $true            
                } catch {            
                    $flagged = $false            
                    Write-Warning "Failed because $($_.Exception.Message)"            
                }            
                if ($flagged)            
                {            
                    Write-Verbose -Message "Successfully set kill-bit on $GUIDitem in hive $HiveLocation"            
                } else {            
                    Write-Verbose -Message "Failed to set kill-bit on $GUIDitem in hive $HiveLocation"            
                }            
            }            
        }            
    }            
    End{}            
    }            
                
    Function Clear-KillBit             
    {            
    [CmdletBinding()]            
    param(            
    # By GUID            
    [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]                        
    [string[]]$GUID=$null            
    )            
    Begin{            
        # Make sure we run as admin                        
        $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()                        
        $IsAdmin = $usercontext.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")                                           
        if (-not($IsAdmin))                        
        {                        
            Write-Warning "Must run powerShell as Administrator to perform these actions"                        
            return                        
        }            
        $x86='Software\Wow6432Node'            
        $x64='Software'            
    }            
    Process{            
        $GUID | ForEach-Object -Process {            
            $GUIDitem = $_            
            Write-Verbose "Handling GUID $GUIDitem"            
            $x86,$x64 | ForEach-Object {            
                Write-Verbose "Setting it in hive $_"            
                $HiveLocation = $_            
                $flagged = $null            
                try {            
                    if (Test-Path "HKLM:\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem")            
                    {            
                        Remove-Item -Path "HKLM:\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem" -Force -ErrorAction Stop | Out-Null            
                    } else {            
                        # already removed            
                    }            
                    $flagged = $true            
                } catch {            
                    $flagged = $false            
                    Write-Warning "Failed because $($_.Exception.Message)"            
                }            
                if ($flagged)            
                {            
                    Write-Verbose -Message "Successfully cleared kill-bit on $GUIDitem in hive $HiveLocation"            
                } else {            
                    Write-Verbose -Message "Failed to clear kill-bit on $GUIDitem in hive $HiveLocation"            
                }            
            }            
        }            
    }            
    End{}            
    }            
    

    To use the above functions, you can for example do:

                
    #            
    # Set the kill-bit on any Java related CLSID            
    #            
                
    (Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Classes\CLSID -Recurse) | ForEach-Object -Process {            
        if ($_.PSIsContainer -and ($_.PSChildName -match [regex]'(?^\{[A-Za-z0-9]{8}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{12}\})'))            
        {            
            try            
            {            
                (Get-ItemProperty $_.PSPath -Name '(default)' -ErrorAction Stop)            
            } catch {            
            }            
        }            
    } | ForEach-Object -Process {            
        if ($_.'(default)' -match "Java Plug-in")            
        {            
            $_            
        }            
    } | ForEach-Object -Process {            
        Set-KillBit -GUID $_.PSChildName            
    }             
                
    #            
    # Get all the kill-bits set            
    #            
                
    (Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Classes\CLSID -Recurse) | Where-Object {            
        $_.PSIsContainer -and ($_.PSChildName -match [regex]'(?^\{[A-Za-z0-9]{8}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{4}\-[A-Za-z0-9]{12}\})')            
    } | ForEach-Object -Process {                
            try {            
                (Get-ItemProperty $_.PSPath -Name '(default)' -ErrorAction Stop)            
            } catch {}            
    } | Where-Object  {($_.'(default)' -match "Java Plug-in")} | ForEach-Object -Process {            
         Get-KillBit -GUID $_.PSChildName            
    }  | Sort-Object -Descending -Property GUID | Select-Object -Property GUID,DisplayName,HexValue            
                
    #             
    # Clear some kill-bit on a subset of CLSIDs            
    #             
                
    # Define a array of whitelisted CLSIDs            
    $allowed = "{CAFEEFAC-FFFF-FFFF-FFFF-ABCDEFFEDCBA}",            
    "{CAFEEFAC-0016-0000-0035-ABCDEFFEDCBC}",            
    "{CAFEEFAC-0016-0000-0035-ABCDEFFEDCBB}",            
    "{CAFEEFAC-0016-0000-0035-ABCDEFFEDCBA}",            
    "{8AD9C840-044E-11D1-B3E9-00805F499D93}"            
    # Clear            
    $allowed | Clear-KillBit -Verbose            
    

    In other words, Powershell allows us to dynamically disable all the Java Plug-ins’ CLSIDs present on a computer instead of having (too many) CLSIDs hardcoded in a .reg file.

    Best of all, here are the most comprehensive articles on what can be done in the Internet Explorer configuration to control and harden the Java behavior:

    So, if you want to permit Java to run only in the Intranet and Trusted Sites zones:
    Adjust the URLAction for the Internet Zone to Disable
    Remove the * from the Per-Site list of the ActiveX Control
    Step #1 will ensure that only Intranet Zone and Trusted Zone sites may load Java for APPLET Tags.
    Step #2 will ensure that the Java Plug-in will not load as an OBJECT on Internet Zone sites; a notification will be shown instead.
    Because Intranet and Trusted Sites ignore the Per-Site ActiveX list, you won’t see any additional warnings on those sites.

    I’d like to mention other interesting articles on this subject:

  • Protecting yourself from CVE-2012-4681 Java exploits
  • The Kill-Bit FAQ: Part 1 of 3
  • The Kill-Bit FAQ: Part 2 of 3
  • The Kill-Bit FAQ: Part 3 of 3
  • Managing ActiveX Controls
  • How to stop an ActiveX control from running in Internet Explorer
  • Flags behavior of registered Microsoft ActiveX controls
  • 12 thoughts on “Securing the Java plug-in in Internet Explorer

    1. Pingback: Java CRL Checks einschalten | romgal

    2. Hello! Have you been able to get the “Default for Java for Browsers” option to work in Java 7 so that Java plugin in only valid in IE and not Firefox? It appears that the interface no longer lets you disable just Firefox (it returns as soon as you close out of it). Thanks!

      • Hi,
        Good question. I’ve quickly tested what you’ve asked. I’ve monitored with procmon what happens when you click “enable java content in the browser”

        Bascially when you want to disable it for Firefox, you should just delete any java plugin referenced under the registry key HKLM\SOFTWARE\Wow6432Node\MozillaPlugins

        • Thanks for the quick response!

          Would you recommend simply removing the entire “@java.com” key under “HKLM\SOFTWARE\Wow6432Node\MozillaPlugins”, or would you suggest deleting the actual plugin files “C:\Program Files\Java\jre7\bin\plugin2\npjp2.dll” and “C:\Windows\System32\npdeployJava1.dll” (and the corresponding 32bit references on a 64bit computer)?

          I haven’t tested this yet (I plan to soon), but it appears that Firefox may still be able to load it since the plugins are still in “known” locations as per http://mike.kaply.com/2012/02/16/how-firefox-loads-plugins.

          Also, do you know if removing the registry entries you mentioned earlier will disable Java support from Chrome too?

          Thanks!

        • NP,
          Good catch 🙂

          I’m not a big fan of what Oracle is doing to disable the JRE 7.x in the browsers. Removing registry keys is wrong in my opinion.

          I forgot Mike’s post that is now 1 year old. Mike is very active in the Mozilla Enterprise User Working Group. You can ask questions to the group
          https://wiki.mozilla.org/Enterprise
          http://www.mozilla.org/en-US/firefox/organizations/

          Mike’s post is good (I bookmarked it as a reference) but I cannot tell you if it still applies to recent Firefox releases.
          Many things changed for Firefox since his post. There are new security features being introduced by the Mozilla foundation.
          Here’s an example of the new click-to-play:

          http://support.mozilla.org/en-US/kb/why-do-i-have-click-activate-plugins
          https://blog.mozilla.org/security/2013/01/29/putting-users-in-control-of-plugins/

          Let’s talk about the content of Mike’s article. I’ve taken some notes when I read Mike’s post last year.
          I’ve got a .cfg file in ‘C:\Program Files (x86)\Mozilla Firefox’ that contains the following line:
          lockPref(“plugin.scan.plid.all”, false);
          As he said,

          Firefox will no longer read plugins from the registry HKEY_LOCAL_MACHINE\SOFTWARE\MozillaPlugins

          This will disable all the plugins in the registry except for the reader:

          and all the files that you may find under ‘C:\Program Files (x86)\Mozilla Firefox\plugins’
          You can confirm this by typing: about:plugins in the Mozilla Firefox address bar.

          […]the second way Firefox locates plugins. It uses known paths to find them […]
          These preferences are not booleans, though, they are minimum versions. So if you want to prevent them from being loaded, you can just set the versions very high. I set them all to 100.0.
          lockPref(“plugin.scan.SunJRE”, “100.0”);

          It seems that this is no longer used…per my recent tests.

          I’ve also indentified another issue. Sometimes, it’s not a plugin but an add-on.
          I noted that the content of ‘C:\Program Files (x86)\Java\jre6\lib\deploy\ffjcext.zip’ was extracted to ‘C:\Program Files (x86)\Mozilla Firefox\extensions’
          In this case, there’s a prompt.

          To review the addons, you can type about:addons in the address bar of Firefox.

          The best approach is to test and validate the behavior based on your needs in your environment.
          I would not delete the registry keys and not delete files because it’s a MSI package and that these registry keys and files could be restored by a repair.
          The JRE 6.x installer has some command line switches that allows you to choose what browser to target upon installation.
          http://www.oracle.com/technetwork/java/javase/silent-136552.html
          but the JRE 7.x doesn’t…
          http://docs.oracle.com/javase/7/docs/webnotes/install/windows/jre-installation-windows.html

        • Wow, lot’s of good information, thanks!

          I did unfortunately find that setting (plugin.scan.SunJRE”, “100.0”) no longer works unfortunately (had this worked, that would have been perfect!).

          I will try the Mozilla user group to get information from them.

          Thanks for all of our help – it is definitely appreciated!

    3. I missed a thought: I imagine that Chrome doesn’t use the Mozilla registry references, but I have confirmed that deleting the plugin files does prevent Chrome from loading Java too, i.e. both Firefox and Chrome reference these plugins. So this is why I am considering deleting the actual plugin files. What are your thoughts about this?

      • Sorry, I can’t help you for Chrome.
        Deleting files and registry keys should be considered as a quick and dirty fix.
        For sure, it’s not the best approach but it’s a response in case of emergency.
        The software editor has first to fix his product and has to provide a more reliable solution and a clear guidance. A large audience of corporate administrators in the Microsoft world would expect to control the behaviour through group policies.

    4. Pingback: Hardening Internet Explorer and Java 6 #infosec | ComputerComputerComputer

    Leave a comment

    This site uses Akismet to reduce spam. Learn how your comment data is processed.