James Moger
2014-09-06 dfaf1fc1f6d8214bcabb9a613d53d0f0dc45352c
XSS sanitize standard page url parameters
2 files modified
44 ■■■■ changed files
src/main/java/com/gitblit/wicket/GitBlitWebApp.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitblitParamUrlCodingStrategy.java 42 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitBlitWebApp.java
@@ -255,7 +255,7 @@
        if (!settings.getBoolean(Keys.web.mountParameters, true)) {
            parameters = new String[] {};
        }
        mount(new GitblitParamUrlCodingStrategy(settings, location, clazz, parameters));
        mount(new GitblitParamUrlCodingStrategy(settings, xssFilter, location, clazz, parameters));
        // map the mount point to the cache control definition
        if (clazz.isAnnotationPresent(CacheControl.class)) {
src/main/java/com/gitblit/wicket/GitblitParamUrlCodingStrategy.java
@@ -15,13 +15,13 @@
 */
package com.gitblit.wicket;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.wicket.IRequestTarget;
import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
import org.apache.wicket.request.RequestParameters;
import org.apache.wicket.request.target.coding.MixedParamUrlCodingStrategy;
import org.apache.wicket.util.string.AppendingStringBuffer;
@@ -30,6 +30,7 @@
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.utils.XssFilter;
/**
 * Simple subclass of mixed parameter url coding strategy that works around the
@@ -49,6 +50,8 @@
    private IStoredSettings settings;
    private XssFilter xssFilter;
    /**
     * Construct.
     *
@@ -62,12 +65,14 @@
     */
    public <C extends Page> GitblitParamUrlCodingStrategy(
            IStoredSettings settings,
            XssFilter xssFilter,
            String mountPath,
            Class<C> bookmarkablePageClass, String[] parameterNames) {
        super(mountPath, bookmarkablePageClass, parameterNames);
        this.parameterNames = parameterNames;
        this.settings = settings;
        this.xssFilter = xssFilter;
    }
    /**
@@ -111,10 +116,37 @@
     */
    @Override
    public IRequestTarget decode(RequestParameters requestParameters) {
        final String parametersFragment = requestParameters.getPath().substring(
                getMountPath().length());
        logger.debug(MessageFormat
                .format("REQ: {0} PARAMS {1}", getMountPath(), parametersFragment));
        Map<String, Object> parameterMap = (Map<String, Object>) requestParameters.getParameters();
        for (Map.Entry<String, Object> entry : parameterMap.entrySet()) {
            String parameter = entry.getKey();
            if (parameter.startsWith(WebRequestCodingStrategy.NAME_SPACE)) {
                // ignore Wicket parameters
                continue;
            }
            // sanitize Gitblit request parameters
            Object o = entry.getValue();
            if (o instanceof String) {
                String value = o.toString();
                String safeValue = xssFilter.none(value);
                if (!value.equals(safeValue)) {
                    logger.warn("XSS filter triggered on {} URL parameter: {}={}",
                            getMountPath(), parameter, value);
                    parameterMap.put(parameter, safeValue);
                }
            } else if (o instanceof String[]) {
                String[] values = (String[]) o;
                for (int i = 0; i < values.length; i++) {
                    String value = values[i].toString();
                    String safeValue = xssFilter.none(value);
                    if (!value.equals(safeValue)) {
                        logger.warn("XSS filter triggered on {} URL parameter: {}={}",
                                getMountPath(), parameter, value);
                        values[i] = safeValue;
                    }
                }
            }
        }
        return super.decode(requestParameters);
    }