Modified: trunk/Source/WebCore/html/parser/XSSAuditor.cpp (97714 => 97715)
--- trunk/Source/WebCore/html/parser/XSSAuditor.cpp 2011-10-18 04:31:00 UTC (rev 97714)
+++ trunk/Source/WebCore/html/parser/XSSAuditor.cpp 2011-10-18 04:37:22 UTC (rev 97715)
@@ -353,7 +353,7 @@
ASSERT(token.type() == HTMLTokenTypes::StartTag);
ASSERT(hasName(token, scriptTag));
- if (eraseAttributeIfInjected(token, srcAttr, blankURL().string()))
+ if (eraseAttributeIfInjected(token, srcAttr, blankURL().string(), SrcLikeAttribute))
return true;
m_state = AfterScriptStartTag;
@@ -369,7 +369,7 @@
bool didBlockScript = false;
- didBlockScript |= eraseAttributeIfInjected(token, dataAttr, blankURL().string());
+ didBlockScript |= eraseAttributeIfInjected(token, dataAttr, blankURL().string(), SrcLikeAttribute);
didBlockScript |= eraseAttributeIfInjected(token, typeAttr);
didBlockScript |= eraseAttributeIfInjected(token, classidAttr);
@@ -392,7 +392,7 @@
if (!HTMLParamElement::isURLParameter(name))
return false;
- return eraseAttributeIfInjected(token, valueAttr, blankURL().string());
+ return eraseAttributeIfInjected(token, valueAttr, blankURL().string(), SrcLikeAttribute);
}
bool XSSAuditor::filterEmbedToken(HTMLToken& token)
@@ -403,7 +403,7 @@
bool didBlockScript = false;
- didBlockScript |= eraseAttributeIfInjected(token, srcAttr, blankURL().string());
+ didBlockScript |= eraseAttributeIfInjected(token, srcAttr, blankURL().string(), SrcLikeAttribute);
didBlockScript |= eraseAttributeIfInjected(token, typeAttr);
return didBlockScript;
@@ -417,7 +417,7 @@
bool didBlockScript = false;
- didBlockScript |= eraseAttributeIfInjected(token, codeAttr);
+ didBlockScript |= eraseAttributeIfInjected(token, codeAttr, String(), SrcLikeAttribute);
didBlockScript |= eraseAttributeIfInjected(token, objectAttr);
return didBlockScript;
@@ -429,7 +429,7 @@
ASSERT(token.type() == HTMLTokenTypes::StartTag);
ASSERT(hasName(token, iframeTag));
- return eraseAttributeIfInjected(token, srcAttr);
+ return eraseAttributeIfInjected(token, srcAttr, String(), SrcLikeAttribute);
}
bool XSSAuditor::filterMetaToken(HTMLToken& token)
@@ -502,12 +502,12 @@
return didBlockScript;
}
-bool XSSAuditor::eraseAttributeIfInjected(HTMLToken& token, const QualifiedName& attributeName, const String& replacementValue)
+bool XSSAuditor::eraseAttributeIfInjected(HTMLToken& token, const QualifiedName& attributeName, const String& replacementValue, AttributeKind treatment)
{
size_t indexOfAttribute;
if (findAttributeWithName(token, attributeName, indexOfAttribute)) {
const HTMLToken::Attribute& attribute = token.attributes().at(indexOfAttribute);
- if (isContainedInRequest(decodedSnippetForAttribute(token, attribute))) {
+ if (isContainedInRequest(decodedSnippetForAttribute(token, attribute, treatment))) {
if (attributeName == srcAttr && isSameOriginResource(String(attribute.m_value.data(), attribute.m_value.size())))
return false;
if (attributeName == http_equivAttr && !isDangerousHTTPEquiv(String(attribute.m_value.data(), attribute.m_value.size())))
@@ -528,7 +528,7 @@
return m_parser->sourceForToken(token).substring(start, end - start);
}
-String XSSAuditor::decodedSnippetForAttribute(const HTMLToken& token, const HTMLToken::Attribute& attribute)
+String XSSAuditor::decodedSnippetForAttribute(const HTMLToken& token, const HTMLToken::Attribute& attribute, AttributeKind treatment)
{
const size_t kMaximumSnippetLength = 100;
@@ -540,6 +540,20 @@
int end = attribute.m_valueRange.m_end - token.startIndex();
String decodedSnippet = fullyDecodeString(snippetForRange(token, start, end), m_parser->document()->decoder());
decodedSnippet.truncate(kMaximumSnippetLength);
+ if (treatment == SrcLikeAttribute) {
+ int slashCount;
+ size_t currentLength;
+ // Characters following the first ?, #, or third slash may come from
+ // the page itself and can be merely ignored by an attacker's server
+ // when a remote script or script-like resource is requested.
+ for (slashCount = 0, currentLength = 0; currentLength < decodedSnippet.length(); ++currentLength) {
+ if (decodedSnippet[currentLength] == '?' || decodedSnippet[currentLength] == '#'
+ || ((decodedSnippet[currentLength] == '/' || decodedSnippet[currentLength] == '\\') && ++slashCount > 2)) {
+ decodedSnippet.truncate(currentLength);
+ break;
+ }
+ }
+ }
return decodedSnippet;
}
@@ -566,7 +580,6 @@
return (m_parser->document()->url().host() == resourceURL.host() && resourceURL.query().isEmpty());
}
-
String XSSAuditor::snippetForJavaScript(const String& string)
{
const size_t kMaximumFragmentLengthTarget = 100;
Modified: trunk/Source/WebCore/html/parser/XSSAuditor.h (97714 => 97715)
--- trunk/Source/WebCore/html/parser/XSSAuditor.h 2011-10-18 04:31:00 UTC (rev 97714)
+++ trunk/Source/WebCore/html/parser/XSSAuditor.h 2011-10-18 04:37:22 UTC (rev 97715)
@@ -48,6 +48,11 @@
AfterScriptStartTag,
};
+ enum AttributeKind {
+ NormalAttribute,
+ SrcLikeAttribute
+ };
+
void init();
bool filterTokenInitial(HTMLToken&);
@@ -64,11 +69,11 @@
bool filterFormToken(HTMLToken&);
bool eraseDangerousAttributesIfInjected(HTMLToken&);
- bool eraseAttributeIfInjected(HTMLToken&, const QualifiedName&, const String& replacementValue = String());
+ bool eraseAttributeIfInjected(HTMLToken&, const QualifiedName&, const String& replacementValue = String(), AttributeKind treatment = NormalAttribute);
String snippetForRange(const HTMLToken&, int start, int end);
String snippetForJavaScript(const String&);
- String decodedSnippetForAttribute(const HTMLToken&, const HTMLToken::Attribute&);
+ String decodedSnippetForAttribute(const HTMLToken&, const HTMLToken::Attribute&, AttributeKind treatment = NormalAttribute);
bool isContainedInRequest(const String&);
bool isSameOriginResource(const String& url);