Sanitize http_auth_header

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Sanitize http_auth_header

Grigory Trenin
Hello All,

We are using Guacamole auth-header extension and needed some way to sanitize http_auth_header.
So I've created a simple AuthHeaderValve for Tomcat that does it.

It checks if http_auth_header is present in the request, and denies access if it didn't come from allowed source(s). If http-auth-header is not present in the request, it does nothing. Allowed sources are specified in /etc/tomcat/server.xml (it uses the same allow/deny syntax as other Tomcat standard valves).

Eg:  <Valve className="com.vtbcapital.guacamole.AuthHeaderValve" allow="10\.1\.1\.1|10\.2\.2\.2" />

Java code is basically as simple as:

public final class AuthHeaderValve extends RequestFilterValve {

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        HttpServletRequest req = request.getRequest();
        if (req.getHeader("http-auth-header") != null)
            process(req.getRemoteAddr(), request, response);
        else
            getNext().invoke(request, response);
    }
}

Maybe someone finds it helpful.

Guacamole documentation states that it's necessary to sanitize http_auth_header, but does not suggest how to do it.
Maybe it's worth including this feature in Guacamole (not necessarily as a valve, but in some other way).

We are also using Nginx as a reverse proxy, so I've performed sanitization at Nginx too.
Nginx config is as simple as:

# Remove http-auth-header if it does not come from allowed source

geo $psa {
    10.1.1.1  yes;
    10.2.2.2  yes;
    default   no;
}

map $psa $sanitized_auth_header {
    "yes"    $http_http_auth_header;
    "no"     "";
}

server  {
    ...
    location / {
        proxy_pass http://HOSTNAME:8080/guacamole/;
        ...
        proxy_set_header http-auth-header $sanitized_auth_header;
    }
}



Kind regards,
Grigory Trenin
Reply | Threaded
Open this post in threaded view
|

Re: Sanitize http_auth_header

Victor Norman
Grigory,

Thanks!

It sounds like your set up is similar to the setup I'm working with.

I'm curious: when you connect to your server, do you see an error in the console log?  The error I see is:

Failed to load resource: the server responded with a status of 404 ().

When I click on it, I see this:

{"message":"Session not associated with authentication provider \"header\".","translatableMessage":{"key":"Session not associated with authentication provider \"header\".","variables":null},"statusCode":null,"expected":null,"type":"NOT_FOUND"}
Do you see this?

Anyone else? Any idea what this means? Should I be concerned?


From: Grigory Trenin <[hidden email]>
Sent: Wednesday, July 1, 2020 5:49 AM
To: [hidden email] <[hidden email]>
Subject: Sanitize http_auth_header
 
Hello All,

We are using Guacamole auth-header extension and needed some way to sanitize http_auth_header.
So I've created a simple AuthHeaderValve for Tomcat that does it.

It checks if http_auth_header is present in the request, and denies access if it didn't come from allowed source(s). If http-auth-header is not present in the request, it does nothing. Allowed sources are specified in /etc/tomcat/server.xml (it uses the same allow/deny syntax as other Tomcat standard valves).

Eg:  <Valve className="com.vtbcapital.guacamole.AuthHeaderValve" allow="10\.1\.1\.1|10\.2\.2\.2" />

Java code is basically as simple as:

public final class AuthHeaderValve extends RequestFilterValve {

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        HttpServletRequest req = request.getRequest();
        if (req.getHeader("http-auth-header") != null)
            process(req.getRemoteAddr(), request, response);
        else
            getNext().invoke(request, response);
    }
}

Maybe someone finds it helpful.

Guacamole documentation states that it's necessary to sanitize http_auth_header, but does not suggest how to do it.
Maybe it's worth including this feature in Guacamole (not necessarily as a valve, but in some other way).

We are also using Nginx as a reverse proxy, so I've performed sanitization at Nginx too.
Nginx config is as simple as:

# Remove http-auth-header if it does not come from allowed source

geo $psa {
    10.1.1.1  yes;
    10.2.2.2  yes;
    default   no;
}

map $psa $sanitized_auth_header {
    "yes"    $http_http_auth_header;
    "no"     "";
}

server  {
    ...
    location / {
        proxy_pass http://HOSTNAME:8080/guacamole/;
        ...
        proxy_set_header http-auth-header $sanitized_auth_header;
    }
}



Kind regards,
Grigory Trenin
Reply | Threaded
Open this post in threaded view
|

Re: Sanitize http_auth_header

Grigory Trenin

Hi Victor,

I have grepped /var/log/messages for "Session not associated with authentication provider" and can see the following messages:

Jun 30 14:09:57 hostname server: INFO: Error parsing HTTP request header
Jun 30 14:09:57 hostname server: Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
Jun 30 14:09:57 hostname server: java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
Jun 30 14:09:57 hostname server: at org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:198)
Jun 30 14:09:57 hostname server: at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
Jun 30 14:09:57 hostname server: at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
Jun 30 14:09:57 hostname server: at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
Jun 30 14:09:57 hostname server: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
Jun 30 14:09:57 hostname server: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
Jun 30 14:09:57 hostname server: at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
Jun 30 14:09:57 hostname server: at java.lang.Thread.run(Thread.java:748)
Jun 30 14:09:57 hostname server: 14:09:57.993 [http-bio-8443-exec-15219] ERROR o.a.g.w.GuacamoleWebSocketTunnelEndpoint - Creation of WebSocket tunnel to guacd failed: Session not associated with authentication provider "header".
Jun 30 14:09:58 hostname server: 14:09:58.285 [http-bio-8443-exec-15519] WARN  o.a.g.s.GuacamoleHTTPTunnelServlet - HTTP tunnel request rejected: Session not associated with authentication provider "header".

I'm running 1.1.0 version on RHEL7.
It's better to create a separate thread for this and do not hijack this one.


Kind regards,
Grigory Trenin