diff options
Diffstat (limited to 'Source/WebCore/page/XSSAuditor.h')
-rw-r--r-- | Source/WebCore/page/XSSAuditor.h | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/Source/WebCore/page/XSSAuditor.h b/Source/WebCore/page/XSSAuditor.h new file mode 100644 index 0000000..2b781f1 --- /dev/null +++ b/Source/WebCore/page/XSSAuditor.h @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2008, 2009 Daniel Bates (dbates@intudata.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef XSSAuditor_h +#define XSSAuditor_h + +#include "HTTPParsers.h" +#include "PlatformString.h" +#include "SuffixTree.h" +#include "TextEncoding.h" + +namespace WebCore { + + class FormData; + class Frame; + class ScriptSourceCode; + + // The XSSAuditor class is used to prevent type 1 cross-site scripting + // vulnerabilities (also known as reflected vulnerabilities). + // + // More specifically, the XSSAuditor class decides whether the execution of + // a script is to be allowed or denied based on the content of any + // user-submitted data, including: + // + // * the URL. + // * the HTTP-POST data. + // + // If the source code of a script resembles any user-submitted data then it + // is denied execution. + // + // When you instantiate the XSSAuditor you must specify the Frame of the + // page that you wish to audit. + // + // Bindings + // + // An XSSAuditor is instantiated within the constructor of a + // ScriptController object and passed the Frame the script originated. The + // ScriptController calls back to the XSSAuditor to determine whether a + // JavaScript script is safe to execute before executing it. The following + // methods call into XSSAuditor: + // + // * ScriptController::evaluateInWorld - used to evaluate JavaScript scripts. + // * ScriptController::executeIfJavaScriptURL - used to evaluate JavaScript URLs. + // * ScriptEventListener::createAttributeEventListener - used to create JavaScript event handlers. + // * HTMLBaseElement::process - used to set the document base URL. + // * HTMLDocumentParser::shouldLoadExternalScriptFromSrc - used to load external JavaScript scripts. + // * SubframeLoader::requestObject - used to load <object>/<embed> elements. + // + class XSSAuditor : public Noncopyable { + public: + XSSAuditor(Frame*); + ~XSSAuditor(); + + bool isEnabled() const; + + // Determines whether the script should be allowed or denied execution + // based on the content of any user-submitted data. + bool canEvaluate(const String& code) const; + + // Determines whether the JavaScript URL should be allowed or denied execution + // based on the content of any user-submitted data. + bool canEvaluateJavaScriptURL(const String& code) const; + + // Determines whether the event listener should be created based on the + // content of any user-submitted data. + bool canCreateInlineEventListener(const String& functionName, const String& code) const; + + // Determines whether the external script should be loaded based on the + // content of any user-submitted data. + bool canLoadExternalScriptFromSrc(const String& url) const; + + // Determines whether object should be loaded based on the content of + // any user-submitted data. + // + // This method is called by SubframeLoader::requestObject. + bool canLoadObject(const String& url) const; + + // Determines whether the base URL should be changed based on the content + // of any user-submitted data. + // + // This method is called by HTMLBaseElement::process. + bool canSetBaseElementURL(const String& url) const; + + private: + class CachingURLCanonicalizer + { + public: + CachingURLCanonicalizer() : m_decodeEntities(false), m_decodeURLEscapeSequencesTwice(false), m_generation(0) { } + String canonicalizeURL(FormData*, const TextEncoding& encoding, bool decodeEntities, + bool decodeURLEscapeSequencesTwice); + String canonicalizeURL(const String& url, const TextEncoding& encoding, bool decodeEntities, + bool decodeURLEscapeSequencesTwice); + + void clear(); + + int generation() const { return m_generation; } + + private: + // The parameters we were called with last. + String m_inputURL; + TextEncoding m_encoding; + bool m_decodeEntities; + bool m_decodeURLEscapeSequencesTwice; + RefPtr<FormData> m_formData; + + // Incremented every time we see a new URL. + int m_generation; + + // The cached result. + String m_cachedCanonicalizedURL; + }; + + struct FindTask { + FindTask() + : decodeEntities(true) + , allowRequestIfNoIllegalURICharacters(false) + , decodeURLEscapeSequencesTwice(false) + { + } + + String context; + String string; + bool decodeEntities; + bool allowRequestIfNoIllegalURICharacters; + bool decodeURLEscapeSequencesTwice; + }; + + static String canonicalize(const String&); + static String decodeURL(const String& url, const TextEncoding& encoding, bool decodeEntities, + bool decodeURLEscapeSequencesTwice = false); + static String decodeHTMLEntities(const String&, bool leaveUndecodableEntitiesUntouched = true); + + bool isSameOriginResource(const String& url) const; + bool findInRequest(const FindTask&) const; + bool findInRequest(Frame*, const FindTask&) const; + + XSSProtectionDisposition xssProtection() const; + + // The frame to audit. + Frame* m_frame; + + // A state store to help us avoid canonicalizing the same URL repeated. + // When a page has form data, we need two caches: one to store the + // canonicalized URL and another to store the cannonicalized form + // data. If we only had one cache, we'd always generate a cache miss + // and load some pages extremely slowly. + // https://bugs.webkit.org/show_bug.cgi?id=35373 + mutable CachingURLCanonicalizer m_pageURLCache; + mutable CachingURLCanonicalizer m_formDataCache; + + mutable OwnPtr<SuffixTree<ASCIICodebook> > m_formDataSuffixTree; + mutable int m_generationOfSuffixTree; + }; + +} // namespace WebCore + +#endif // XSSAuditor_h |