mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:52:43 +00:00 
			
		
		
		
	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. :^)
			
			
This commit is contained in:
		
							parent
							
								
									4c1f317572
								
							
						
					
					
						commit
						37c287b1d4
					
				
					 4 changed files with 28 additions and 4 deletions
				
			
		|  | @ -445,8 +445,9 @@ void generate_implementation(const IDL::Interface& interface) | ||||||
|     out() << "#include <LibWeb/Bindings/NodeWrapperFactory.h>"; |     out() << "#include <LibWeb/Bindings/NodeWrapperFactory.h>"; | ||||||
|     out() << "#include <LibWeb/Bindings/" << wrapper_class << ".h>"; |     out() << "#include <LibWeb/Bindings/" << wrapper_class << ".h>"; | ||||||
|     out() << "#include <LibWeb/DOM/Element.h>"; |     out() << "#include <LibWeb/DOM/Element.h>"; | ||||||
|     out() << "#include <LibWeb/HTML/HTMLElement.h>"; |  | ||||||
|     out() << "#include <LibWeb/DOM/EventListener.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/CommentWrapper.h>"; | ||||||
|     out() << "#include <LibWeb/Bindings/DocumentWrapper.h>"; |     out() << "#include <LibWeb/Bindings/DocumentWrapper.h>"; | ||||||
|     out() << "#include <LibWeb/Bindings/DocumentFragmentWrapper.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/ImageDataWrapper.h>"; | ||||||
|     out() << "#include <LibWeb/Bindings/TextWrapper.h>"; |     out() << "#include <LibWeb/Bindings/TextWrapper.h>"; | ||||||
|     out() << "#include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.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.
 |     // FIXME: This is a total hack until we can figure out the namespace for a given type somehow.
 | ||||||
|     out() << "using namespace Web::DOM;"; |     out() << "using namespace Web::DOM;"; | ||||||
|  | @ -606,6 +608,11 @@ void generate_implementation(const IDL::Interface& interface) | ||||||
|         out() << "    if (!impl)"; |         out() << "    if (!impl)"; | ||||||
|         out() << "        return {};"; |         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")) { |         if (attribute.extended_attributes.contains("Reflect")) { | ||||||
|             auto attribute_name = attribute.extended_attributes.get("Reflect").value(); |             auto attribute_name = attribute.extended_attributes.get("Reflect").value(); | ||||||
|             if (attribute_name.is_null()) |             if (attribute_name.is_null()) | ||||||
|  |  | ||||||
|  | @ -26,17 +26,20 @@ | ||||||
| 
 | 
 | ||||||
| #include <LibGUI/Button.h> | #include <LibGUI/Button.h> | ||||||
| #include <LibGUI/TextBox.h> | #include <LibGUI/TextBox.h> | ||||||
|  | #include <LibWeb/Bindings/WindowObject.h> | ||||||
| #include <LibWeb/DOM/Document.h> | #include <LibWeb/DOM/Document.h> | ||||||
| #include <LibWeb/DOM/Event.h> | #include <LibWeb/DOM/Event.h> | ||||||
|  | #include <LibWeb/DOM/Window.h> | ||||||
| #include <LibWeb/Dump.h> | #include <LibWeb/Dump.h> | ||||||
| #include <LibWeb/HTML/HTMLFormElement.h> | #include <LibWeb/HTML/HTMLFormElement.h> | ||||||
| #include <LibWeb/HTML/HTMLIFrameElement.h> | #include <LibWeb/HTML/HTMLIFrameElement.h> | ||||||
| #include <LibWeb/HTML/Parser/HTMLDocumentParser.h> | #include <LibWeb/HTML/Parser/HTMLDocumentParser.h> | ||||||
|  | #include <LibWeb/InProcessWebView.h> | ||||||
| #include <LibWeb/Layout/LayoutFrame.h> | #include <LibWeb/Layout/LayoutFrame.h> | ||||||
| #include <LibWeb/Layout/LayoutWidget.h> | #include <LibWeb/Layout/LayoutWidget.h> | ||||||
| #include <LibWeb/Loader/ResourceLoader.h> | #include <LibWeb/Loader/ResourceLoader.h> | ||||||
|  | #include <LibWeb/Origin.h> | ||||||
| #include <LibWeb/Page/Frame.h> | #include <LibWeb/Page/Frame.h> | ||||||
| #include <LibWeb/InProcessWebView.h> |  | ||||||
| 
 | 
 | ||||||
| namespace Web::HTML { | namespace Web::HTML { | ||||||
| 
 | 
 | ||||||
|  | @ -81,6 +84,18 @@ void HTMLIFrameElement::load_src(const String& value) | ||||||
|     m_content_frame->loader().load(url, FrameLoader::Type::IFrame); |     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 | const DOM::Document* HTMLIFrameElement::content_document() const | ||||||
| { | { | ||||||
|     return m_content_frame ? m_content_frame->document() : nullptr; |     return m_content_frame ? m_content_frame->document() : nullptr; | ||||||
|  |  | ||||||
|  | @ -44,6 +44,9 @@ public: | ||||||
| 
 | 
 | ||||||
|     const DOM::Document* content_document() const; |     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>); |     void content_frame_did_load(Badge<FrameLoader>); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |  | ||||||
|  | @ -7,6 +7,5 @@ interface HTMLIFrameElement : HTMLElement { | ||||||
|     [Reflect] attribute DOMString width; |     [Reflect] attribute DOMString width; | ||||||
|     [Reflect] attribute DOMString height; |     [Reflect] attribute DOMString height; | ||||||
| 
 | 
 | ||||||
|     readonly attribute Document? contentDocument; |     [ReturnNullIfCrossOrigin] readonly attribute Document? contentDocument; | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling