mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1376459 - Prevent Offline Application Cache fallback namespace and fallback page be from a parent directory relative to the manifest. r=jduell
This commit is contained in:
parent
eb211c43fa
commit
f008a7d471
@ -196,6 +196,50 @@ Hash(const char *buf, nsACString &hash)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsInSubpathOfAppCacheManifest(nsIApplicationCache *cache, nsACString const& uriSpec)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(cache);
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURL> url(do_QueryInterface(uri, &rv));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoCString directory;
|
||||||
|
rv = url->GetDirectory(directory);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> manifestURI;
|
||||||
|
rv = cache->GetManifestURI(getter_AddRefs(manifestURI));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURL> manifestURL(do_QueryInterface(manifestURI, &rv));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoCString manifestDirectory;
|
||||||
|
rv = manifestURL->GetDirectory(manifestDirectory);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringBeginsWith(directory, manifestDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
// We only treat 3xx responses as redirects if they have a Location header and
|
// We only treat 3xx responses as redirects if they have a Location header and
|
||||||
@ -3503,6 +3547,12 @@ nsHttpChannel::ProcessFallback(bool *waitingForRedirectCallback)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IsInSubpathOfAppCacheManifest(mApplicationCache, mFallbackKey)) {
|
||||||
|
// Refuse to fallback if the fallback key is not contained in the same
|
||||||
|
// path as the cache manifest.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(fallbackEntryType & nsIApplicationCache::ITEM_FALLBACK,
|
MOZ_ASSERT(fallbackEntryType & nsIApplicationCache::ITEM_FALLBACK,
|
||||||
"Fallback entry not marked correctly!");
|
"Fallback entry not marked correctly!");
|
||||||
|
|
||||||
@ -4602,6 +4652,17 @@ nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry,
|
|||||||
|
|
||||||
if (namespaceType &
|
if (namespaceType &
|
||||||
nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) {
|
nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) {
|
||||||
|
|
||||||
|
nsAutoCString namespaceSpec;
|
||||||
|
rv = namespaceEntry->GetNamespaceSpec(namespaceSpec);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// This prevents fallback attacks injected by an insecure subdirectory
|
||||||
|
// for the whole origin (or a parent directory).
|
||||||
|
if (!IsInSubpathOfAppCacheManifest(mApplicationCache, namespaceSpec)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
rv = namespaceEntry->GetData(mFallbackKey);
|
rv = namespaceEntry->GetData(mFallbackKey);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
@ -801,6 +801,37 @@ nsOfflineManifestItem::AddNamespace(uint32_t namespaceType,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
GetURIDirectory(nsIURI* uri, nsACString &directory)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURL> url(do_QueryInterface(uri, &rv));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = url->GetDirectory(directory);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
CheckFileContainedInPath(nsIURI* file, nsACString const &masterDirectory)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
nsAutoCString directory;
|
||||||
|
rv = GetURIDirectory(file, directory);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
bool contains = StringBeginsWith(directory, masterDirectory);
|
||||||
|
if (!contains) {
|
||||||
|
return NS_ERROR_DOM_BAD_URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegin,
|
nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegin,
|
||||||
const nsCString::const_iterator &aEnd)
|
const nsCString::const_iterator &aEnd)
|
||||||
@ -945,6 +976,25 @@ nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegi
|
|||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// The following set of checks is preventing a website under
|
||||||
|
// a subdirectory to add fallback pages for the whole origin
|
||||||
|
// (or a parent directory) to prevent fallback attacks.
|
||||||
|
nsAutoCString manifestDirectory;
|
||||||
|
rv = GetURIDirectory(mURI, manifestDirectory);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = CheckFileContainedInPath(namespaceURI, manifestDirectory);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = CheckFileContainedInPath(fallbackURI, manifestDirectory);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Manifest and namespace must be same origin
|
// Manifest and namespace must be same origin
|
||||||
if (!NS_SecurityCompareURIs(mURI, namespaceURI,
|
if (!NS_SecurityCompareURIs(mURI, namespaceURI,
|
||||||
mStrictFileOriginPolicy))
|
mStrictFileOriginPolicy))
|
||||||
|
Loading…
Reference in New Issue
Block a user