You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gc...@apache.org on 2011/11/29 21:42:51 UTC
svn commit: r1208059 - in /myfaces/trinidad/trunk: src/site/xdoc/devguide/
trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/
trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/
trinidad-impl/src/main/java/org/apache/myfaces/...
Author: gcrawford
Date: Tue Nov 29 20:42:49 2011
New Revision: 1208059
URL: http://svn.apache.org/viewvc?rev=1208059&view=rev
Log:
TRINIDAD-2169 add framebusting support to handle clickjacking attacks
Added:
myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/FrameBustingUtils.java
Modified:
myfaces/trinidad/trunk/src/site/xdoc/devguide/configuration.xml
myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml
myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/TrinidadPhaseListener.java
myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java
myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
Modified: myfaces/trinidad/trunk/src/site/xdoc/devguide/configuration.xml
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/src/site/xdoc/devguide/configuration.xml?rev=1208059&r1=1208058&r2=1208059&view=diff
==============================================================================
--- myfaces/trinidad/trunk/src/site/xdoc/devguide/configuration.xml (original)
+++ myfaces/trinidad/trunk/src/site/xdoc/devguide/configuration.xml Tue Nov 29 20:42:49 2011
@@ -351,6 +351,32 @@ Some Apache Trinidad configuration optio
<code><context-param></code> elements in your
<code>WEB-INF/web.xml</code>file.
</p>
+
+<subsection name="org.apache.myfaces.trinidad.security.FRAME_BUSTING">
+
+<p>
+The parameter "org.apache.myfaces.trinidad.security.FRAME_BUSTING" controls the framebusting feature.
+Framebusting stops content from running inside frames (meaning a frame or iframe tag).
+</p>
+<p>
+This context parameter is ignored when org.apache.myfaces.trinidad.util.ExternalContextUtils.isPortlet is true,
+and will behave as if the context parameter is set to 'never'.
+</p>
+<p>
+Possible values are:
+<ul>
+<li>differentOrigin - only bust frames if the an ancestor window origin and the
+ frame origin are different. If the ancestor windows and frame have
+ the same origin then allow the content to run in a frame. This is the default.
+</li>
+<li>always - always bust frames, meaning don't allow a page to be embedded in frames
+</li>
+<li>never - never bust frames, meaning always allow a page to be embedded in frames
+</li>
+</ul>
+</p>
+</subsection>
+
<subsection name="org.apache.myfaces.trinidad.CACHE_VIEW_ROOT">
<p>
Enables or disables UIViewRoot caching; defaults to true.
Modified: myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml?rev=1208059&r1=1208058&r2=1208059&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml (original)
+++ myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/web.xml Tue Nov 29 20:42:49 2011
@@ -34,6 +34,32 @@
<param-value>.jspx</param-value>
</context-param>
+
+
+ <context-param>
+ <!--description>
+ The parameter "org.apache.myfaces.trinidad.security.FRAME_BUSTING" controls
+ the framebusting feature. Framebusting stops content from running inside
+ frames (meaning a frame or iframe tag).
+
+ This context parameter is ignored when
+ org.apache.myfaces.trinidad.util.ExternalContextUtils.isPortlet is true,
+ and will behave as if the context parameter is set to 'never'.
+
+ Possible values are:
+
+ differentOrigin - only bust frames if the an ancestor window origin
+ and the frame origin are different. If the ancestor windows
+ and frame have the same origin then allow the content to run
+ in a frame. This is the default.
+ always - always bust frames, meaning don't allow a page to be embedded in frames
+ never - never bust frames, meaning always allow a page to be embedded in frames
+
+ </description-->
+ <param-name>org.apache.myfaces.trinidad.security.FRAME_BUSTING</param-name>
+ <param-value>differentOrigin</param-value>
+ </context-param>
+
<!-- Set to true for using the lightweight dialog feature -->
<context-param>
<param-name>org.apache.myfaces.trinidad.ENABLE_LIGHTWEIGHT_DIALOGS</param-name>
Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/TrinidadPhaseListener.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/TrinidadPhaseListener.java?rev=1208059&r1=1208058&r2=1208059&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/TrinidadPhaseListener.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/context/TrinidadPhaseListener.java Tue Nov 29 20:42:49 2011
@@ -26,6 +26,7 @@ import javax.faces.event.PhaseListener;
import org.apache.myfaces.trinidadinternal.config.xmlHttp.XmlHttpConfigurator;
import org.apache.myfaces.trinidadinternal.renderkit.core.CoreRenderKit;
+import org.apache.myfaces.trinidadinternal.util.FrameBustingUtils;
/**
* Performs some trinidad logic and provides some hooks.
@@ -68,11 +69,14 @@ public class TrinidadPhaseListener imple
@SuppressWarnings("unchecked")
public void beforePhase(PhaseEvent event)
{
+
+ PhaseId phaseId = event.getPhaseId();
+
// Ensure that the implicit object gets created. In general,
// "restore view" would be sufficient, but someone can call
// renderResponse() before even calling Lifecycle.execute(),
// in which case RESTORE_VIEW doesn't actually run.
- if (event.getPhaseId() == PhaseId.RESTORE_VIEW)
+ if (phaseId == PhaseId.RESTORE_VIEW)
{
FacesContext context = event.getFacesContext();
ExternalContext ec = context.getExternalContext();
@@ -82,11 +86,35 @@ public class TrinidadPhaseListener imple
// If we've reached "apply request values", this is definitely a
// postback (the ViewHandler should have reached the same conclusion too,
// but make sure)
- else if (event.getPhaseId() == PhaseId.APPLY_REQUEST_VALUES)
+ else if (phaseId == PhaseId.APPLY_REQUEST_VALUES)
{
FacesContext context = event.getFacesContext();
markPostback(context);
}
+ else if (phaseId == PhaseId.RENDER_RESPONSE)
+ {
+ // add response headers for framebusting if needed
+
+ FacesContext context = event.getFacesContext();
+ String frameBusting = FrameBustingUtils.getFrameBustingValue(context);
+
+ if (! FrameBustingUtils.FRAME_BUSTING_NEVER.equalsIgnoreCase(frameBusting))
+ {
+ // TODO: Mozilla has introduced CSP
+ // https://wiki.mozilla.org/Security/CSP/Specification
+ // which we may want to support at some point
+
+ // the X-Frame-Options header doesn't work on all browsers, but we're adding it anyway
+ if (FrameBustingUtils.FRAME_BUSTING_ALWAYS.equalsIgnoreCase(frameBusting))
+ {
+ context.getExternalContext().addResponseHeader("X-Frame-Options", "deny");
+ }
+ else
+ {
+ context.getExternalContext().addResponseHeader("X-Frame-Options", "sameorigin");
+ }
+ }
+ }
}
Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java?rev=1208059&r1=1208058&r2=1208059&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java Tue Nov 29 20:42:49 2011
@@ -35,6 +35,7 @@ import org.apache.myfaces.trinidad.conte
import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.skin.Skin;
import org.apache.myfaces.trinidad.util.Service;
+import org.apache.myfaces.trinidadinternal.util.FrameBustingUtils;
/**
@@ -141,8 +142,12 @@ public class BodyRenderer extends PanelP
if (supportsScripting(rc))
{
+ // this sets display:none on body and removes it with javascript. If no javascript is supported,
+ // no need to render the script. (it breaks emailable page mode because display:none is never cleared)
+ _renderFrameBustingScript(context, rc);
+
_renderNoScript(context, rc);
- _storeInitialFocus(rc, component, bean);
+ _storeInitialFocus(rc, component, bean);
}
if (!isPartialPass)
@@ -584,6 +589,47 @@ public class BodyRenderer extends PanelP
return "(" + versionInfo + apiSpecTitle + " - " + apiVersion + "/"
+ implSpecTitle + " - " + implVersion + ")";
}
+
+ private void _renderFrameBustingScript(
+ FacesContext context,
+ RenderingContext rc
+ ) throws IOException
+ {
+ // get the framebusting param set in web.xml
+ String frameBusting = FrameBustingUtils.getFrameBustingValue(context);
+
+ if (! FrameBustingUtils.FRAME_BUSTING_NEVER.equalsIgnoreCase(frameBusting))
+ {
+ ResponseWriter out = context.getResponseWriter();
+
+ // Add a style to hide the body tag, if the framebusting code runs and decides it does not
+ // need to bust frames then it will remove the style dom node, which will make the content
+ // visible.
+ //
+ // We are using a style element instead of setting a style/class directly on the
+ // body tag because if we ever added a splash screen it would not show.
+ // We are setting an id on the style so that it can be removed on the client,
+ // which will make the content visible.
+ //
+ // We had previously tried to use javascript to add display:block to the
+ // style attribute of the body tag, but the style attribute of the body tag can get removed,
+ // for example when you do ppr nav or you ppr the document. Therefore we are now
+ // removing the style element on the client.
+ //
+ out.startElement("style", null);
+ // an id cannot start with an underscore
+ out.writeAttribute("id", "trinFrameBustStyle", null);
+ out.writeText("body {display:none}", null);
+ out.endElement("style");
+
+ out.startElement("script", null);
+ XhtmlRenderer.renderScriptTypeAttribute(context, rc);
+ out.writeText("TrPage.__frameBusting(\"", null);
+ out.writeText(frameBusting, null);
+ out.writeText("\");", null);
+ out.endElement("script");
+ }
+ }
private PropertyKey _firstClickPassedKey;
private PropertyKey _initialFocusIdKey;
Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/FrameBustingUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/FrameBustingUtils.java?rev=1208059&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/FrameBustingUtils.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/util/FrameBustingUtils.java Tue Nov 29 20:42:49 2011
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.trinidadinternal.util;
+
+
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.trinidad.util.ExternalContextUtils;
+
+import org.apache.myfaces.trinidad.context.RequestContext;
+
+/**
+ * @author Gabrielle Crawford
+ */
+public class FrameBustingUtils
+{
+
+ // This parameter controls the framebusting feature. framebusting stops content from
+ // running inside frames (meaning a frame or iframe tag).
+ //
+ // This context parameter is ignored when
+ // org.apache.myfaces.trinidad.util.ExternalContextUtils.isPortlet is true,
+ // and will behave as if the context parameter is set to 'never'.
+ //
+ // Possible values are:
+ // differentOrigin - only bust frames if the an ancestor window origin and the
+ // frame origin are different. If the ancestor windows and frame have
+ // the same origin then allow the content to run in a frame.
+ // This is the default.
+ // always - always bust frames, meaning don't allow a page to be embedded in frames
+ // never - never bust frames, meaning always allow a page to be embedded in frames
+ static private final String _FRAME_BUSTING_PARAM = "org.apache.myfaces.trinidad.security.FRAME_BUSTING";
+ static public final String FRAME_BUSTING_NEVER = "never";
+ static public final String FRAME_BUSTING_ALWAYS = "always";
+ static public final String FRAME_BUSTING_DIFFERENT_ORIGIN = "differentOrigin";
+
+ public static String getFrameBustingValue(FacesContext context)
+ {
+
+ // Act as if the value is never if
+ // 1. we're doing ppr, we should only need to bust frames on a full page render
+ // 2. if the web.xml value is never
+ // 3. if we're in a portal
+ // Portals have a concept of producers and consumers.
+ // The main page is the consumer, and the portlets inside that page are the producers.
+ // Producer content can only be accessed by trusted consumers.
+ //
+ // The consumer page can set the context param as needed,
+ // but the producers will not do framebusting.
+ // In other words when ExternalContextUtils.isPortlet is true we will behave as if
+ // the context param is set to 'never'.
+
+ String frameBusting = context.getExternalContext().getInitParameter(_FRAME_BUSTING_PARAM);
+
+ if ( FRAME_BUSTING_NEVER.equalsIgnoreCase(frameBusting) ||
+ RequestContext.getCurrentInstance().isPartialRequest(context) ||
+ ExternalContextUtils.isPortlet(context.getExternalContext()))
+ {
+ return FRAME_BUSTING_NEVER;
+ }
+ else if (FRAME_BUSTING_ALWAYS.equalsIgnoreCase(frameBusting))
+ {
+ return FRAME_BUSTING_ALWAYS;
+ }
+ else
+ {
+ // default is different origin
+ return FRAME_BUSTING_DIFFERENT_ORIGIN;
+ }
+ }
+}
Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js?rev=1208059&r1=1208058&r2=1208059&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js Tue Nov 29 20:42:49 2011
@@ -1019,4 +1019,66 @@ TrPage.prototype._getDomToBeUpdated = fu
}
return oldElements;
-}
\ No newline at end of file
+}
+
+
+// static method called on server
+TrPage.__frameBusting = function(frameBusting)
+{
+
+ if ( !(self == top || frameBusting == "never"))
+ {
+ if (frameBusting == "always")
+ {
+ top.location.href = location.href;
+ }
+ else
+ {
+ var topNotProcessed = true;
+ var parentWindow = parent;
+
+ while (topNotProcessed)
+ {
+ try
+ {
+ // if we have a different origin parentWindow.location.href will throw an exception
+ // in firefox and IE
+ var parentWindowLocation = parentWindow.location.href;
+
+ // in safari and google chrome no exception is thrown for referring to
+ // parentWindow.location.href, instead the parent window location is undefined
+ if (parentWindowLocation == null)
+ {
+ top.location.href = location.href;
+ return;
+ }
+ }
+ catch(e)
+ {
+ // the content has different origin, redirect
+ top.location.href = location.href;
+ return;
+ }
+
+ if (parentWindow == top)
+ topNotProcessed = false;
+
+ parentWindow = parentWindow.parent;
+ }
+ }
+ }
+
+ // we didn't end up framebusting, so show the content
+ //
+ // We had previously tried to use javascript to add display:block to the
+ // style attribute of the body tag, but the style attribute of the body tag can get removed,
+ // for example when you do ppr nav or you ppr the document. Therefore we are now
+ // removing the style element on the client.
+ var styleNode = document.getElementById("trinFrameBustStyle");
+
+ if (styleNode)
+ {
+ styleNode.parentNode.removeChild(styleNode);
+ }
+}
+