XSS Auditor bypass via script tag src=data:, URLS.
authortsepez@chromium.org <tsepez@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Mar 2012 02:13:24 +0000 (02:13 +0000)
committertsepez@chromium.org <tsepez@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Mar 2012 02:13:24 +0000 (02:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=81948

Reviewed by Adam Barth.

Source/WebCore:

This change fixes an XSSAuditor bypass wherby a script with a data: URL src
attribute could evade detection by using characters from the page to create
a snippet for matching not found in the URL's reflected vector.  This change
terminates the snippet for matching earlier in these cases.

Test: http/tests/security/xssAuditor/script-tag-with-source-data-url2.html

* html/parser/XSSAuditor.cpp:
(WebCore::XSSAuditor::decodedSnippetForAttribute):

LayoutTests:

Add a test that data: URLs can't bypass xssauditor with trailing comments.

* http/tests/security/xssAuditor/script-tag-with-source-data-url2-expected.txt: Added.
* http/tests/security/xssAuditor/script-tag-with-source-data-url2.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@111808 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/http/tests/security/xssAuditor/script-tag-with-source-data-url2-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/xssAuditor/script-tag-with-source-data-url2.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/parser/XSSAuditor.cpp

index aa95367f25793be244883ca0483038707d8e522a..efa4840c520ac7a643258183e0e6d5f33a0d7864 100644 (file)
@@ -1,3 +1,15 @@
+2012-03-22  Tom Sepez  <tsepez@chromium.org>
+
+        XSS Auditor bypass via script tag src=data:, URLS.
+        https://bugs.webkit.org/show_bug.cgi?id=81948
+
+        Reviewed by Adam Barth.
+
+        Add a test that data: URLs can't bypass xssauditor with trailing comments.
+        
+        * http/tests/security/xssAuditor/script-tag-with-source-data-url2-expected.txt: Added.
+        * http/tests/security/xssAuditor/script-tag-with-source-data-url2.html: Added.
+
 2012-03-22  Dave Tharp  <dtharp@codeaurora.org>
 
         QT 4.8 soft hyphen bug has no failing test case
diff --git a/LayoutTests/http/tests/security/xssAuditor/script-tag-with-source-data-url2-expected.txt b/LayoutTests/http/tests/security/xssAuditor/script-tag-with-source-data-url2-expected.txt
new file mode 100644 (file)
index 0000000..f0ecf3d
--- /dev/null
@@ -0,0 +1,3 @@
+CONSOLE MESSAGE: Refused to execute a JavaScript script. Source code of script found within request.
+
+
diff --git a/LayoutTests/http/tests/security/xssAuditor/script-tag-with-source-data-url2.html b/LayoutTests/http/tests/security/xssAuditor/script-tag-with-source-data-url2.html
new file mode 100644 (file)
index 0000000..33cc837
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.layoutTestController) {
+  layoutTestController.dumpAsText();
+  layoutTestController.setXSSAuditorEnabled(true);
+}
+</script>
+</head>
+<body>
+<iframe src="http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?clutter=<b>***</b>&q=<script%20src=%22data:,alert(1)//&q2=%22></script>">
+</iframe>
+</body>
+</html>
index 9e90483ba16cbb26a1f7d227cd677e9ee594d980..4e163742f210b8039315f97ea984221fee5e33de 100644 (file)
@@ -1,3 +1,20 @@
+2012-03-22  Tom Sepez  <tsepez@chromium.org>
+
+        XSS Auditor bypass via script tag src=data:, URLS.
+        https://bugs.webkit.org/show_bug.cgi?id=81948
+
+        Reviewed by Adam Barth.
+
+        This change fixes an XSSAuditor bypass wherby a script with a data: URL src
+        attribute could evade detection by using characters from the page to create
+        a snippet for matching not found in the URL's reflected vector.  This change 
+        terminates the snippet for matching earlier in these cases.
+        
+        Test: http/tests/security/xssAuditor/script-tag-with-source-data-url2.html
+
+        * html/parser/XSSAuditor.cpp:
+        (WebCore::XSSAuditor::decodedSnippetForAttribute):
+
 2012-03-22  Dana Jansens  <danakj@chromium.org>
 
         [chromium] Incorrect assert on animating opacity for a surface
index 3812cd9d5579431f30a6825fef214b5ec1e0831b..b56db5f3dddb25f99a939439e7d139b111086340 100644 (file)
@@ -516,17 +516,23 @@ String XSSAuditor::decodedSnippetForAttribute(const HTMLToken& token, const HTML
     String decodedSnippet = fullyDecodeString(m_parser->sourceForToken(token).substring(start, end - start), m_parser->document()->decoder());
     decodedSnippet.truncate(kMaximumFragmentLengthTarget);
     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)) {
+        int slashCount = 0;
+        bool commaSeen = false;
+        // In HTTP URLs, 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. In DATA URLS, the payload starts at
+        // the first comma, and the the first /* or // may introduce a comment. Characters
+        // following this may come from the page itself and may be ignored when the script is
+        // executed. For simplicity, we don't differentiate based on URL scheme, and stop at
+        // the first # or ?, the third slash, or the first slash once a comma is seen.
+        for (size_t currentLength = 0; currentLength < decodedSnippet.length(); ++currentLength) {
+            UChar currentChar = decodedSnippet[currentLength];
+            if (currentChar == '?' || currentChar == '#' || ((currentChar == '/' || currentChar == '\\') && (commaSeen || ++slashCount > 2))) {
                 decodedSnippet.truncate(currentLength);
                 break;
             }
+            if (currentChar == ',')
+                commaSeen = true;
         }
     }
     return decodedSnippet;