If you have configured

WhiteListedAllowFromStrategy w = new WhiteListedAllowFromStrategy(
                    Arrays.asList("http://localhost:3000",
                            "http://localhost:9082",
                            "somethingthatiswhitelisted"));
            wlafs.setAllowFromParameterName("x-frames-allow-from"); // I know default value
            http.headers().frameOptions().disable();
            http.headers().addHeaderWriter(new XFrameOptionsHeaderWriter(w));

The code that is eventually called to see if the calling website should be able to frame it is:

public String getAllowFromValue(HttpServletRequest request) {
        String allowFromOrigin = request.getParameter(this.allowFromParameterName);
        if (this.log.isDebugEnabled()) {
            this.log.debug("Supplied origin '" + allowFromOrigin + "'");
        }

        return StringUtils.hasText(allowFromOrigin) && this.allowed(allowFromOrigin) ? allowFromOrigin : "DENY";
    }

Where as request.getParameter is set via query string from the calling website... that is if I know what you have set in your white list I can simply make my IFrame have: <iframe src="http://somewebsite?x-frames-allow-from=somethingthatiswhitelisted"></iframe>

This seems to be pretty weak protection, would it not be be better to use something like: request.getHeader("referer") vs a request.getParameter that can easily be set by the calling website that wished to embed your content? Using the header("referer") would also just work vs having to manually set a parameter, and or guard against someone artificially setting the parameter via a query string.

Comment From: jchambers-ln

Actually probably more accurately should add a new class RefererWhiteListedAllowFromStrategy

Something like:

package org.springframework.security.web.header.writers.frameoption;

import org.springframework.security.web.header.writers.frameoptions.AllowFromStrategy;
import java.util.Collection;

import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;

public class RefererWhiteListedAllowFromStrategy implements AllowFromStrategy  {
    private final Collection<String> allowed;

    /**
     * Creates a new instance
     * @param allowed the origins that are allowed.
     */
    public RefererWhiteListedAllowFromStrategy (Collection<String> allowed) {
        Assert.notEmpty(allowed, "Allowed origins cannot be empty.");
        this.allowed = allowed;
    }

    @Override
    public String getAllowFromValue(HttpServletRequest request) {
       //todo: harden for trailing slashes and different protocols http/https 
        if(allowed.contains(request.getHeader("referer"))){
            return request.getHeader("referer");
        }
        return "DENY";
    }
}

Then it can be used with something like: (note request.getHeader("referer"); typically has the trailing slash, so for hardened code probably would want to make the code handle with or without trailing slash.)

RefererWhiteListedAllowFromStrategy w= new RefererWhiteListedAllowFromStrategy (
                    Arrays.asList("http://localhost:3000/",
                            "http://localhost:9082/",
                            "http://localhost:8088/"));
            //wlafs.setAllowFromParameterName("referer");
            http.headers().frameOptions().disable();
            http.headers().addHeaderWriter(new XFrameOptionsHeaderWriter(
                    w
                    ));

For now I've just done something similar with a local class to meet my needs. I know referer can be spoofed by the client, but more worried about a website embedding content than an individual user tweaking the header here.

Comment From: fhanik

hi @jchambers-ln

Looking through the history and some stackoverflow, this works as designed.

As you mention, it's not really a protection scheme, and you have a valid workaround. I'm going to close this categorized as not and issue.

If you feel strongly about making the case for an enhancement, I would open up a PR with test cases. Please note, you'll want to take a look at HeadersBeanDefinitionParser.java too, as this component touches on the same logic.