You may have already seen this popup when your Oracle Java Runtime (JRE) 1.7 is out-of-date.
Your administrator may have already turned off the first mecanism of update using group policies to prevent update notifications’ balloons to pop out in the system tray.
Guess what! Oracle introduced a 2nd update notification mechanism since version 1.7_10 that phones home to check whether it’s up-to-date or expired.
If it’s unable to phone home, the expiry date is set using an hardcoded value that follows the CPU (Critical Patch Update) lifecycle. 😦
JRE Expiration Date
The JRE relies on periodic checks with an Oracle Server to determine if it (the JRE)is still considered up-to-date with all the available security fixes (above the security baseline). In the past, if the JRE was unable to contact the Oracle Server, it continued to behave as though it is still the most recent version with regard to security, for an indefinite period.
To avoid this problem, a secondary mechanism, that does not rely on external communication, has been added to the JDK 7u10. From this release onwards, all JREs will contain a hard-coded expiration date. The expiration date is calculated to end after the scheduled release of the next Critical Patch Update.
This means that JREs that are unable to contact Oracle Servers for an extended period of time, will now start offering additional protection after a reasonable period, and will not continue to behave as if they were still up-to-date with security fixes.
Sources: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/client-security.html#secure and http://www.oracle.com/technetwork/java/javase/7u10-relnotes-1880995.html
No, you’re not dreaming. We’re in 2013 and software developpers at Oracle launched this security awareness campaign using the above pop-up 😉
The problem with this new feature is that Oracle didn’t provide guidance on how to turn off this notification in a corporate environment.
You can of course click “Later” and tick “don’t ask again until next update” during a certain period of time. This will write some values in the registry and the current user deployment.properties file located in “%userprofile%AppData\LocalLow\Sun\Java\Deployment”. (Note that registry settings take precedence over the deployment.properties file content)
Worse, when the expiry date is reached, the pop-up doesn’t rely anymore on the above registry settings.
They are simply ignored and you start being nagged by this pop-up every time an applet is loaded by the browser.
Here’s what I asked on twitter to Donald Smith who is a member of the Oracle Java SE PM team:
The current situation is that we, I mean corporate administrators, have great hopes and may expect the JRE to really take fully advantages of Group Policies in a close future.
Source: http://www.symantec.com/connect/forums/how-everyone-addressing-forced-java-dialog-java-update-needed-your-java-version-insecure
As you can see, Donald was very kind and answered my questions very quickly.
But, as a corporate administrator, I don’t deploy and manage software with hope.
Now, let’s see how to defeat this new update notification feature.
The idea is simple. I’ll just prevent the DLL file responsible for these notifications from being loaded in Internet Explorer.
To achieve this, I need to identify the GUID (Global Unique identifiers) of the component and set its kill-bit value to COMPAT_EVIL_DONT_LOAD.
Let me reintroduce 3 small helper functions I wrote last year and that I revisited:
Function Get-KillBit { [CmdletBinding()] param( [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [ValidatePattern('^\{[A-Z0-9]{4}([A-Z0-9]{4}-){4}[A-Z0-9]{12}\}$')] [string[]]$GUID ) Begin{ $x86='Software\Wow6432Node' $x64='Software' $FLAGS = DATA { ConvertFrom-StringData @' 1=COMPAT_AGGREGATE 2=COMPAT_NO_OBJECTSAFETY 4=COMPAT_NO_PROPNOTIFYSINK 8=COMPAT_SEND_SHOW 16=COMPAT_SEND_HIDE 32=COMPAT_ALWAYS_INPLACEACTIVATE 64=COMPAT_NO_SETEXTENT 128=COMPAT_NO_UIACTIVATE 256=COMPAT_NO_QUICKACTIVATE 512=COMPAT_NO_BINDF_OFFLINEOPERATION 1024=COMPAT_EVIL_DONT_LOAD 2048=COMPAT_PROGSINK_UNTIL_ACTIVATED 4096=COMPAT_USE_PROPBAG_AND_STREAM 8192=COMPAT_DISABLEWINDOWLESS 16384=COMPAT_SETWINDOWRGN 32768=COMPAT_PRINTPLUGINSITE 65536=COMPAT_INPLACEACTIVATEEVENWHENINVISIBLE 131072=COMPAT_NEVERFOCUSSABLE 262144=COMPAT_ALWAYSDEFERSETWINDOWRGN 524288=COMPAT_INPLACEACTIVATESYNCHRONOUSLY 1048576=COMPAT_NEEDSZEROBASEDDRAWRECT 2097152=COMPAT_HWNDPRIVATE 4194304=COMPAT_SECURITYCHECKONREDIRECT 8388608=COMPAT_SAFEFOR_LOADING '@ } } Process{ $GUID | ForEach-Object -Process { $GUIDitem = $_ Write-Verbose "Testing GUID $GUIDitem" $x86,$x64 | ForEach-Object { Write-Verbose "Testing Hive $_" $RegPath = $_ $flag = $null if (Test-Path "HKLM:\$RegPath\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem") { try { $flag = Get-ItemProperty -Path "HKLM:\$RegPath\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem" -Name 'Compatibility Flags' -ErrorAction Stop } catch { Write-Warning "Failed because $($_.Exception.Message)" return } $Meaning = @() $FLAGS.Keys | ForEach-Object { if (($flag.'Compatibility Flags') -band $_) { $Meaning += $FLAGS["$_"] } } New-Object -TypeName PSobject -Property @{ Meaning = $Meaning GUID = $GUIDitem Path = $flag.PSPath Value = $flag.'Compatibility Flags' HexValue = -join ('0x',('{0:X0}' -f $flag.'Compatibility Flags')) DisplayName = (Get-ItemProperty -Path "HKLM:\$RegPath\Classes\CLSID\$GUIDitem" -Name '(default)' -ErrorAction Silentlycontinue).'(default)' } } else { Write-Verbose "Skipped HKLM:\$RegPath\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem as it doesn't exist" } } } } End{} } Function Set-KillBit { [CmdletBinding()] param( [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [ValidatePattern('^\{[A-Z0-9]{4}([A-Z0-9]{4}-){4}[A-Z0-9]{12}\}$')] [string[]]$GUID ) Begin { # Make sure we run as admin $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() $IsAdmin = $usercontext.IsInRole(544) if (-not($IsAdmin)) { Write-Warning "Must run powerShell as Administrator to perform these actions" return } } Process { $GUID | ForEach-Object -Process { $GUIDitem = $_ Write-Verbose "Handling GUID $GUIDitem" $null,"Wow6432Node" | ForEach-Object { $HiveLocation = $_ $flagged = $null try { if (-not(Test-Path "HKLM:\Software\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem")) { New-Item -Path "HKLM:\Software\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility" -Name $GUIDitem -Force -ErrorAction Stop | Out-Null New-ItemProperty -Path "HKLM:\Software\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem" -PropertyType DWORD -Name 'Compatibility Flags' -Value 1024 -Force | Out-Null } else { Set-ItemProperty -Path "HKLM:\Software\$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( [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [ValidatePattern('^\{[A-Z0-9]{4}([A-Z0-9]{4}-){4}[A-Z0-9]{12}\}$')] [string[]]$GUID ) Begin { # Make sure we run as admin $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() $IsAdmin = $usercontext.IsInRole(544) if (-not($IsAdmin)) { Write-Warning "Must run powerShell as Administrator to perform these actions" return } } Process { $GUID | ForEach-Object -Process { $GUIDitem = $_ Write-Verbose "Handling GUID $GUIDitem" $null,"Wow6432Node" | ForEach-Object { Write-Verbose "Setting it in hive $_" $HiveLocation = $_ $flagged = $null try { if (Test-Path "HKLM:\Software\$HiveLocation\Microsoft\Internet Explorer\ActiveX Compatibility\$GUIDitem") { Remove-Item -Path "HKLM:\Software\$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{} }
I found the meaning of the decimal/hexadecimal values on this MSDN page where it’s also mentioned that
These enumeration members are bit masks that determine how ActiveX controls are used in Internet Explorer.
My Set-KillBit function only uses the single value “COMPAT_EVIL_DONT_LOAD”.
It doesn’t “merge” bit mask values although it should and note that it could overwrite any preexisting values, so use it with caution.
Idem, my Clear-KillBit function doesn’t remove the 0x400 flag.
Only my Get-KillBit function isn’t considered as written in quick and dirty mode 😛
- Step 1: Identify GUIDs
$allJREGUIDs = @() $Nodes = @($null,'Wow6432Node') $WMI = [wmiclass]"root\default:stdRegProv" $allJREGUIDs += $Nodes | ForEach-Object { $WMI.EnumKey(2147483650,"SOFTWARE\$_\Classes\CLSID").sNames } | Where-Object { $_ -match "CAFEEFAC"} $allJREGUIDs | ? {$_ -match "-DEC"}
$allJREGUIDs | ? {$_ -match "-DEC"} | Set-KillBit -Verbose
$allJREGUIDs | ? {$_ -match "-DEC"} | Get-KillBit | ft GUID,DisplayName,Meaning
To test, you need 4 things:
- an out-of-date JRE version
- a test URL
- A way to revert back to the original state with no kill-bit set on the deployment kit component
http://www.java.com/en/download/testjava.jsp
$allJREGUIDs | ? {$_ -match "-DEC"} | Get-KillBit | Clear-KillBit -Verbose
Happy testing until Oracle fixes its products and releases an official guidance about the new notification, a.k.a JRE expiration, feature 😎
looked really promising, but it dosn’t work unfortunately …..soooo frustrating
at least on paper the solution is provided in the new Java release 7 update 40
_____________________________________________
http://www.java.com/en/download/faq/expire_date.xml
“Why am I always redirected to Java.com when visiting a page with a Java application?
The continual redirection to java.com was a known issue affecting Java versions 7u25 and older. This issue is fixed as of 7u40 release of Java.”
Check the new features and changes:
Option to disable the “JRE out of date” warning
Starting from 7u40, a new deployment property deployment.expiration.check.enabled is available. This property can be used to disable the “JRE out of date” warning.
When the installed JRE (7u10 or later), falls below the security baseline or passes it’s built-in expiration date, an additional warning is shown to users to update their installed JRE to the latest version. For businesses that manage the update process centrally, users attempting to update their JRE individually, may cause problems.
To suppress this specific warning message, add the following entry in the deployment properties file:
deployment.expiration.check.enabled=false
For more information, see Deployment Configuration File and Properties.
_______________________________________________________
Yes, that’s correct. Here’s what the release notes say:
Source: http://www.oracle.com/technetwork/java/javase/7u40-relnotes-2004172.html
Today is already October 15, 2013 in South Africa. We realize that the USA is on very slow time, as most of the world starts the day while the USA is still in yesterday. How do we see whether the latest Java issue was already made available from Oracle.com, for downloading on a worldwide basis? The news release of this update seems to be missing.
Great writeup. This just hit us as we started deploying Java 7 this last month after some compatability issues were resolved internally. More than a few of our less knowledgeable users freaked out thinking their PC was infected or who knows what. Hopefully Oracle get’s their stuff together so we can control this via Group Policy.
> Thanks Pascal for your comment on http://www.itninja.com/blog/view/java-7-update-25-best-way-to-deploy-with-customized-settings
deployment.expiration.check.enabled=false
Does not work with 1.7_76 Any help there?
Your powershell script does disable the Out Of Date Check but now I get the following error:
The Java plug-in failed to load.
The required version:1.7.0_21 or higher
Where did you get the message? Can you post a screenshot?
the official page where all options are listed for version 1.7.x is:
https://docs.oracle.com/javase/7/docs/technotes/guides/jweb/jcp/properties.html
1.70_76 is an expired JRE version.
The release notes from 1.7.0_76 http://www.oracle.com/technetwork/java/javase/7u76-relnotes-2389087.html
confirm when it has expired:
The release notes are listed on this page:
http://www.oracle.com/technetwork/java/javase/7u-relnotes-515228.html
You can also see the current release version. Get the latest release and install it if you require it.
Pingback: How to Run with an old version of JRE | Luca's Space