Changeset 77041 in webkit


Ignore:
Timestamp:
Jan 28, 2011 6:08:44 PM (13 years ago)
Author:
abarth@webkit.org
Message:

2011-01-28 Adam Barth <abarth@webkit.org>

Reviewed by Eric Seidel.

XSSFilter should log to the console when it blocks something
https://bugs.webkit.org/show_bug.cgi?id=53354

This patch refactors a bunch of methods in XSSFilter to return a bool
indicating whether they blocked anything. Using this bool, we decide
whether to log to the console. We're using the same log message as the
XSSAuditor, but it seems likely we can improve this message in the
future (especially by piping in the correct line number, which is now
accessible via the parser).

  • html/parser/XSSFilter.cpp: (WebCore::HTMLNames::isNameOfInlineEventHandler): (WebCore::XSSFilter::filterToken): (WebCore::XSSFilter::filterTokenInitial): (WebCore::XSSFilter::filterTokenAfterScriptStartTag): (WebCore::XSSFilter::filterScriptToken): (WebCore::XSSFilter::filterObjectToken): (WebCore::XSSFilter::filterEmbedToken): (WebCore::XSSFilter::filterAppletToken): (WebCore::XSSFilter::filterMetaToken): (WebCore::XSSFilter::filterBaseToken): (WebCore::XSSFilter::eraseInlineEventHandlersIfInjected):
  • html/parser/XSSFilter.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r77034 r77041  
     12011-01-28  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        XSSFilter should log to the console when it blocks something
     6        https://bugs.webkit.org/show_bug.cgi?id=53354
     7
     8        This patch refactors a bunch of methods in XSSFilter to return a bool
     9        indicating whether they blocked anything.  Using this bool, we decide
     10        whether to log to the console.  We're using the same log message as the
     11        XSSAuditor, but it seems likely we can improve this message in the
     12        future (especially by piping in the correct line number, which is now
     13        accessible via the parser).
     14
     15        * html/parser/XSSFilter.cpp:
     16        (WebCore::HTMLNames::isNameOfInlineEventHandler):
     17        (WebCore::XSSFilter::filterToken):
     18        (WebCore::XSSFilter::filterTokenInitial):
     19        (WebCore::XSSFilter::filterTokenAfterScriptStartTag):
     20        (WebCore::XSSFilter::filterScriptToken):
     21        (WebCore::XSSFilter::filterObjectToken):
     22        (WebCore::XSSFilter::filterEmbedToken):
     23        (WebCore::XSSFilter::filterAppletToken):
     24        (WebCore::XSSFilter::filterMetaToken):
     25        (WebCore::XSSFilter::filterBaseToken):
     26        (WebCore::XSSFilter::eraseInlineEventHandlersIfInjected):
     27        * html/parser/XSSFilter.h:
     28
    1292011-01-28  Adam Barth  <abarth@webkit.org>
    230
  • trunk/Source/WebCore/html/parser/XSSFilter.cpp

    r77034 r77041  
    6161}
    6262
    63 bool isNameOfScriptCarryingAttribute(const Vector<UChar, 32>& name)
    64 {
    65     const size_t lengthOfShortestScriptCarryingAttribute = 5; // To wit: oncut.
    66     if (name.size() < lengthOfShortestScriptCarryingAttribute)
     63bool isNameOfInlineEventHandler(const Vector<UChar, 32>& name)
     64{
     65    const size_t lengthOfShortestInlineEventHandlerName = 5; // To wit: oncut.
     66    if (name.size() < lengthOfShortestInlineEventHandlerName)
    6767        return false;
    6868    return name[0] == 'o' && name[1] == 'n';
     
    105105        return;
    106106
     107    bool didBlockScript = false;
     108
    107109    switch (m_state) {
    108110    case Initial:
     111        didBlockScript = filterTokenInitial(token);
    109112        break;
    110113    case AfterScriptStartTag:
    111         filterTokenAfterScriptStartTag(token);
     114        didBlockScript = filterTokenAfterScriptStartTag(token);
    112115        ASSERT(m_state == Initial);
    113116        m_cachedSnippet = String();
    114         return;
    115     }
     117        break;
     118    }
     119
     120    if (didBlockScript) {
     121        // FIXME: Consider using a more helpful console message.
     122        DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
     123        // FIXME: We should add the real line number to the console.
     124        m_parser->document()->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
     125    }
     126#endif
     127}
     128
     129bool XSSFilter::filterTokenInitial(HTMLToken& token)
     130{
     131    ASSERT(m_state == Initial);
    116132
    117133    if (token.type() != HTMLToken::StartTag)
    118         return;
     134        return false;
     135
     136    bool didBlockScript = eraseInlineEventHandlersIfInjected(token);
    119137
    120138    if (hasName(token, scriptTag))
    121         return filterScriptToken(token);
    122 
    123     if (hasName(token, objectTag))
    124         return filterObjectToken(token);
    125 
    126     if (hasName(token, embedTag))
    127         return filterEmbedToken(token);
    128 
    129     if (hasName(token, appletTag))
    130         return filterAppletToken(token);
    131 
    132     if (hasName(token, metaTag))
    133         return filterMetaToken(token);
    134 
    135     if (hasName(token, baseTag))
    136         return filterBaseToken(token);
    137 
    138     for (size_t i = 0; i < token.attributes().size(); ++i) {
    139         const HTMLToken::Attribute& attribute = token.attributes().at(i);
    140         if (!isNameOfScriptCarryingAttribute(attribute.m_name))
    141             continue;
    142         if (!isContainedInRequest(snippetForAttribute(token, attribute)))
    143             continue;
    144         token.eraseValueOfAttribute(i);
    145     }
    146 #endif
    147 }
    148 
    149 void XSSFilter::filterTokenAfterScriptStartTag(HTMLToken& token)
     139        didBlockScript |= filterScriptToken(token);
     140    else if (hasName(token, objectTag))
     141        didBlockScript |= filterObjectToken(token);
     142    else if (hasName(token, embedTag))
     143        didBlockScript |= filterEmbedToken(token);
     144    else if (hasName(token, appletTag))
     145        didBlockScript |= filterAppletToken(token);
     146    else if (hasName(token, metaTag))
     147        didBlockScript |= filterMetaToken(token);
     148    else if (hasName(token, baseTag))
     149        didBlockScript |= filterBaseToken(token);
     150
     151    return didBlockScript;
     152}
     153
     154bool XSSFilter::filterTokenAfterScriptStartTag(HTMLToken& token)
    150155{
    151156    ASSERT(m_state == AfterScriptStartTag);
     
    154159    if (token.type() != HTMLToken::Character) {
    155160        ASSERT(token.type() == HTMLToken::EndTag || token.type() == HTMLToken::EndOfFile);
    156         return;
     161        return false;
    157162    }
    158163
     
    164169        token.eraseCharacters();
    165170        token.appendToCharacter(' '); // Technically, character tokens can't be empty.
    166     }
    167 }
    168 
    169 void XSSFilter::filterScriptToken(HTMLToken& token)
     171        return true;
     172    }
     173    return false;
     174}
     175
     176bool XSSFilter::filterScriptToken(HTMLToken& token)
    170177{
    171178    ASSERT(m_state == Initial);
     
    174181
    175182    if (eraseAttributeIfInjected(token, srcAttr))
    176         return;
     183        return true;
    177184
    178185    m_state = AfterScriptStartTag;
    179186    m_cachedSnippet = m_parser->sourceForToken(token);
    180 }
    181 
    182 void XSSFilter::filterObjectToken(HTMLToken& token)
     187    return false;
     188}
     189
     190bool XSSFilter::filterObjectToken(HTMLToken& token)
    183191{
    184192    ASSERT(m_state == Initial);
     
    186194    ASSERT(hasName(token, objectTag));
    187195
    188     eraseAttributeIfInjected(token, dataAttr);
    189     eraseAttributeIfInjected(token, typeAttr);
    190     eraseAttributeIfInjected(token, classidAttr);
    191 }
    192 
    193 void XSSFilter::filterEmbedToken(HTMLToken& token)
     196    bool didBlockScript = false;
     197
     198    didBlockScript |= eraseAttributeIfInjected(token, dataAttr);
     199    didBlockScript |= eraseAttributeIfInjected(token, typeAttr);
     200    didBlockScript |= eraseAttributeIfInjected(token, classidAttr);
     201
     202    return didBlockScript;
     203}
     204
     205bool XSSFilter::filterEmbedToken(HTMLToken& token)
    194206{
    195207    ASSERT(m_state == Initial);
     
    197209    ASSERT(hasName(token, embedTag));
    198210
    199     eraseAttributeIfInjected(token, srcAttr);
    200     eraseAttributeIfInjected(token, typeAttr);
    201 }
    202 
    203 void XSSFilter::filterAppletToken(HTMLToken& token)
     211    bool didBlockScript = false;
     212
     213    didBlockScript |= eraseAttributeIfInjected(token, srcAttr);
     214    didBlockScript |= eraseAttributeIfInjected(token, typeAttr);
     215
     216    return didBlockScript;
     217}
     218
     219bool XSSFilter::filterAppletToken(HTMLToken& token)
    204220{
    205221    ASSERT(m_state == Initial);
     
    207223    ASSERT(hasName(token, appletTag));
    208224
    209     eraseAttributeIfInjected(token, codeAttr);
    210     eraseAttributeIfInjected(token, objectAttr);
    211 }
    212 
    213 void XSSFilter::filterMetaToken(HTMLToken& token)
     225    bool didBlockScript = false;
     226
     227    didBlockScript |= eraseAttributeIfInjected(token, codeAttr);
     228    didBlockScript |= eraseAttributeIfInjected(token, objectAttr);
     229
     230    return didBlockScript;
     231}
     232
     233bool XSSFilter::filterMetaToken(HTMLToken& token)
    214234{
    215235    ASSERT(m_state == Initial);
     
    217237    ASSERT(hasName(token, metaTag));
    218238
    219     eraseAttributeIfInjected(token, http_equivAttr);
    220 }
    221 
    222 void XSSFilter::filterBaseToken(HTMLToken& token)
     239    return eraseAttributeIfInjected(token, http_equivAttr);
     240}
     241
     242bool XSSFilter::filterBaseToken(HTMLToken& token)
    223243{
    224244    ASSERT(m_state == Initial);
     
    226246    ASSERT(hasName(token, baseTag));
    227247
    228     eraseAttributeIfInjected(token, hrefAttr);
     248    return eraseAttributeIfInjected(token, hrefAttr);
     249}
     250
     251bool XSSFilter::eraseInlineEventHandlersIfInjected(HTMLToken& token)
     252{
     253    bool didBlockScript = false;
     254    for (size_t i = 0; i < token.attributes().size(); ++i) {
     255        const HTMLToken::Attribute& attribute = token.attributes().at(i);
     256        if (!isNameOfInlineEventHandler(attribute.m_name))
     257            continue;
     258        if (!isContainedInRequest(snippetForAttribute(token, attribute)))
     259            continue;
     260        token.eraseValueOfAttribute(i);
     261        didBlockScript = true;
     262    }
     263    return didBlockScript;
    229264}
    230265
  • trunk/Source/WebCore/html/parser/XSSFilter.h

    r77034 r77041  
    4646    };
    4747
    48     void filterTokenAfterScriptStartTag(HTMLToken&);
    49     void filterScriptToken(HTMLToken&);
    50     void filterObjectToken(HTMLToken&);
    51     void filterEmbedToken(HTMLToken&);
    52     void filterAppletToken(HTMLToken&);
    53     void filterMetaToken(HTMLToken&);
    54     void filterBaseToken(HTMLToken&);
     48    bool filterTokenInitial(HTMLToken&);
     49    bool filterTokenAfterScriptStartTag(HTMLToken&);
    5550
     51    bool filterScriptToken(HTMLToken&);
     52    bool filterObjectToken(HTMLToken&);
     53    bool filterEmbedToken(HTMLToken&);
     54    bool filterAppletToken(HTMLToken&);
     55    bool filterMetaToken(HTMLToken&);
     56    bool filterBaseToken(HTMLToken&);
     57
     58    bool eraseInlineEventHandlersIfInjected(HTMLToken&);
    5659    bool eraseAttributeIfInjected(HTMLToken&, const QualifiedName&);
    5760
Note: See TracChangeset for help on using the changeset viewer.