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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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,
|
||||
"Fallback entry not marked correctly!");
|
||||
|
||||
@ -4602,6 +4652,17 @@ nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry,
|
||||
|
||||
if (namespaceType &
|
||||
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);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
@ -801,6 +801,37 @@ nsOfflineManifestItem::AddNamespace(uint32_t namespaceType,
|
||||
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
|
||||
nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegin,
|
||||
const nsCString::const_iterator &aEnd)
|
||||
@ -945,6 +976,25 @@ nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegi
|
||||
if (NS_FAILED(rv))
|
||||
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
|
||||
if (!NS_SecurityCompareURIs(mURI, namespaceURI,
|
||||
mStrictFileOriginPolicy))
|
||||
|
Loading…
Reference in New Issue
Block a user