Oracle's Java Security Clusterfuck
(September 1, 2013; other vulnerabilities)
Oracle intentionally and needlessly breaks local file system Java Applets
UPDATE: 1/21/2014: Thanks for Christian Beilken for pointing out that Java 7 Update 51
silently fixes getCodeBase() and getDocumentBase() -- NULL is no longer returned!
However, for us at Duckware, the damage inflicted upon Java by Oracle is done -- we
killed off all of our Java applets and switched over to HTML5+JavaScript!
|
Executive Summary:
Oracle's Java Security team is removing "file path" information from a
locally run Java applet, busting the applet, citing security concerns.
But removal of that information was a
clusterfuck from day one, because "file path" information will always
be available — no matter
what is done to Java — via the web page the applet is in:
<html><body>
<!-- Oracle ignores that 'file path' info is a part of HTML -->
<script>document.write("HREF="+window.location.href)</script>
<!-- and INTENTIONALLY breaks this applet -->
<applet code="pmvr.class" width=800 height=600>
<param name="pano" value="mypanorama.jpg"> <!--busted-->
</applet>
</body></html>
|
Therefore, the removal of the information from Java was pointless (even if all
file path information is removed from Java, the applet can always get it from
the web page), ill-conceived, reckless
(someone should be fired over this),
and not even implemented properly (Oracle returns null even for an
applet code signed with FULL access to the computer).
And to make matters far worse, if removal was due
to actual real 'security' reasons, the Oracle Java security team is incompetent due
to blatantly obvious (disclosed below) remaining "file path" information in Java.
I am willing to bet that the person on the security team who pushed for this has NO legitimate
(toy maybe, but not real world) Java Applet programming experience.
The Problem:
In Java 7u25, Oracle returns null for an Applet's getCodeBase() (and in
Java 7u40, getDocumentBase() also returns null) when the Applet is running
from the local file system. And now Oracle is saying that any sandboxed
Applet's (signed or not) that requires access to non-JAR resources CAN NOT access those resources
via getCodeBase(),
even if the applet is code signed with FULL access to the computer.
[Source: 7u25-relnotes]
"Local Applets return NULL for codebase:
Beginning with JDK 7u25, an applet's getCodeBase() method will return NULL
when the applet is running from the local file system."
Yes, you read that correctly.
A code-signed Applet with FULL access to the computer will have a getCodeBase()
and getDocumentBase() that return NULL,
likely breaking the applet (something that I have tested and verified). Because, as
Oracle says, for 'security' reasons.
That is downright malicious (or is that incompetent) behavior on the part
of Oracle -- especially when this issue is marked as "WILL NOT FIX, intended behavior."
Quick tips for Java Applet developers:
Visit bugreport.sun.com and file a bug
report, citing this web page.
Assume that both Applet.getCodeBase() and Applet.getDocumentBase()
don't exist (they will return null). Assume that
Class.getResource() does not exist (a security exception will be thrown
because Java will not allow you access to resource URL's).
You must place all possible files inside the JAR, and use the Class.getResourceAsStream()
calls to access. If you need to access any files outside the JAR, Oracle
has screwed you over — switch to HTML5.
Oracle did this intentionally:
A posting from Oracle's Sandeep Konchady (Senior Software Manager and former member
of the JSS security team at Sun Microsystems)
on
gmane.comp.java.openjdk.security.devel,
states:
"The issue you are seeing is intended behavior. This was caused
because of a vulnerability that was fixed in 7u25 in which which (sic) a
getCodeBase call against all local applet/jnlp apps will return null."
But what vulnerability? We find out from
Java Bug Database ID=8017250:
"The fix to have getCodeBase() return NULL for file applets is because
it will expose local file system information (file path),
which sandbox applets should
not have access to it."
The Core Issue: Oracle is intentionally killing off the Java security sandbox
under the pretense of improving security. Oracle's alternative to a null getCodeBase()?
Code sign your Java applet and get FULL UNRESTRICTED ACCESS to the entire
computer.
[Source: Java Bug Database ID=8017250]
"if the resource is in arbitary (sic) location, not inside applet JAR, they should have
other ways to get to that location, since it's not part of the applet resource anyway.
(e.g user.home java system property, provided that their applet has all-permissions)"
The Oracle employee who made those comments should be put
out to pasture for having such a narrow mind and grossly misunderstanding
real-world Java Applets that are driven by end-user created data (therefore
impossible to add ahead of time to the JAR). Like a panorama applet trying
to access a user created panorama, mypanorama.jpg, disclosed at the
top of this web page.
Oracle's security fix for a sandboxed applet that can see some path
information — already available via the web page — is to break
the applet, and then Oracle recommends that 'the fix' for the broken applet is
to run the applet outside the sandbox (where the Applet has access to EVERYTHING
on the computer) WTF! — Oracle is clearly trying to kill off the
security sandbox.
The Implication for a Sandboxed local Applet:
Since there is no codebase (it is NULL), the applet
has no permission to access any local non-JAR resources (like a panorama viewer applet that
needs to load a multi-node panorama script):
InputStream in=(new URL(getDocumentBase(),"script.txt")).openStream();
This worked fine under ALL prior versions of Java, all the way back to Java 1.0.2
(1996). But now, in 2013, after working for 17 years, Oracle is saying that code
should no longer work. Here is that error that is now seen:
java.security.AccessControlException: access denied ("java.io.FilePermission" "C:\javatest\script.txt" "read")
Seeing the difference: So, to see what is going on, place Duckware's
java version applet
in a folder on your local computer, like c:\javatest\, and when run
in Java 6 (left), this applet can access the codebase, but when run in Java 7u25,
this (sandboxed) applet can NOT access the codebase:
Summary of Oracle's reason: So, Oracle is breaking sandboxed local file
system applets, because Oracle claims the applets should not have access to local
file path information, which Oracle says is a security risk -- even though that
information is available to the web page running the applet (and hence, the applet).
The problem with Oracle's attitude: But the huge problem with Oracle's attitude
is that "file path" information is available all over the place in Java
(and elsewhere), not just from getCodeBase(). So Oracle changing only getCodeBase()
is a huge security FAIL, showing a complete lack of understanding in how
Java works...
Place One:
It should be painfully obvious to any astute reader at this point
(and any real Java Applet programmer), that getDocumentBase()
also reveals "file path" information. It is incredibly hard to miss when
both methods are right next to each other
in the documentation
(seen right).
NOTE that Oracle
has stated that it intends for that to return null as well in the future.
System.out.println( ""+getDocumentBase() );
displays:
file:/C:/javatest/javahelp.html
Place Two:
The Applet classloader reveals "file path" information:
System.out.println( ""+getClass().getClassLoader() );
displays:
Applet2ClassLoader{[file:/C:/javatest/javahelp.jar, file:/C:/javatest/]}
Place Three:
Before I realized that Oracle had made this
change intentionally (I thought it was just a bug), I implemented
my own new getCodeBase(), that works for me (the codebase applet
tag is accessible to the Applet):
String s = getParameter("codebase");
System.out.println( ""+new URL(getDocumentBase(),(s!=null)?s:"."));
displays:
file:/C:/javatest/
Place Four:
Ask HTML/Javascript for the file path information:
Object o = (JSObject.getWindow(this)).eval("window.location.href");
System.out.println( ""+o );
displays:
file:///C:/javatest/javahelp.html
Place Five:
With Javascript in the HTML web page,
document.write() the <applet> tag into the HTML,
passing window.location.href as an applet parameter, which
the Applet can then obtain via a getParameter().
If you are using Oracle's deployJava.js
(reference),
this is as easy as adding "myurl:window.location.href"
to the "parameters" list:
System.out.println( getParameter("myurl") );
displays:
file:///C:/javatest/javahelp.html
Place Six ... and other places:
There are other ways of obtaining the "file path"
information from Java that I have confirmed -- but those are being withheld
because Oracle's incompetent decision-making can not be trusted.
Java leaks "file path" information from many places.
The Oracle clusterfuck:
Is Oracle's Java security team really that incompetent to not understand that:
- getDocumentBase() exists
- file path information exists elsewhere in Java Applets in many places
- that window.location.href exists; OUTSIDE of Java in the web page;
something Oracle can never remove
Even if Oracle did (eventually) eliminate ALL "file path"
information from Java, "file path" can ALWAYS be obtained
via window.location.href. So there is no point
in denying access to something that is already fully open
and available outside of Java, in the HTML web page! Pure silliness
(and a fool's errand) on the part of Oracle.
So what if a sandboxed applet gets its hands on
"file path" information. It can do nothing more with that
information, than what the web page alone (without Java) can already do
with that information!
In fact, Java can do FAR LESS with that information that what the
web page can do with it. Believe me when I say that that any local
web page being viewed, without any applet, can already remotely record
the entire local file path of the web page. So if there is any security
threat here, it comes NOT from Java, but from the web page itself.
Exposing file path information to Java, exposes NO MORE information
than what is already exposed to JavaScript inside the web page itself.
Plugging all of Java does nothing to plug window.location.href
inside the web page, and a web page is REQUIRED to run the applet.
And in fact, Oracle requires Javascript to be enabled when
using Oracle's preferred deployJava.js to deploy applets.
Draconian thinking:
Oracles says, 'we can't expose file path information,
so we are going to kill all file access' -- rather than thinking how they
could continue to provide file access to file-based applet resources
without file path information!
Conclusion:
Oracle needlessly broke file system sandboxed applets,
under the ridiculous guise of 'security', over something openly
available to the web page. If 'security' was the true reason,
the Oracle Java security team is incompetent and someone should be
fired. Regardless of a sandbox or not, "file path" information is
always available to the applet (via the webpage). Oracle needs to
acknowledge that and restore getCodeBase() and getDocumentBase().
Oracle needs to IMMEDIATELY own up to their clusterfuck, and
fix Java Applets ASAP.
ALTERNATIVE SANDBOX SOLUTIONS FOR ORACLE:
(1) BEST / A little work: The "file://" syntax already has a
'host' component. In a sandbox, the 'host' is meaningless, so use that!
getCodeBase() should return "file://codebase#/" (where # is a unique number
that identifies a particular JAR in use, of many). And due to how the bases
(code and document) work when run via a local file system, the getDocumentBase()
must ALWAYS be based on that. For example getDocumentBase() might return
"file://codebase1/one/tour/index.html" (because applets in sub folders
of a tree may codebase back to the web server root). Then internally, at the
very lowest level possible, there is a substitution for "codebase1" to the
real location on the file system (for example: "c:\javatest") in a way that will not leak real "file path"
out in thrown exceptions.
(2) GOOD / Almost no work:
When run from the local file system, return "file://" URL's that
are REAL (but symbolic links), and point to a location that is
"well known" and discloses nothing of substance. For example, getCodeBase() returns
"file:///c:/CAFEBABE/XYZ/", where CAFEBABE (or whatever name
Oracle wants and creates on the fly) is a Java VM controlled folder, and XYZ
is a symbolic link to the real location on the file system, c:\javatest\
(3) A bug to fix regardless: Allow developers to access known
non-JAR resources via getResourceAsStream() calls -- because as of
now, even that is improperly busted. getResourceAsStream("pano.jpg") should
work, but does not. That is a bug. There is no "file path" information.
|
More Information: Here is more information on the issue:
Once again, Oracle knows about this: Funny how Oracle keeps hitting my web
pages within hours of the posting going live. Thanks to 148.87.67.207, 193.9.13.138,
193.9.13.139, 202.45.129.180, 148.87.67.203, 148.87.19.198, 137.254.4.8, 148.87.67.212
Are you going to act, or sit there looking dumbfounded?
My direct inquiries into Oracle have so far been met with silence.
History is repeating itself: This is not the first time that Sun (Oracle)
has messed around with getCodeBase() and getDocumentBase(). Sun
did it once before arond 2002 and then reversed their decision. Now isn't it interesting that
the bug report can NOT be found in Oracle's current bug database?
But,
here it is archived.
Is Lax Quality Control at Oracle the problem?
It is very clear that Java is going 'out the door' without any meaningful quality control
and it is easy to prove. Take any Applet, and add the following line of code:
System.out.println( getClass().getResourceAsStream("index.html") );
Then code sign the applet JAR and run in an index.html web page, locally.
You will obtain a security popup asking if you want to give the applet
full unrestricted access to the computer. Answer yes.
And when the above line of code is run,
you will get this completely bogus security popup that "The
Applet contains both signed and unsigned code":
If you press the 'Block' button, null will be printed. If you
press "Don't block" button, something non-null will be printed.
There is nothing worse than false positives to erode security confidence
and this security popup does that. Because accessing the same file
a different way — "getDocumentBase().openStream()" —
yields no security popups.
Or, is Java itself becoming self-aware and when it says "Java has discovered ...
a security concern", is Java itself warning all of us that Java itself presents
a "security problem"?
Smile . . . . if you can.
|
|