diff options
author | Andreas Kling <kling@serenityos.org> | 2020-09-22 18:26:33 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-22 20:10:20 +0200 |
commit | 37c287b1d4b8bcc936e79a3d7b9280a329fa19e3 (patch) | |
tree | 8253492b65f86e911e76374bba76ab9ba5409d9b | |
parent | 4c1f31757208df3057f963363c102c47fdb68c73 (diff) | |
download | serenity-37c287b1d4b8bcc936e79a3d7b9280a329fa19e3.zip |
LibWeb: Disallow cross-origin access to <iframe>.contentDocument
With this patch, we now enforce basic same-origin policy for this one
<iframe> attribute.
To make it easier to add more attributes like this, I've added an
extended IDL attribute ("[ReturnNullIfCrossOrigin]") that does exactly
what it sounds like. :^)
-rw-r--r-- | Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp | 9 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLIFrameElement.cpp | 17 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLIFrameElement.h | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLIFrameElement.idl | 3 |
4 files changed, 28 insertions, 4 deletions
diff --git a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index 570089bc28..4d0365b109 100644 --- a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -445,8 +445,9 @@ void generate_implementation(const IDL::Interface& interface) out() << "#include <LibWeb/Bindings/NodeWrapperFactory.h>"; out() << "#include <LibWeb/Bindings/" << wrapper_class << ".h>"; out() << "#include <LibWeb/DOM/Element.h>"; - out() << "#include <LibWeb/HTML/HTMLElement.h>"; out() << "#include <LibWeb/DOM/EventListener.h>"; + out() << "#include <LibWeb/HTML/HTMLElement.h>"; + out() << "#include <LibWeb/Origin.h>"; out() << "#include <LibWeb/Bindings/CommentWrapper.h>"; out() << "#include <LibWeb/Bindings/DocumentWrapper.h>"; out() << "#include <LibWeb/Bindings/DocumentFragmentWrapper.h>"; @@ -457,6 +458,7 @@ void generate_implementation(const IDL::Interface& interface) out() << "#include <LibWeb/Bindings/ImageDataWrapper.h>"; out() << "#include <LibWeb/Bindings/TextWrapper.h>"; out() << "#include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>"; + out() << "#include <LibWeb/Bindings/WindowObject.h>"; // FIXME: This is a total hack until we can figure out the namespace for a given type somehow. out() << "using namespace Web::DOM;"; @@ -606,6 +608,11 @@ void generate_implementation(const IDL::Interface& interface) out() << " if (!impl)"; out() << " return {};"; + if (attribute.extended_attributes.contains("ReturnNullIfCrossOrigin")) { + out() << " if (!impl->may_access_from_origin(static_cast<WindowObject&>(global_object).origin()))"; + out() << " return JS::js_null();"; + } + if (attribute.extended_attributes.contains("Reflect")) { auto attribute_name = attribute.extended_attributes.get("Reflect").value(); if (attribute_name.is_null()) diff --git a/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp index 3c1d536c1e..7fe0c5b929 100644 --- a/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp @@ -26,17 +26,20 @@ #include <LibGUI/Button.h> #include <LibGUI/TextBox.h> +#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> +#include <LibWeb/DOM/Window.h> #include <LibWeb/Dump.h> #include <LibWeb/HTML/HTMLFormElement.h> #include <LibWeb/HTML/HTMLIFrameElement.h> #include <LibWeb/HTML/Parser/HTMLDocumentParser.h> +#include <LibWeb/InProcessWebView.h> #include <LibWeb/Layout/LayoutFrame.h> #include <LibWeb/Layout/LayoutWidget.h> #include <LibWeb/Loader/ResourceLoader.h> +#include <LibWeb/Origin.h> #include <LibWeb/Page/Frame.h> -#include <LibWeb/InProcessWebView.h> namespace Web::HTML { @@ -81,6 +84,18 @@ void HTMLIFrameElement::load_src(const String& value) m_content_frame->loader().load(url, FrameLoader::Type::IFrame); } +Origin HTMLIFrameElement::content_origin() const +{ + if (!m_content_frame || !m_content_frame->document()) + return {}; + return m_content_frame->document()->origin(); +} + +bool HTMLIFrameElement::may_access_from_origin(const Origin& origin) const +{ + return origin.is_same(content_origin()); +} + const DOM::Document* HTMLIFrameElement::content_document() const { return m_content_frame ? m_content_frame->document() : nullptr; diff --git a/Libraries/LibWeb/HTML/HTMLIFrameElement.h b/Libraries/LibWeb/HTML/HTMLIFrameElement.h index bff8692b22..2d5e138d7c 100644 --- a/Libraries/LibWeb/HTML/HTMLIFrameElement.h +++ b/Libraries/LibWeb/HTML/HTMLIFrameElement.h @@ -44,6 +44,9 @@ public: const DOM::Document* content_document() const; + Origin content_origin() const; + bool may_access_from_origin(const Origin&) const; + void content_frame_did_load(Badge<FrameLoader>); private: diff --git a/Libraries/LibWeb/HTML/HTMLIFrameElement.idl b/Libraries/LibWeb/HTML/HTMLIFrameElement.idl index 97513c966c..5a9e2bf186 100644 --- a/Libraries/LibWeb/HTML/HTMLIFrameElement.idl +++ b/Libraries/LibWeb/HTML/HTMLIFrameElement.idl @@ -7,6 +7,5 @@ interface HTMLIFrameElement : HTMLElement { [Reflect] attribute DOMString width; [Reflect] attribute DOMString height; - readonly attribute Document? contentDocument; - + [ReturnNullIfCrossOrigin] readonly attribute Document? contentDocument; } |