Diff
Modified: trunk/Source/WebCore/ChangeLog (127149 => 127150)
--- trunk/Source/WebCore/ChangeLog 2012-08-30 16:08:27 UTC (rev 127149)
+++ trunk/Source/WebCore/ChangeLog 2012-08-30 16:12:13 UTC (rev 127150)
@@ -1,3 +1,48 @@
+2012-08-30 Otto Derek Cheung <[email protected]>
+
+ [BlackBerry] Modifying how IP domains are handled in Cookies
+ https://bugs.webkit.org/show_bug.cgi?id=95381
+
+ Reviewed by Rob Buis.
+ Internally reviewed by Joe Mason.
+
+ Current implementation handles IP addresses like normal domains.
+ This makes invalid cross domain cookies possibe by setting cookie
+ domains to a suffix of the targeted IP. (ex. hackers on 11.121.61.97
+ can set cookies to 61.97, so they show up on the targeted website of
+ 10.120.61.97)
+
+ New Implementation is to detect IP addresses and treat them without
+ exploding them with the delimiter ".". That way, IP addresses will
+ be stored as a whole and other IPs won't have access to it.
+
+ PR 130051
+
+ Manually tested by accessing a webpage via IP (hosted through
+ LAMP - ex:10.121.61.97) and tried to set cookies with domains that
+ are a suffix to the ip address (ex: .97, 121.61.97).
+ Also tried to set cookies to other ip addresses that "domain matches"
+ the IP address (ex. 11.121.61.97). Verified that they all failed.
+
+ Tested using the cookies test page: http://browser.swlab.rim.net/test/cookies
+
+ * platform/blackberry/CookieManager.cpp:
+ (WebCore::CookieManager::getRawCookies):
+ (WebCore::CookieManager::checkAndTreatCookie):
+ (WebCore::CookieManager::findOrCreateCookieMap):
+ * platform/blackberry/CookieManager.h:
+ * platform/blackberry/CookieParser.cpp:
+ (WebCore::CookieParser::CookieParser):
+ (WebCore::CookieParser::parseOneCookie):
+ * platform/blackberry/CookieParser.h:
+ (CookieParser):
+ * platform/blackberry/ParsedCookie.cpp:
+ (WebCore::ParsedCookie::ParsedCookie):
+ * platform/blackberry/ParsedCookie.h:
+ (WebCore::ParsedCookie::setDomain):
+ (WebCore::ParsedCookie::domainIsIPAddress):
+ (ParsedCookie):
+
2012-08-30 Ilya Tikhonovsky <[email protected]>
Web Inspector: [regression] ui: heap profiler: splitter between containment and retainment views has white background.
Modified: trunk/Source/WebCore/platform/blackberry/CookieManager.cpp (127149 => 127150)
--- trunk/Source/WebCore/platform/blackberry/CookieManager.cpp 2012-08-30 16:08:27 UTC (rev 127149)
+++ trunk/Source/WebCore/platform/blackberry/CookieManager.cpp 2012-08-30 16:12:13 UTC (rev 127150)
@@ -40,6 +40,7 @@
#include <BlackBerryPlatformMessageClient.h>
#include <BlackBerryPlatformNavigatorHandler.h>
#include <BlackBerryPlatformSettings.h>
+#include <network/DomainTools.h>
#include <stdlib.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/CString.h>
@@ -219,8 +220,15 @@
}
Vector<String> delimitedHost;
- requestURL.host().lower().split(".", true, delimitedHost);
+ // IP addresses are stored in a particular format (due to ipv6). Reduce the ip address so we can match
+ // it with the one in memory.
+ string canonicalIP = BlackBerry::Platform::getCanonicalIPFormat(requestURL.host().utf8().data());
+ if (!canonicalIP.empty())
+ delimitedHost.append(String(canonicalIP.c_str()));
+ else
+ requestURL.host().lower().split(".", true, delimitedHost);
+
// Go through all the protocol trees that we need to search for
// and get all cookies that are valid for this domain
for (size_t k = 0; k < protocolsToSearch.size(); k++) {
@@ -341,7 +349,7 @@
// If protocol support domain, we have to traverse the domain tree to find the right
// cookieMap to handle with
if (!ignoreDomain)
- curMap = findOrCreateCookieMap(curMap, candidateCookie->domain(), candidateCookie->hasExpired());
+ curMap = findOrCreateCookieMap(curMap, *candidateCookie);
// Now that we have the proper map for this cookie, we can modify it
// If cookie does not exist and has expired, delete it
@@ -475,12 +483,17 @@
}
}
-CookieMap* CookieManager::findOrCreateCookieMap(CookieMap* protocolMap, const String& domain, bool findOnly)
+CookieMap* CookieManager::findOrCreateCookieMap(CookieMap* protocolMap, const ParsedCookie& candidateCookie)
{
// Explode the domain with the '.' delimiter
Vector<String> delimitedHost;
- domain.split(".", delimitedHost);
+ // If the domain is an IP address, don't split it.
+ if (candidateCookie.domainIsIPAddress())
+ delimitedHost.append(candidateCookie.domain());
+ else
+ candidateCookie.domain().split(".", delimitedHost);
+
CookieMap* curMap = protocolMap;
size_t hostSize = delimitedHost.size();
@@ -494,7 +507,7 @@
CookieMap* nextMap = curMap->getSubdomainMap(delimitedHost[i]);
if (!nextMap) {
CookieLog("CookieManager - cannot find map\n");
- if (findOnly)
+ if (candidateCookie.hasExpired())
return 0;
CookieLog("CookieManager - creating %s in currentmap %s\n", delimitedHost[i].utf8().data(), curMap->getName().utf8().data());
nextMap = new CookieMap(delimitedHost[i]);
Modified: trunk/Source/WebCore/platform/blackberry/CookieManager.h (127149 => 127150)
--- trunk/Source/WebCore/platform/blackberry/CookieManager.h 2012-08-30 16:08:27 UTC (rev 127149)
+++ trunk/Source/WebCore/platform/blackberry/CookieManager.h 2012-08-30 16:12:13 UTC (rev 127150)
@@ -114,7 +114,7 @@
void addCookieToMap(CookieMap* targetMap, ParsedCookie* candidateCookie, BackingStoreRemovalPolicy postToBackingStore, CookieFilter = WithHttpOnlyCookies);
- CookieMap* findOrCreateCookieMap(CookieMap* protocolMap, const String& domain, bool findOnly);
+ CookieMap* findOrCreateCookieMap(CookieMap* protocolMap, const ParsedCookie& candidateCookie);
void initiateCookieLimitCleanUp();
void cookieLimitCleanUp(Timer<CookieManager>*);
Modified: trunk/Source/WebCore/platform/blackberry/CookieParser.cpp (127149 => 127150)
--- trunk/Source/WebCore/platform/blackberry/CookieParser.cpp 2012-08-30 16:08:27 UTC (rev 127149)
+++ trunk/Source/WebCore/platform/blackberry/CookieParser.cpp 2012-08-30 16:12:13 UTC (rev 127150)
@@ -55,6 +55,14 @@
CookieParser::CookieParser(const KURL& defaultCookieURL)
: m_defaultCookieURL(defaultCookieURL)
{
+ m_defaultCookieHost = defaultCookieURL.host();
+ m_defaultDomainIsIPAddress = false;
+ string hostDomainCanonical = BlackBerry::Platform::getCanonicalIPFormat(m_defaultCookieHost.utf8().data()).c_str();
+ if (!hostDomainCanonical.empty()) {
+ m_defaultCookieHost = String(hostDomainCanonical.c_str());
+ m_defaultDomainIsIPAddress = true;
+ } else
+ m_defaultCookieHost = m_defaultCookieHost.startsWith(".") ? m_defaultCookieHost : "." + m_defaultCookieHost;
}
CookieParser::~CookieParser()
@@ -260,24 +268,38 @@
// For example: ab.c.com dose not domain match b.c.com;
String realDomain = parsedValue[0] == '.' ? parsedValue : "." + parsedValue;
- // The request host should domain match the Domain attribute.
- // Domain string starts with a dot, so a.b.com should domain match .a.b.com.
- // add a "." at beginning of host name, because it can handle many cases such as
- // a.b.com matches b.com, a.b.com matches .B.com and a.b.com matches .A.b.Com
- // and so on.
- String hostDomainName = m_defaultCookieURL.host();
- hostDomainName = hostDomainName.startsWith('.') ? hostDomainName : "." + hostDomainName;
- if (!hostDomainName.endsWith(realDomain, false))
- LOG_AND_DELETE("Invalid cookie %s (domain): it does not domain match the host");
- // We should check for an embedded dot in the portion of string in the host not in the domain
- // but to match firefox behaviour we do not.
+ // Try to return an canonical ip address if the domain is an ip
- // Check whether the domain is a top level domain, if it is throw it out
- // http://publicsuffix.org/list/
- if (BlackBerry::Platform::isTopLevelDomain(realDomain.utf8().data()))
- LOG_AND_DELETE("Invalid cookie %s (domain): it did not pass the top level domain check", cookie.ascii().data());
+ bool isIPAddress = false;
+ // We only check if the current domain is an IP address when the default domain is an IP address
+ // We know if the default domain is not an IP address and the current domain is, it won't suffix match
+ // If it is an IP Address, we should treat it only if it matches the host exactly
+ // We determine the canonical IP format before comparing because IPv6 could be represented in multiple formats
+ if (m_defaultDomainIsIPAddress) {
+ String realDomainCanonical = String(BlackBerry::Platform::getCanonicalIPFormat(realDomain.utf8().data()).c_str());
+ if (realDomainCanonical.isEmpty() || realDomainCanonical != m_defaultCookieHost)
+ LOG_AND_DELETE("Invalid cookie %s (domain): domain is IP but does not match host's IP", cookie.ascii().data());
+ realDomain = realDomainCanonical;
+ isIPAddress = true;
+ } else {
+ // The request host should domain match the Domain attribute.
+ // Domain string starts with a dot, so a.b.com should domain match .a.b.com.
+ // add a "." at beginning of host name, because it can handle many cases such as
+ // a.b.com matches b.com, a.b.com matches .B.com and a.b.com matches .A.b.Com
+ // and so on.
+ // We also have to make a special case for IP addresses. If a website tries to set
+ // a cookie to 61.97, that domain is not an IP address and will end with the m_defaultCookieHost
+ if (!m_defaultCookieHost.endsWith(realDomain, false))
+ LOG_AND_DELETE("Invalid cookie %s (domain): it does not domain match the host", cookie.ascii().data());
+ // We should check for an embedded dot in the portion of string in the host not in the domain
+ // but to match firefox behaviour we do not.
- res->setDomain(realDomain);
+ // Check whether the domain is a top level domain, if it is throw it out
+ // http://publicsuffix.org/list/
+ if (BlackBerry::Platform::isTopLevelDomain(realDomain.utf8().data()))
+ LOG_AND_DELETE("Invalid cookie %s (domain): it did not pass the top level domain check", cookie.ascii().data());
+ }
+ res->setDomain(realDomain, isIPAddress);
} else
LOG_AND_DELETE("Invalid cookie %s (domain)", cookie.ascii().data());
break;
@@ -363,7 +385,7 @@
// If no domain was provided, set it to the host
if (!res->domain())
- res->setDomain(m_defaultCookieURL.host());
+ res->setDomain(m_defaultCookieHost, m_defaultDomainIsIPAddress);
// According to the Cookie Specificaiton (RFC6265, section 4.1.2.4 and 5.2.4, http://tools.ietf.org/html/rfc6265),
// If no path was provided or the first character of the path value is not '/', set it to the host's path
Modified: trunk/Source/WebCore/platform/blackberry/CookieParser.h (127149 => 127150)
--- trunk/Source/WebCore/platform/blackberry/CookieParser.h 2012-08-30 16:08:27 UTC (rev 127149)
+++ trunk/Source/WebCore/platform/blackberry/CookieParser.h 2012-08-30 16:12:13 UTC (rev 127150)
@@ -50,6 +50,8 @@
ParsedCookie* parseOneCookie(const String& cookie, unsigned start, unsigned end, double curTime);
KURL m_defaultCookieURL;
+ String m_defaultCookieHost;
+ bool m_defaultDomainIsIPAddress;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/blackberry/ParsedCookie.cpp (127149 => 127150)
--- trunk/Source/WebCore/platform/blackberry/ParsedCookie.cpp 2012-08-30 16:08:27 UTC (rev 127149)
+++ trunk/Source/WebCore/platform/blackberry/ParsedCookie.cpp 2012-08-30 16:12:13 UTC (rev 127150)
@@ -45,6 +45,7 @@
, m_isHttpOnly(false)
, m_isSession(true)
, m_isForceExpired(false)
+ , m_domainIsIPAddress(false)
{
}
@@ -61,6 +62,7 @@
, m_isHttpOnly(isHttpOnly)
, m_isSession(false)
, m_isForceExpired(false)
+ , m_domainIsIPAddress(false)
{
}
@@ -77,6 +79,7 @@
, m_isHttpOnly(cookie->m_isHttpOnly)
, m_isSession(cookie->m_isSession)
, m_isForceExpired(cookie->m_isForceExpired)
+ , m_domainIsIPAddress(cookie->m_domainIsIPAddress)
{
}
Modified: trunk/Source/WebCore/platform/blackberry/ParsedCookie.h (127149 => 127150)
--- trunk/Source/WebCore/platform/blackberry/ParsedCookie.h 2012-08-30 16:08:27 UTC (rev 127149)
+++ trunk/Source/WebCore/platform/blackberry/ParsedCookie.h 2012-08-30 16:12:13 UTC (rev 127150)
@@ -63,7 +63,7 @@
void setPath(const String& path) { m_path = path; }
const String& domain() const { return m_domain; }
- void setDomain(const String& domain) { m_domain = domain.lower(); }
+ void setDomain(const String& domain, bool domainIsIPAddress = false) { m_domain = domain.lower(); m_domainIsIPAddress = domainIsIPAddress; }
const String& protocol() const { return m_protocol; }
void setProtocol(const String& protocol) { m_protocol = protocol; }
@@ -90,6 +90,7 @@
bool hasExpired() const;
bool isForceExpired() const { return m_isForceExpired; }
bool isUnderSizeLimit() const;
+ bool domainIsIPAddress() const { return m_domainIsIPAddress; }
String toString() const;
String toNameValuePair() const;
@@ -110,6 +111,7 @@
bool m_isHttpOnly;
bool m_isSession;
bool m_isForceExpired;
+ bool m_domainIsIPAddress;
};
} // namespace WebCore