ClickjackingHealthCheck.java 6.4 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.PropertyUnbounded
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.http.Header
 *  org.apache.http.HeaderIterator
 *  org.apache.http.client.methods.CloseableHttpResponse
 *  org.apache.http.client.methods.HttpGet
 *  org.apache.http.client.methods.HttpUriRequest
 *  org.apache.http.impl.client.CloseableHttpClient
 *  org.apache.http.impl.client.HttpClients
 *  org.apache.sling.commons.osgi.PropertiesUtil
 *  org.apache.sling.hc.api.HealthCheck
 *  org.apache.sling.hc.api.Result
 *  org.apache.sling.hc.api.ResultLog
 *  org.apache.sling.hc.util.FormattingResultLog
 *  org.osgi.service.component.ComponentContext
 */
package com.adobe.cq.security.hc.webserver.impl;

import java.io.IOException;
import java.util.Dictionary;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyUnbounded;
import org.apache.felix.scr.annotations.Service;
import org.apache.http.Header;
import org.apache.http.HeaderIterator;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.hc.api.HealthCheck;
import org.apache.sling.hc.api.Result;
import org.apache.sling.hc.api.ResultLog;
import org.apache.sling.hc.util.FormattingResultLog;
import org.osgi.service.component.ComponentContext;

@Component(metatype=1, label="Web Server Configuration Health Check", description="This checks if the web server sets the X-FRAME-OPTIONS HTTP header to SAMEORIGIN or DENY.")
@Properties(value={@Property(name="hc.name", value={"Web Server Configuration"}, label="Name", description="Name of the health check."), @Property(name="hc.tags", unbounded=PropertyUnbounded.ARRAY, value={"webserver", "production", "security", "clickjacking"}, label="Tags", description="Tags for the health check."), @Property(name="hc.mbean.name", value={"webServerConfig"}, label="MBean Name", description="Name of the JMX mbean to register for this check.")})
@Service(value={HealthCheck.class})
public class ClickjackingHealthCheck
implements HealthCheck {
    @Property(value={""}, label="Public Address", description="The public address for the site.")
    private static final String WEBSERVER_URL = "webserver.address";
    private String webserverUrl;

    @Activate
    protected void activate(ComponentContext ctx) {
        this.webserverUrl = PropertiesUtil.toString(ctx.getProperties().get("webserver.address"), (String)"");
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Result execute() {
        FormattingResultLog resultLog;
        resultLog = new FormattingResultLog();
        boolean success = true;
        boolean found = false;
        if (this.webserverUrl.trim().equals("")) {
            resultLog.warn("The URL of the website served by the server is not configured.", new Object[0]);
            resultLog.debug("[You can configure the website URL via the Public Address property of this health check.]( )", new Object[0]);
            return new Result((ResultLog)resultLog);
        }
        HttpGet httpget = new HttpGet(this.webserverUrl);
        CloseableHttpClient client = null;
        CloseableHttpResponse httpResponse = null;
        try {
            client = HttpClients.createDefault();
            httpResponse = client.execute((HttpUriRequest)httpget);
            resultLog.debug("[In order to prevent clickjacking, it is recommended to set the web server X-FRAME-OPTIONS HTTP response header to SAMEORIGIN or DENY.]( )", new Object[0]);
            if (httpResponse != null) {
                HeaderIterator headerIter = httpResponse.headerIterator();
                while (headerIter.hasNext()) {
                    Header header = headerIter.nextHeader();
                    if (!"X-FRAME-OPTIONS".equals(header.getName().toUpperCase())) continue;
                    found = true;
                    String headerValue = header.getValue().toUpperCase();
                    if ("SAMEORIGIN".equals(headerValue)) {
                        resultLog.debug("The X-FRAME-OPTIONS HTTP response header is set to SAMEORIGIN.", new Object[0]);
                        continue;
                    }
                    if ("DENY".equals(headerValue)) {
                        resultLog.debug("The X-FRAME-OPTIONS HTTP response header is set to DENY.", new Object[0]);
                        continue;
                    }
                    resultLog.warn("The X-FRAME-OPTIONS HTTP response header is set to {}. It is recommended to set it to SAMEORIGIN or DENY.", new Object[]{headerValue});
                    success = false;
                }
            }
            if (!success || !found) {
                resultLog.debug("[Check the 'Clickjacking' section of the security guidelines.](https://www.adobe.com/go/aem6_2_docs_security_click_en)", new Object[0]);
            }
        }
        catch (Exception e) {
            resultLog.warn("Could not check the HTTP headers returned by the web server. Please check the website URL.", new Object[0]);
            resultLog.debug("[You can configure the website URL via the Public Address property of this health check.]( )", new Object[0]);
        }
        finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                }
                catch (IOException e) {
                    resultLog.warn("Could not close the HTTP response due to an IOException.", new Object[0]);
                }
            }
            if (client != null) {
                try {
                    client.close();
                }
                catch (IOException e) {
                    resultLog.warn("Could not close the HTTP client due to an IOException", new Object[0]);
                }
            }
        }
        return new Result((ResultLog)resultLog);
    }
}