Changeset 94225 in webkit


Ignore:
Timestamp:
Aug 31, 2011 1:52:10 PM (13 years ago)
Author:
commit-queue@webkit.org
Message:

Fix XSS filter bypass by multiply decoding both the URL and the body
snippet until they are in the most minimal form before comparison.
https://bugs.webkit.org/show_bug.cgi?id=66585

Patch by Tom Sepez <tsepez@chromium.org> on 2011-08-31
Reviewed by Adam Barth.

Source/WebCore:

  • html/parser/XSSAuditor.cpp:

(WebCore::fullyDecodeString):
(WebCore::XSSAuditor::init):
(WebCore::XSSAuditor::filterToken):
(WebCore::XSSAuditor::isContainedInRequest):

LayoutTests:

  • http/tests/security/xssAuditor/anchor-url-dom-write-location2.html:
  • http/tests/security/xssAuditor/resources/echo-dom-write-unescaped-location.html: Added.
Location:
trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r94224 r94225  
     12011-08-31  Tom Sepez  <tsepez@chromium.org>
     2
     3        Fix XSS filter bypass by multiply decoding both the URL and the body
     4        snippet until they are in the most minimal form before comparison.
     5        https://bugs.webkit.org/show_bug.cgi?id=66585
     6
     7        Reviewed by Adam Barth.
     8
     9        * http/tests/security/xssAuditor/anchor-url-dom-write-location2.html:
     10        * http/tests/security/xssAuditor/resources/echo-dom-write-unescaped-location.html: Added.
     11
    1122011-08-31  Cary Clark  <caryclark@google.com>
    213
  • trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location2.html

    r93745 r94225  
    1010</head>
    1111<body>
    12 <iframe src="http://localhost:8000/security/xssAuditor/resources/echo-dom-write-location.html?#<script>alert('XS%41S')</script>">
     12<iframe src="http://localhost:8000/security/xssAuditor/resources/echo-dom-write-unescaped-location.html?#<script>alert('XS%41S')</script>">
    1313</iframe>
    1414</body>
  • trunk/Source/WebCore/ChangeLog

    r94215 r94225  
     12011-08-31  Tom Sepez  <tsepez@chromium.org>
     2
     3        Fix XSS filter bypass by multiply decoding both the URL and the body
     4        snippet until they are in the most minimal form before comparison.
     5        https://bugs.webkit.org/show_bug.cgi?id=66585
     6
     7        Reviewed by Adam Barth.
     8
     9        * html/parser/XSSAuditor.cpp:
     10        (WebCore::fullyDecodeString):
     11        (WebCore::XSSAuditor::init):
     12        (WebCore::XSSAuditor::filterToken):
     13        (WebCore::XSSAuditor::isContainedInRequest):
     14
    1152011-08-31  Simon Fraser  <simon.fraser@apple.com>
    216
  • trunk/Source/WebCore/html/parser/XSSAuditor.cpp

    r91396 r94225  
    4040#include "TextEncoding.h"
    4141#include "TextResourceDecoder.h"
     42
    4243#include <wtf/text/CString.h>
    4344
     
    115116}
    116117
    117 static String decodeURL(const String& string, const TextEncoding& encoding)
    118 {
     118static String fullyDecodeString(const String& string, const TextResourceDecoder* decoder)
     119{
     120    size_t oldWorkingStringLength;
    119121    String workingString = string;
     122    do {
     123        oldWorkingStringLength = workingString.length();
     124        workingString = decodeURLEscapeSequences(workingString);
     125    } while (workingString.length() < oldWorkingStringLength);
     126    if (decoder) {
     127        CString workingStringUTF8 = workingString.utf8();
     128        String decodedString = decoder->encoding().decode(workingStringUTF8.data(), workingStringUTF8.length());
     129        if (!decodedString.isEmpty())
     130            workingString = decodedString;
     131    }
    120132    workingString.replace('+', ' ');
    121     workingString = decodeURLEscapeSequences(workingString);
    122     CString workingStringUTF8 = workingString.utf8();
    123     String decodedString = encoding.decode(workingStringUTF8.data(), workingStringUTF8.length());
    124     // FIXME: Is this check necessary?
    125     if (decodedString.isEmpty())
    126         return canonicalize(workingString);
    127     return canonicalize(decodedString);
     133    workingString = canonicalize(workingString);
     134    return workingString;
    128135}
    129136
     
    153160    if (!m_isEnabled)
    154161        return;
    155    
     162
    156163    // In theory, the Document could have detached from the Frame after the
    157164    // XSSAuditor was constructed.
     
    169176
    170177    TextResourceDecoder* decoder = m_parser->document()->decoder();
    171     m_decodedURL = decoder ? decodeURL(url.string(), decoder->encoding()) : url.string();
     178    m_decodedURL = fullyDecodeString(url.string(), decoder);
    172179    if (m_decodedURL.find(isRequiredForInjection, 0) == notFound)
    173180        m_decodedURL = String();
     
    180187        if (httpBody && !httpBody->isEmpty()) {
    181188            String httpBodyAsString = httpBody->flattenToString();
    182             m_decodedHTTPBody = decoder ? decodeURL(httpBodyAsString, decoder->encoding()) : httpBodyAsString;
     189            m_decodedHTTPBody = fullyDecodeString(httpBodyAsString, decoder);
    183190            if (m_decodedHTTPBody.find(isRequiredForInjection, 0) == notFound)
    184191                m_decodedHTTPBody = String();
     
    208215        ASSERT_NOT_REACHED();
    209216        break;
    210     case Initial: 
     217    case Initial:
    211218        didBlockScript = filterTokenInitial(token);
    212219        break;
     
    455462{
    456463    ASSERT(!snippet.isEmpty());
    457     String canonicalizedSnippet = canonicalize(snippet);
    458     ASSERT(!canonicalizedSnippet.isEmpty());
    459     if (m_decodedURL.find(canonicalizedSnippet, 0, false) != notFound)
     464    TextResourceDecoder* decoder = m_parser->document()->decoder();
     465    String decodedSnippet = fullyDecodeString(snippet, decoder);
     466    if (decodedSnippet.isEmpty())
     467        return false;
     468    if (m_decodedURL.find(decodedSnippet, 0, false) != notFound)
    460469        return true;
    461     if (m_decodedHTTPBodySuffixTree && !m_decodedHTTPBodySuffixTree->mightContain(canonicalizedSnippet))
    462         return false;
    463     return m_decodedHTTPBody.find(canonicalizedSnippet, 0, false) != notFound;
     470    if (m_decodedHTTPBodySuffixTree && !m_decodedHTTPBodySuffixTree->mightContain(decodedSnippet))
     471        return false;
     472    return m_decodedHTTPBody.find(decodedSnippet, 0, false) != notFound;
    464473}
    465474
Note: See TracChangeset for help on using the changeset viewer.