[squid-users] SSL bump config or possible code issue

Greg Saylor gregs at net-virtual.com
Thu Dec 8 16:15:41 UTC 2016


Hello,

This is my first time looking at the squid code. I'm trying to debug a situation where squid 3.4 would return a ERR_ACCESS_DENIED and version 3.5 does not. I believe its somehow related to ssl peek/slice/bump, but being new to Squid I can't really understand that too well.

So squid is configured with:

configure options:  '--prefix=/usr' '--includedir=/usr/include' '--datadir=/usr/share' '--bindir=/usr/sbin' '--libexecdir=/usr/lib/squid' '--localstatedir=/var' '--sysconfdir=/etc/squid' '--with-logdir=/var/log/squid' '--with-openssl' '--enable-linux-netfilter' '--enable-ssl' '--enable-icap-client’

Here’s the http_access rules which exhibit this behavior:


acl socialnetworks dstdomain .facebook.com

acl localnet src 10.0.0.0/8     # RFC1918 possible internal network
acl localnet src 172.16.0.0/12  # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network

acl SSL_ports port 443 8443
acl Safe_ports port 80          # http
acl Safe_ports port 443         # https
acl Safe_ports port 8443         # https
acl Safe_ports port 3128        # squid
acl CONNECT method CONNECT

http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

http_access allow socialnetworks

icp_access deny all
icp_port 4130


Now in socat setup a proxy like so:

socat TCP-LISTEN:8080,fork "SSL,verify=0 | PROXY-CONNECT:www.facebook.com:443 | TCP:{squid host}:4130"


Then make a request to port 8080 which sets (which is some https service on localnet):

Host: 172.16.0.10:443

Then try one that is not running https:

Host: 172.16.0.11:443

You will see that in 3.5 172.16.0.10 responds with the response, 172.16.0.11 times out.  The 3.4 behavior was that both of these hosts would result in a ERR_ACCESS_DENIED.


So, I started looking at the source code between 3.4 and 3.5. In 3.5 there is this code in src/client_side_request.cc.

    if (calloutContext->error) {
        const char *storeUri = request->storeId();
        StoreEntry *e= storeCreateEntry(storeUri, storeUri, request->flags, request->method);
#if USE_OPENSSL
        if (sslBumpNeeded()) { 
            // We have to serve an error, so bump the client first.
            sslBumpNeed(Ssl::bumpClientFirst);
            // set final error but delay sending until we bump 
            Ssl::ServerBump *srvBump = new Ssl::ServerBump(request, e);
            errorAppendEntry(e, calloutContext->error);
            calloutContext->error = NULL; 
            getConn()->setServerBump(srvBump);
            e->unlock("ClientHttpRequest::doCallouts+sslBumpNeeded");
        } else  
#endif
        {       
            // send the error to the client now
            clientStreamNode *node = (clientStreamNode *)client_stream.tail->prev->data;
            clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
            assert (repContext);
            repContext->setReplyToStoreEntry(e, "immediate SslBump error");
            errorAppendEntry(e, calloutContext->error);
            calloutContext->error = NULL; 
            if (calloutContext->readNextRequest && getConn())
                getConn()->flags.readMore = true; // resume any pipeline reads.
            node = (clientStreamNode *)client_stream.tail->data;
            clientStreamRead(node, this, node->readBuffer);
            e->unlock("ClientHttpRequest::doCallouts-sslBumpNeeded");
            return; 
        }       
    }


If I change:

if (sslBumpNeeded()) {

to:

if (sslBumpNeeded() && 0) {

Then it correctly responds with ERR_ACCESS_DENIED. Otherwise it seems to proceed along and actually process and return the request.

I sincerely apologize for not, yet, being able to get my head around this new feature. But, it does seem like somehow calloutContext->error is getting lost or overridden by something else later in the processing chain.

It looks to me as if something is taking precedence over calloutContext->error.  But even if it was not, because the request is actually being processed it would allow a security hole where an attacker could map a private internal network of https services based on the time it takes them to respond - even if it allowed the connection.

Again, my apologies for the lack of detail.  This is my first time working with squid since late 1990’s, its obviously come a very long way since then.


Any ideas?

Regards,

Greg Saylor



More information about the squid-users mailing list