Preventing Un-validated Redirects on the Access Gateway Service using a Whitelist

Preventing Un-validated Redirects on the Access Gateway Service using a Whitelist

by Gary L. Gilbert


Introduction



Redirection, which is required by many applications and services, inherently brings security risks to organizations. For instance, an “un-validated” redirect can allow an unsuspecting user visiting a trusted site to be redirected to a malicious site, therefore exploiting the users' trust. Using a “whitelist” can help mitigate this vulnerability by restricting redirections to specific domains only.

When using NetIQ Access Manager™, the Access Gateway responds to requests from a user’s browser when accessing a protected resource. A hacker can intercept and manipulate these requests by simply appending another web site as a parameter in the URL, thus redirecting the user. Here is a simple example of a typical Access Gateway URL that was altered to redirect to a un-validated web site (i.e. google.com):

https://www.mydomain.com/nesp/app/plogin?c=secure/name/password/uri&%22http://google.com%22

In this article, I’ll describe how to intercept a request on the Access Gateway Service to check if the URL contains a valid domain specified in a “whitelist” using a Servlet Filter. This article assumes that you have some java knowledge and are familiar with NetIQ Access Manager™.

Technical Overview



To intercept an Access Gateway request, we can create a Servlet Filter and deploy it to the Tomcat application service on the Access Gateway Service. A Servlet Filter can be used to intercept and process requests before they are sent to an application endpoint. The filter can also intercept responses after the application endpoint finishes and before the Tomcat container sends the response back to the client. In this solution, we only intercept and process the servlet request.

Servlet filters are pluggable components that are independent of an application endpoint and can be turned on/off simply by modifying descriptors in the tomcat container’s web.xml file. The application and the servlet filter are both unaware of each other’s existence and there can be multiple chained filters that are executed in the order configured in the web.xml file.

Servlet Filter Servlet Filter


Figure 1 – Un-validated Redirect Filter

Referring to Figure 1 above, the new Servlet Filter (Filter C) is deployed to the Tomcat servlet container on the Access Gateway Service. The application endpoint is the “plogin” service within the ESP on the Access Gateway. In this solution, the filter will intercept the plogin request to determine if any request parameters contain invalid domains that are not specified in a domain whitelist. The whitelist is defined in the web.xml file on the servlet container. If the filter detects an invalid domain, the user is immediately logged out of Access Manager.

Solution Details



Servlet Filter:

The servlet filter is simply a Java class that implements the javax.servlet.Filter interface. The javax.servlet.Filter interface defines three methods that make up the lifecycle of a filter, which is managed by the Tomcat servlet container. The filter interface methods include the following:

  • void init(FilterConfig paramFilterConfig) – When the container initializes the Filter, this is the method that gets invoked. This method is called only once in the lifecycle of filter and initializes any resources in this method. We will use this method to retrieve the defined whitelist and debug parameters.



  • doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) – This is the method invoked by the Tomcat container each time a request is made. The FilterChain is used to invoke the next filter in the chain.



  • void destroy() – When container offloads the Filter instance, it invokes the destroy() method. This method is only called once and is used to close any resources opened by the filter.


Here is the java source code for the Servlet Filter. To create the Java class, you can use your choice of Java IDE’s, for example Eclipse or IntelliJ, to compile the source code and generate an archive JAR that can be deployed to the Access Gateway Service.

package com.netiq.ag;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.net.URL;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Enumeration;/** * Created by IntelliJ IDEA. * User: Gary L. Gilbert * Date: July 01, 2015 * Time: 11:24:06 PM * Description: Use this filter to capture unvalidated redirects on the Access Gateway. */public class Filter implements javax.servlet.Filter {

protected FilterConfig config;

protected ServletContext ctx;

protected String targetDomains[];

protected boolean debug = true;

private static final DateFormat LOG_TIMESTAMP_FORMAT = new SimpleDateFormat(“yyyy-MM-dd,HH:mm:ss.SSS”);

public void init(FilterConfig config) throws ServletException {

try {

debug = Boolean.parseBoolean(config.getInitParameter("debug"));

log ("FILTER: ====================================================");

log ("FILTER: Initializing");

ctx = config.getServletContext();

targetDomains = config.getInitParameter("target_domains").replaceAll("\\s","").toLowerCase().split(",");

for (String targetDomain : targetDomains) {

log ("FILTER: Target Domain: " + targetDomain);

}

this.config = config;

log ("FILTER: End Initializing");

log ("FILTER: ====================================================");

} catch (Exception e) {

log ("FILTER: **** ERROR: Retrieving config parameters. Check init parameters in web.xml.");

}

}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) servletRequest;

HttpServletResponse response = (HttpServletResponse) servletResponse;

boolean validURL = true;

String paramName = "";

Enumeration<String> parameterNames = request.getParameterNames();

mainloop:

while (parameterNames.hasMoreElements()) {

paramName = parameterNames.nextElement();

log ("FILTER: Parameter Name: " + paramName);

if ( paramName.toLowerCase().startsWith("\"http") ) {

URL turl = new URL(paramName.replaceAll("\"", ""));

paramName = turl.getHost().toLowerCase();

log ("FILTER: Parsed Domain: " + paramName);

validURL = false;

for (String targetDomain : targetDomains) {

log ("FILTER: Target Domain: " + targetDomain);

if ( paramName.endsWith( targetDomain ) ) {

validURL = true;

break mainloop;

}

}

break;

}

}

if ( validURL ) {

log ("FILTER: **** Valid Target Domain ****: " + paramName);

filterChain.doFilter(request, response);

} else {

log ("FILTER: **** Invalid Target Domain ****: " + paramName);

response.sendRedirect("/AGLogout");

}

}

public void destroy() {

config = null;

}

protected void log(String message) {

if (debug) {

System.out.print(LOG_TIMESTAMP_FORMAT.format(new Date()));

System.out.print(" Thread-");

System.out.print(Thread.currentThread().getId());

System.out.print(": ");

System.out.println(message);

}

}

}


web.xml:

Servlet Filters are pluggable components that are configured in the deployment descriptor (web.xml) file. Note that both applications and servlet filters are unaware of each other, so it is possible to add or remove a filter just by editing the web.xml. In this solution, our servlet filter has two initialization “init” parameters that are configured in the web.xml.

  • target_domains – This parameter contains the “whitelist” which the filter will use to check if the target domains are valid. You can enter multiple domains separated by a comma (,).



  • debug – This parameter allows you to enable filter debug logging to the ESP catalina.out file. You can tail this log and grep for “FILTER:” (all caps) to see the filter processing.



<filter>
<filter-name>UnvalidatedTargetFilter</filter-name>


<filter-class>com.netiq.ag.Filter</filter-class>


<init-param>


<param-name>target_domains</param-name>


<param-value>.netiq.com,.novell.com</param-value>


</init-param>


<init-param>


<param-name>debug</param-name>


<param-value>true</param-value>


</init-param>


</filter>


<filter-mapping>


<filter-name>UnvalidatedTargetFilter</filter-name>


<url-pattern>/*</url-pattern>


</filter-mapping>




Deployment Steps



A compiled version of the Servlet Filter is available for download by clicking here. To deploy this JAR, use the following steps:


  • Unzip download file and copy the JAR file to the following directory on each of the Access Gateways:
    /opt/novell/nesp/lib/webapp/WEB-INF/lib

  • Change the file and ownership properties of the JAR file:
    chmod 644 agfilter.jar
    chown novlwww:novlwww agfilter

  • Edit your existing web.xml file on each of the Access Gateways and add the filter configuration tags shown in the web.xml section above. Be sure to add the new filter block after all the other filters defined in the file. The file is located in:
    /opt/novell/nesp/lib/webapp/WEB-INF/web.xml

  • Restart each of the Access Gateways:
    rcnovell-appliance restart



Testing and Verification Steps



After restarting the Access Gateway, open the ESP catalina.out and make sure the filter has initialized without any java exceptions. You can search the file for the keyword “nidpJspFilter” and verify that you see the following log entries:

2015-07-10,00:57:40.375 Thread-11: FILTER: ====================================================

2015-07-10,00:57:40.375 Thread-11: FILTER: Initializing

2015-07-10,00:57:40.376 Thread-11: FILTER: Target Domain: .netiq.com

2015-07-10,00:57:40.376 Thread-11: FILTER: Target Domain: .novell.com

2015-07-10,00:57:40.383 Thread-11: FILTER: End Initializing

2015-07-10,00:57:40.383 Thread-11: FILTER: ====================================================

Filter initialized! 'nidpJspFilter'

Jul 10, 2015 12:57:41 AM org.apache.catalina.startup.HostConfig deployDirectory

INFO: Deployment of web application directory /opt/novell/nam/mag/webapps/nesp has finished in 14,777 ms


If you do not see log entries during the filter initialization, make sure the web.xml debug parameter is configured for debugging (debug = true). You should see filter log entries appear while you are tailing the catalina.out file:

tail –f /var/opt/novell/nam/logs/mag/tomcat/catalina.out | grep “FILTER:”


Next, test the filter functionality. Open a web browser and navigate to a protected resource on the Access Gateway. After successful authentication, try to access a malicious URL like:

https://www.mydomain.com/nesp/app/plogin?c=secure/name/password/uri&%22http://google.com%22

For this test case, you should be redirected to the AG Logout service and your session terminated.

Disclaimer



This solution is only applicable for NetIQ Access Manager™ 4.0.x or 4.1.x, however may also work with past and future versions (not validated). You should thoroughly test this solution in your test environment prior to releasing into your production environment. .
Labels (1)
Attachments

DISCLAIMER:

Some content on Community Tips & Information pages is not officially supported by Micro Focus. Please refer to our Terms of Use for more detail.
Top Contributors
Version history
Revision #:
3 of 3
Last update:
‎2020-01-31 22:07
Updated by:
 
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.