Closed
Bug 611897
Opened 14 years ago
Closed 14 years ago
Only pass URL schemes to the OJI plugin that Java can understand
Categories
(Core Graveyard :: Plug-ins, defect)
Tracking
(blocking1.9.2 .13+, status1.9.2 .13-fixed, blocking1.9.1 .16+, status1.9.1 .16-fixed)
People
(Reporter: smichaud, Assigned: smichaud)
References
Details
(Whiteboard: [sg:high] (goes with bug 611910))
Attachments
(2 files, 5 obsolete files)
32.09 KB,
patch
|
jst
:
review+
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
16.73 KB,
patch
|
Details | Diff | Splinter Review |
This bug was spun off from bug 589041, to fix that bug for OJI plugins. OJI uses the current script principal's origin to configure the privileges of Java code that's called (via the nsISecureEnv interface) from JavaScript code (aka JavaScript-to-Java LiveConnect). As the testcase from bug 589041 shows, if the script principal's origin is a malformed URL (or one that Java can't understand), JavaScript-to-Java calls will run with abnormally high privileges: Specifically, it will be allowed to read any file. This happens in the following method in SecureInvocation.java (part of the source distro for Sun/Oracle JDKs going back to Java 1.4.2): private static ProtectionDomain getDefaultProtectionDomain(String urlString, boolean direct) This method tries to construct a URL object from the urlString parameter, using the URL(String) constructor. If the constructor fails with a MalformedURLException, the 'url' variable gets set to 'null'. Then if 'url' is 'null' or its scheme/protocol is 'file', the following permission is added to the PermissionCollection object from which a ProtectionDomain will be created: FilePermission("<<ALL FILES>>", "read") The 'urlString' value passed to getDefaultProtectionDomain() ultimately comes from a call to nsCSecurityContext::GetOrigin() in Mozilla OJI code. In my next comment I'll post a patch that changes this method to only return an 'origin' that Java will understand -- that won't cause the URL(String) constructor to throw a MalformedURLException.
Assignee | ||
Updated•14 years ago
|
Blocks: CVE-2010-3775
Assignee | ||
Comment 1•14 years ago
|
||
As promised in comment #0, my patch changes the nsCSecurityContext::GetOrigin() method to only return an 'origin' that Java will understand. If the "original" origin isn't a proper URL, or if its scheme isn't in the small lists of schemes/protocols that Java understands, it returns a "fake" URL with the "http" scheme and a random hostname ending in an invalid TLD (currently ".xyz"). The idea is to return a URL that won't make the URL(String) constructor choke, but which also won't cause any usable network privileges to be granted.
Assignee | ||
Updated•14 years ago
|
Attachment #490300 -
Flags: review? → review?(jst)
Assignee | ||
Comment 2•14 years ago
|
||
I'd like to post a Linux test build made with my patch from comment #1, plus some debug logging. But wierdness in my current Linux build configuration prevents me from doing that. Hopefully I'll find a way around it next week. (As of a few months ago, the tryservers are only available do to trunk builds.)
Comment 3•14 years ago
|
||
Please set the TLD to "invalid" instead, since that's actually guaranteed to never be a working TLD?
Assignee | ||
Comment 4•14 years ago
|
||
Comment on attachment 490300 [details] [diff] [review] Fix Oops, forgot to mention that this is a patch on 1.9.1-branch code -- since it can only be tested on the 1.9.1 branch.
Assignee | ||
Comment 5•14 years ago
|
||
> Please set the TLD to "invalid" instead, since that's actually guaranteed to
> never be a working TLD?
Good idea. I'll try that out next week.
Assignee | ||
Comment 6•14 years ago
|
||
Comment on attachment 490300 [details] [diff] [review] Fix I need to make some changes to this patch, which I'll do next week.
Attachment #490300 -
Flags: review?(jst)
Assignee | ||
Updated•14 years ago
|
blocking1.9.1: --- → ?
blocking1.9.2: --- → ?
Comment 7•14 years ago
|
||
(In reply to comment #6) > I need to make some changes to this patch, which I'll do next week. Please do it today or tomorrow, code freeze for the branch is Thursday and you'll need to leave time to get reviews.
Comment 8•14 years ago
|
||
(In reply to comment #1) > If the "original" origin isn't a proper URL, or if its scheme isn't in > the small lists of schemes/protocols that Java understands, it returns > a "fake" URL with the "http" scheme and a random hostname ending in an > invalid TLD (currently ".xyz"). The idea is to return a URL that > won't make the URL(String) constructor choke, but which also won't > cause any usable network privileges to be granted. Why not just return an error, "no java for you!"? If returning an error doesn't stop java execution then I worry about the error return further down if origin is null. What happens then?
Assignee | ||
Comment 9•14 years ago
|
||
> Why not just return an error, "no java for you!"? Then you may break Java in unexpected ways, like what happened when I did the same kind of thing in JEP 0.9.7.4's workaround for bug 589041, and triggered bug 606737 and bug 607678. I thought we'd agreed on a URL scheme whitelist (bug 589041 comment #50). > If returning an error doesn't stop java execution then I worry about > the error return further down if origin is null. What happens then? I don't understand what you're saying. With my current patch, a null origin gets replaced by a fake URL that Java can understand, but can't use to access the network.
Assignee | ||
Comment 10•14 years ago
|
||
> With my current patch, a null origin gets replaced by a fake URL
> that Java can understand, but can't use to access the network.
Oops, that's wrong.
nsCSecurityContext::GetOrigin() does an error return if it finds a
NULL origin. And now I see this is what you're referring to.
I'll look into what happens when nsCSecurityContext::GetOrigin() does
an error return.
Assignee | ||
Comment 11•14 years ago
|
||
> I'll look into what happens when nsCSecurityContext::GetOrigin() > does an error return. Since my patch for bug 610525 landed, I don't think it's any longer possible that nsCSecurityContext::GetOrigin() will fail to find an origin while doing JavaScript-to-Java LiveConnect. But there's only one place this method is called (from getAndPackSecurityInfo() in the OJI plugin's remotejni.cpp), and the caller doesn't check for an error return. So I've bullet-proofed nsCSecurityContext::GetOrigin() as much as possible. And I now call it from browser-side OJI code, just before every possible JavaScript-to-Java call, and abort the call if (by some very unlikely chance) nsCSecurityContext::GetOrigin() does an error return. We really shouldn't say "no Java for you" unless absolutely necessary -- we're usually deep inside plugin code, and it's hard to predict what Java will do when we start breaking things. I wish I'd thought of my fake URL solution when I was doing my workaround for bug 589041 in JEP 0.9.7.4 -- it would have been much less disruptive. I've also followed Boris' suggestion from bug 611910 comment #4 and bug 611910 comment #6 to put some of my patch into nsNetUtil.h where it can be shared (for example by my patch for bug 611910). Note that this patch (like the previous one) is on the 1.9.1 branch. The OJI plugin's getAndPackSecurityInfo() calls nsCSecurityContext::GetOrigin() with a 256-byte stack buffer -- which is why I do the same thing from ProxyJNIEnv's various methods.
Attachment #490300 -
Attachment is obsolete: true
Assignee | ||
Updated•14 years ago
|
Attachment #490915 -
Flags: review?(jst)
Assignee | ||
Updated•14 years ago
|
Attachment #490915 -
Flags: review?(dveditz)
Assignee | ||
Comment 12•14 years ago
|
||
Comment on attachment 490915 [details] [diff] [review] Fix rev1 (fix various problems) Boris, please review the changes I've made to nsNetUtil.h.
Attachment #490915 -
Flags: review?(bzbarsky)
Updated•14 years ago
|
Whiteboard: [sg:high]
Assignee | ||
Comment 13•14 years ago
|
||
I've already found one mistake: I need to add the following line to nsNetUtil.h. Windows builds fail without it: #include <stdlib.h>
Comment 14•14 years ago
|
||
If we're actually going for unique hostnames, shouldn't we do something better than rand() seeded with a known value that doesn't update very often?
Assignee | ||
Comment 15•14 years ago
|
||
> If we're actually going for unique hostnames, shouldn't we do
> something better than rand() seeded with a known value that doesn't
> update very often?
If you have a better idea, please suggest it. I'm not an expert on
this.
Comment 16•14 years ago
|
||
I think it would make more sense to generate a UUID as the hostname. See the code in nsNullPrincipal::Init. You'll want to strip the '{' and '}' chars off the string ToProvidedString creates, but other than that it should work.
Assignee | ||
Comment 17•14 years ago
|
||
OK, I'll try that. New patch coming up.
Assignee | ||
Comment 18•14 years ago
|
||
This patch makes NS_MakeRandomInvalidURLString() optionally use nsIUUIDGenerator to generate a UUID for the hostname, and falls back to using NS_MakeRandomString(). The fallback is needed if nsIUUIDGenerator fails. But I also discovered that using nsIUUIDGenerator is a significant performance hit if it's called at all often (as it is by the OJI plugin and my current OJI patch). Possibly it's using a randomness provider that blocks until sufficient randomness is available (I tested on Linux). So I've made my OJI patch (this bug's patch) tell NS_MakeRandomInvalidURLString() to always use NS_MakeRandomString(). Since the OJI plugin is obsolete and seldom used on Windows or Linux, I figure this isn't a great loss. My new patch for bug 611910 tells NS_MakeRandomInvalidURLString() to use nsIUUIDGenerator.
Attachment #490915 -
Attachment is obsolete: true
Attachment #491046 -
Flags: review?
Attachment #490915 -
Flags: review?(jst)
Attachment #490915 -
Flags: review?(dveditz)
Attachment #490915 -
Flags: review?(bzbarsky)
Assignee | ||
Updated•14 years ago
|
Attachment #491046 -
Flags: review?(dveditz)
Assignee | ||
Updated•14 years ago
|
Attachment #491046 -
Flags: review?(jst)
Attachment #491046 -
Flags: review?(bzbarsky)
Attachment #491046 -
Flags: review?
Comment 19•14 years ago
|
||
OK, so I feel like I'm missing something. Do we actually need unique/unguessable return values for what Java needs here security-wise? If that's the case, why are not particularly guessable but pretty guessable ones ok? If not, why not just use a constant string?
Assignee | ||
Comment 20•14 years ago
|
||
Here's a new patch that does a better job of dealing with the performance hit I mentioned in comment #18. Turns out this isn't caused by a randomness provider, or by any Mozilla code. Instead it seems to be a subtle problem with the pipe that the OJI plugin uses to pass information from JavaScript code running on the main thread to Java code running on secondary threads. Somehow, rapidly changing the "origin" causes a dramatic slowdown in the operation of this pipe. So if we need to use a fake origin, my new patch dramatically reduces the frequency with which that fake origin is changed. This doesn't open a security hole: Some of Java's same-origin checks may now pass that would fail it the fake origin changed more often. But same-origin checks are only used to grant (or deny) network access, and none of the fake origins (which are invalid URLs) can be used to access the network. My new patch also changes NS_MakeRandomString() in nsNetUtil.h. Turns out the only reason I didn't see the above-mentioned performance hit when using NS_MakeRandomString() is that it only changed the seed (passed to srandom()) every second -- so that frequent calls would return the same "random" string. A comment in the previous code claims the granularity of PR_Now() on "the Mac" is one second. But this was only true of Mac Carbon code, which has been gone since FF 2.0 days. So my code now assumes that PR_Now() has millisecond granularity -- which (judging by the "milliseconds since epoch" comment) was the original intention all along.
Attachment #491046 -
Attachment is obsolete: true
Attachment #491046 -
Flags: review?(jst)
Attachment #491046 -
Flags: review?(dveditz)
Attachment #491046 -
Flags: review?(bzbarsky)
Assignee | ||
Updated•14 years ago
|
Attachment #491578 -
Flags: review?(jst)
Assignee | ||
Updated•14 years ago
|
Attachment #491578 -
Flags: review?(dveditz)
Assignee | ||
Updated•14 years ago
|
Attachment #491578 -
Flags: review?(bzbarsky)
Assignee | ||
Comment 21•14 years ago
|
||
(In reply to comment #19) > why not just use a constant string? This would be visible in our source code, and hence easily guessable. I think my new patch is a better solution.
Assignee | ||
Comment 22•14 years ago
|
||
> Do we actually need unique/unguessable return values for what Java
> needs here security-wise?
We don't need unique return values, and we may not need unguessable
ones -- presuming I'm right about Java only using same-origin checks
to grant or deny network access.
Somehow, though, I feel more comfortable with what my current patch
does.
Comment 23•14 years ago
|
||
OK, thanks for explaining. 1) If we fail to get the UUID generator service, I think we should just throw an exception or equivalent. That should not be happening. 2) I'd prefer not hardcoding "36" when we have a perfectly good NSID_LENGTH lying around that we can use (with a few subtracted obviously). 3) Are there plans to use NS_CheckIsJavaCompatibleURLString anywhere other than this code? 4) PR_Now on modern Mac has microsecond granularity as far as I can tell, but given that I don't think we need NS_MakeRandomString at all (see item 1), I think that's not relevant. 5) GetFakeOrigin should return |const nsCString&| and be a const method, right?
Assignee | ||
Comment 24•14 years ago
|
||
> 1) If we fail to get the UUID generator service, I think we should > just throw an exception or equivalent. That should not be > happening. In both this bug's patch and my patch for bug 611010, we very much want to avoid saying "no Java for you", if at all possible. And my changes substantially improve NS_MakeRandomString(). So I'd really prefer to keep falling back to it. > 2) I'd prefer not hardcoding "36" when we have a perfectly good > NSID_LENGTH lying around that we can use (with a few subtracted > obviously). OK, I'll use 'NSID_LENGTH - 3'. The reason I used '36' is that NSID_LENGTH (at 39) is (currently) one longer than the length of a UUID (presumably to account for null termination), and I was a bit worried this might change (while the actual length of a UUID is extremely unlike to change). But yes, it's always better to use a macro for this kind of value. So I'll do that. > 3) Are there plans to use NS_CheckIsJavaCompatibleURLString anywhere > other than this code? Yes. It's already used by my patch for bug 611910. And I suspect we'll want to use it in a patch for bug 594443. > 5) GetFakeOrigin should return |const nsCString&| and be a const > method, right? Oops, stupid mistake. I'll fix it.
Comment 25•14 years ago
|
||
> we very much want to avoid saying "no Java for you"
Look, if the UUID service is not present, then nsDocument objects can't be instantiated at all. So either the browser won't start, or you're so deep inside XPCOM shutdown that the component is not longer being handed out by the service manager. In either case, no java seems perfectly fine to me.
Assignee | ||
Comment 26•14 years ago
|
||
OK, I'll get rid of the fallback to NS_MakeRandomString(), and make appropriate other changes.
Assignee | ||
Comment 27•14 years ago
|
||
Attachment #491578 -
Attachment is obsolete: true
Attachment #491630 -
Flags: review?(joshmoz)
Attachment #491578 -
Flags: review?(jst)
Attachment #491578 -
Flags: review?(dveditz)
Attachment #491578 -
Flags: review?(bzbarsky)
Assignee | ||
Updated•14 years ago
|
Attachment #491630 -
Flags: review?(bzbarsky)
Assignee | ||
Updated•14 years ago
|
Attachment #491630 -
Flags: review?(joshmoz) → review?(jst)
Assignee | ||
Updated•14 years ago
|
Attachment #491630 -
Flags: review?(dveditz)
Assignee | ||
Comment 28•14 years ago
|
||
jst and dveditz: If there's to be any chance that a fix for this bug makes tonight's code freeze, you need to do your reviews right away.
Assignee | ||
Comment 29•14 years ago
|
||
Comment on attachment 491630 [details] [diff] [review] Fix rev4 (follow Boris' suggestions) Oops, I found a flaw in my current patch (in the OJI code). New patch coming up. Please start your reviews anyway -- the new patch won't change very much. And nsNetUtil.h won't change at all from my current patch.
Assignee | ||
Comment 30•14 years ago
|
||
My previous patch opened a potential security hole: It would have made a single nsCSecurityContext object persist for the entire life of a ProxyJNIEnv object. One ProxyJNIEnv object is (potentially) created for every thread. But JavaScript-to-Java calls are always made on the main thread -- so they're always made from the same ProxyJNIEnv object. As I said above, I don't think it's a problem for the same fake origin to be used for every call from a ProxyJNIEnv object. But the nsCSecurityContext object encapsulates additional security information, which it *would* (potentially) be a problem to share between different instances of the OJI plugin. (I say "potentially" because we're talking about non-applet security, and I'm not sure it's possible to legitimately make non-applet JavaScript-to-Java calls with enhanced privileges.) My new patch takes care of this by only making a fake origin persist for the life of a ProxyJNIEnv object.
Attachment #491630 -
Attachment is obsolete: true
Attachment #491630 -
Flags: review?(jst)
Attachment #491630 -
Flags: review?(dveditz)
Attachment #491630 -
Flags: review?(bzbarsky)
Assignee | ||
Updated•14 years ago
|
Attachment #491669 -
Flags: review?(jst)
Assignee | ||
Updated•14 years ago
|
Attachment #491669 -
Flags: review?(dveditz)
Assignee | ||
Updated•14 years ago
|
Attachment #491669 -
Flags: review?(bzbarsky)
Comment 31•14 years ago
|
||
Comment on attachment 491669 [details] [diff] [review] Fix rev5 (fix potential security hole in previous patch) - In ProxyJNIEnv::~ProxyJNIEnv(): + NS_IF_RELEASE(mContext); This looks unrelated to this fix, but looks like a valid potential leak fix. But there's also some potential risk in doing this. If you feel confident in this fix, I'm fine with taking it, else, we could leave this out until we have time to leave it bake someplace. - In nsCSecurityContext::GetOrigin(char* buf, int buflen): + printf("nsCSecurityContext::GetOrigin(): origin '%s' not Java-compatible, changing to '%s'\n", + origin.get(), mFakeOrigin.get()); Remove the printf. Or at least wrap it in #ifdef DEBUG or somesuch r=jst with that.
Attachment #491669 -
Flags: review?(jst) → review+
Assignee | ||
Comment 32•14 years ago
|
||
Comment on attachment 491669 [details] [diff] [review] Fix rev5 (fix potential security hole in previous patch) > + NS_IF_RELEASE(mContext); > > This looks unrelated to this fix, but looks like a valid potential > leak fix. But there's also some potential risk in doing this. If > you feel confident in this fix, I'm fine with taking it, else, we > could leave this out until we have time to leave it bake someplace. In fact it comes from the previous version of my patch -- where I noticed the leak. Since mContext is initialized to NULL, I'm pretty sure it won't cause any trouble. > + printf("nsCSecurityContext::GetOrigin(): origin '%s' not" > + "Java-compatible, changing to '%s'\n", > + origin.get(), mFakeOrigin.get()); > > Remove the printf. Or at least wrap it in #ifdef DEBUG or somesuch This strayed from my debug patch. I'll get rid of it on landing.
Comment 33•14 years ago
|
||
Comment on attachment 491669 [details] [diff] [review] Fix rev5 (fix potential security hole in previous patch) >+++ b/modules/oji/src/ProxyJNI.cpp The repeated copy/paste here really looks like it wants to be a helper function. >+++ b/modules/oji/src/nsCSecurityContext.cpp Drive-by, but: buf[originlen] = nsnull; // Gotta terminate it. should be '\0' instead, no? And ideally we would just output into an nsCString, not a fixed-size buffer. But whatever; this is not that important. >+++ b/netwerk/base/public/nsNetUtil.h >+#define NU_FAKE_SCHEME "http://" >+#define NU_FAKE_TLD ".invalid" Not sure where the "NU" prefix comes from. Why not just "NS"? >+NS_MakeRandomInvalidURLString(nsCString& result) >+ result.Assign(NU_FAKE_SCHEME); AssignLitera, please >+ result.Append(NU_FAKE_TLD); And AppendLiteral here. r=me with those nits.
Attachment #491669 -
Flags: review?(bzbarsky) → review+
Assignee | ||
Comment 34•14 years ago
|
||
(Following up comment #32) > In fact it comes from the previous version of my patch -- where I > noticed the leak. Since mContext is initialized to NULL, I'm pretty > sure it won't cause any trouble. On second thought, though, it may be better to leave sleeping dogs lie. So if I land this patch tonight, I'll leave out the call to NS_IF_RELEASE(mContext) from the ProxyJNIEnv destructor.
Assignee | ||
Comment 35•14 years ago
|
||
Comment on attachment 491669 [details] [diff] [review] Fix rev5 (fix potential security hole in previous patch) Landed on the 1.9.1 branch with jst's and bzbarsky's fixes: http://hg.mozilla.org/releases/mozilla-1.9.1/rev/05202664ed20 I decided not to wait for dveditz' review. If he has any suggestions, he can make them later.
Attachment #491669 -
Flags: review?(dveditz)
Assignee | ||
Updated•14 years ago
|
Assignee | ||
Comment 36•14 years ago
|
||
Comment on attachment 491669 [details] [diff] [review] Fix rev5 (fix potential security hole in previous patch) Landed on the 1.9.2 branch: http://hg.mozilla.org/releases/mozilla-1.9.2/rev/85be45fb4a34
Assignee | ||
Updated•14 years ago
|
Status: ASSIGNED → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 37•14 years ago
|
||
(In reply to comment #33) >>+++ b/netwerk/base/public/nsNetUtil.h >>+#define NU_FAKE_SCHEME "http://" >>+#define NU_FAKE_TLD ".invalid" > > Not sure where the "NU" prefix comes from. Why not just "NS"? NU stands for NetUtil. NS is fine, though, and that's what's in the final patch.
Assignee | ||
Comment 38•14 years ago
|
||
Gregory Fleischer, please test tomorrow's 1.9.1-branch (FF 3.5.X) Linux nightly plus the OJI plugin with the first of your testcases from bug 589041.
Updated•14 years ago
|
Whiteboard: [sg:high] → [sg:high] (goes with bug 611910)
Comment 39•14 years ago
|
||
Only difference is includes in netwerk/base/public/nsNetUtil.h
Updated•13 years ago
|
Group: core-security
Updated•2 years ago
|
Product: Core → Core Graveyard
You need to log in
before you can comment on or make changes to this bug.
Description
•