[PP-1] Validate alternate domain for oEmbed iFrame

Created on 25 April 2018, about 6 years ago
Updated 10 March 2024, 4 months ago

Problem/Motivation

This is issue is spun off from UX team feedback on #2831944-203: Implement media source plugin for remote video via oEmbed โ†’ .

For security reasons, the oEmbed system uses an iframe to serve content from a third-party oEmbed provider. By default. the iframe is served from the same domain as the main Drupal site, but this is not secure. Therefore, Media introduced a setting, exposed in a configuration form, which allows site builders/admins to set up an alternate domain from which to serve the iframe.

In order to serve oEmbed content more securely, the iFrame domain needs to point to the Drupal site. This is explained on the form, but not validated in any way.

Proposed resolution

It would be nice to add some sort of validation to ensure that the iFrame domain is actually pointing to the Drupal site, because if it isn't, then almost all oEmbed content on the site will break (404 errors or worse), which scare the pants off of our users.

Remaining tasks

  1. Discuss if we should even do this, and if so, how to do it in a way that will please the security team.
  2. Write a patch
  3. Review it until we're all sick of looking at it
  4. Commit it

User interface changes

TBD, but probably none.

API changes

TBD, but probably minimal or none.

Data model changes

None anticipated.

โœจ Feature request
Status

Postponed

Version

11.0 ๐Ÿ”ฅ

Component
Mediaย  โ†’

Last updated 1 minute ago

Created by

๐Ÿ‡บ๐Ÿ‡ธUnited States phenaproxima Massachusetts

Live updates comments and jobs are added and updated live.
  • Security

    It is used for security vulnerabilities which do not need a security advisory. For example, security issues in projects which do not have security advisory coverage, or forward-porting a change already disclosed in a security advisory. See Drupalโ€™s security advisory policy for details. Be careful publicly disclosing security vulnerabilities! Use the โ€œReport a security vulnerabilityโ€ link in the project pageโ€™s sidebar. See how to report a security issue for details.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States sidgrafix

    I have a working solution for anyone still looking.

    Requirements:
    - Website hosted on Apache 2.4+ platform with access to Drupals core .htaccess file.
    - Domain CNAME DNS record for a Subdomain pointing to your main domain
    - The 'Content-Security-Policy' (CSP) โ†’ module installed
    - (optional) The REMOTE_ADDR [IP Address] found under Apache Environment listed on php-info (admin/reports/status/php) page. I'm not sure if it will be available for anyone on a shared hosting platform without a dedicated IP address. Also if it matches your IP don't use it (I read somewhere the REMOTE_ADDR is the users IP when not set/specified) and if that is the case it won't work in a live hosting environment. For my use case the REMOTE_ADDR is static and was the option I chose for the allowed access.

    Note: in the following example the subdomain is 'media' using 'example.com' as the domain - change those to match your subdomain and domain.

    Assuming you have a correctly set up CNAME DNS record specifically for use as the alternate domain used for the oEmbed media option setting.

    If you were just starting to set things up - by default without any modifications this would mean anyone visiting "media.example.com" would see and have access to the same Drupal site at "example.com". Bad for two reasons SEO and user confusion, but we will fix that.

    - That said, if you create content at this point on "example.com" and add a linked video from say youtube via a media field, you would likely run into cross site load error where the iframe should display when viewing the published content and is were the CSP module helps.

    - If your at this point activate the (CSP) Content-Security-Policy module and at a minimum you'll have to configure in "Enforced" Policies "Directives" "frame-ancestors" by checking it on, setting the sub option "Self" and then adding your subdomain to the "Additional Sources" https://media.example.com

    - Odds are "when using this module" especially if this is a live site you'll also have to set additional policies because by default it acts as security measure and denies other scripts and resources your site will try to load for example google maps and other 3rd party scripts and css. This can be a little complicated but easiest way to get through it is to use your browsers console which will output each denial with a tag that will match in CSP modules "Enforced" "Directives" like 'object-src and script-src', I found anything related to the oEmbed media coming from the subdomain by ticking on "self" and adding the subdomain to additional sources as well as enabling whatever identifier the browser console displayed for that "Directive" like 'unsafe-inline or unsafe-hashes' got everything working, for some of the others (3rd party sources also loading on the page) you may need to play with the settings a little to you get everything working without any errors or notices. I also disabled "Report Only" polies options by unchecking "Enable 'Report Only'".

    There is probably an even easier way aside from the use of the SCP module, I'm just not sure what that would be without modifying headers and responses.

    If your past all that and media oembed iframes are now loading from the subdomain on your main domain your almost done.

    Now to either deny access to the subdomain or redirect everything to your main domain "that is not needed for oEmbed media to display."
    - please note simply redirecting all subdomain requests to the main domain will not work (doing that would negate the use of an alternate domain to serve oEmbed content from and you would again see the warning about service oEmbed from the same site is not recommended.

    Add the following to your .htaccess as the last entry inside the so it runs last after any other rewrites or conditions you may be using like https enforcement, strip www or any other custom redirects runs first. Remember to change subdomain and domain names, plus "if" you are using a dedicated IP listed as REMOTE_ADDR (noted above) swap those as well.

    # Check if HTTP_HOST is subdomain used for Media oEmbed.
      <If "%{HTTP_HOST} = 'media.example.com'>
        # Set the order for access.
        Order deny,allow
    
        # Start with deny all access.
        Deny from all
    
        # If HTTP_REFERER is main domain allow access (the last '/' after referer domain is needed).
        <If "%{HTTP_REFERER} == 'https://example\.com/'">
          # If you have IP from REMOTE_ADDR replace 123.123.123.123 with the [REMOTE_ADDR] IP address if not remove or comment out 'Allow from 123.123.123.123'.
          # If on shared hosting platform without dedicated IP uncomment Allow from all and remove or comment out 'Allow from 123.123.123.123'.
          Allow from 123.123.123.123
          # Allow from all
        </If>
        # If oEmbed is requesting resources from core media module let it.
        <ElseIf "%{REQUEST_URI} =~ m#/core/modules/media/#">
          Allow from 123.123.123.123
          # Allow from all
        </ElseIf>
        <Else>
          # If you do not want to redirect but instead deny access to any other part of the subdomain, empty or comment out everything in the 'Else' directive.
          Allow from 123.123.123.123
          # Allow from all
          RewriteCond %{HTTP_HOST} ^media\.example\.com [NC]
          RewriteRule ^(.*) https://example.com%{REQUEST_URI} [L,R=301]
        </Else>
      </If>

    I am by no means an expert on drupal, apache or htaccess, so it took some time getting things working (more like days of trial and error).
    I found you couldn't just set allow all to IP if the HTTP_HOST was the subdomain (everything would still be user accessible at the subdomain), and it had to be the REMOTE_ADDR IP not the dedicated IP listed as SERVER_ADDR for it to work at all with IP.

    Using browser tools and seeing exactly what calls were made to the subdomain when displaying oEmbed media is how I finally worked it all out. First I found there were 2 resources needed, the oembed linked iframe and a css file from the core media module.

    The oEmbed iframe link is passed by HTTP_REFERER of the main domain the css file is passed by HTTP_REFERER of the subdomain (but so is anything and everything if your viewing the site as the subdomain) and why I used a pattern match on the directive, should some things change and more files or other resources in the media module is needed for oEmbed in the future it should continue to work.

    The (If, ElseIf and Else) Directives are only available to apache 2.4+
    - Note the first thing I do in the opening if directive is set the access order as well as Deny access to all, in the following if, elseif and else you set the 'Allow for' so it will process. If you empty the last else or comment everything else it falls back to Deny for all and will show users landing on subdomain Forbidden, permission denied.

    Using either method 'Allow for [IP.ADDRESS]' or 'Allow for all' seams to work great, I tested both!

    And as near I can tell this satisfies/mitigates any SEO (duplicate content), user confusion and Drupal's policy for oEmbed media!

    Hopefully this will help others...

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States duntuk

    @sidgrafix Holy shit... Thanks for this complex writeup.

    I'm kind of puzzled at the lack of an official drupal explanation on how to accomplish this, especially since Drupal status page point this warning out on all the latest Drupal release versions.

    Media
    It is potentially insecure to display oEmbed content in a frame that is served from the same domain as your main Drupal site, as this may allow execution of third-party code. You can specify a different domain for serving oEmbed content here.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States liza

    am flabbergasted at how badly this is being handled.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia newswatch Delhi/Bangalore

    I put the iFrame domain as https://media.mydomain.com

    This subdomain was created through Cpanel, with https://media.mydomain.com redirecting to https://mydomain.com

    But I'm getting an error:

    The requested URL was not found on this server.

    Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

    It is astounding that something as basic as this does not have any documentation, and has been hanging fire for years now.

    The text on /admin/config/media/media-settings is cryptic and confusing.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States sidgrafix

    @ newswatch - "You can't just create a subdomain and redirect it" it must be a CNAME record (or ALIAS record which is not supported by all DNS hosts, can't say for sure if cPanel does or not - it's been years since I've worked with a cPanel account) NOT an A record for a subdomain. This way (if CNAME) you'll have a canonical name (that the DNS name is an "alias" for) which points to your main domain.

    - I know it's a bit much to work through (as I was once in your boat) but if you follow through with what I posted above https://www.drupal.org/project/drupal/issues/2965979#comment-14991459 โœจ [PP-1] Validate alternate domain for oEmbed iFrame Postponed - in comment 75 - you should be able to get things set up and working. I 100% agree with you on this...

    It is astounding that something as basic as this does not have any documentation, and has been hanging fire for years now.

    The text on /admin/config/media/media-settings is cryptic and confusing.

    If you have any questions or run into problems follow up here or send me a pm and I'll help anyway I can.. Best of luck!

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia newswatch Delhi/Bangalore

    Hi Michael: I changed my procedure a bit.

    I did create a media.mydomian.com subdomain, but did not change doc root to public_html (like last time) and instead let it remain the default /home/username/media.mydomain.com

    As of now the error/warning message has disappeared.

    But whether this works or not I will know once I started using the module heavily across the site.

    It's a fledgling site and still being built; so, I will need to keep a watch till I run into errors :)

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom 2dareis2do

    With regard my previous comment, I am switching this back on now as I figured out there was a misconfiguration of my ssl certificate.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States marteenzh

    I don't suppose there are any nginx experts out there who can provide an nginx version of the .htaccess code sidgrafix provided in 75 โœจ [PP-1] Validate alternate domain for oEmbed iFrame Postponed ?

Production build 0.69.0 2024