Re: [squid-users] Question about "proxy_auth REQUIRED" and the case of flushing the authentication-cache

From: Amos Jeffries <squid3_at_treenet.co.nz>
Date: Tue, 26 Feb 2013 14:31:03 +1300

On 25/02/2013 8:27 p.m., Tom Tom wrote:
> I've attached both cache-traces (squid 3.2.7).
>
> "without_407.txt" has the following configuration:
> ...
> ...
> external_acl_type SQUID_KERB_LDAP ttl=7200 children-max=10
> children-startup=1 children-idle=1 negative_ttl=7200 %LOGIN
> /usr/local/squid/libexec/ext_kerberos_ldap_group_acl -g
> "INTERNET_USERS"
> acl INTERNET_ACCESS external SQUID_KERB_LDAP
> acl AUTHENTICATED proxy_auth REQUIRED
> http_access deny !INTERNET_ACCESS
> http_access deny !AUTHENTICATED
> http_access allow INTERNET_ACCESS AUTHENTICATED
> http_access allow localhost
> http_access deny all
> ...
> ...

Note for anyone else reading this:
    The above was a copy-n-paste typo. The without-407 config has no
AUTHENTICATED access control definition.

> In this case, the access.log shows the following:
> Mon Feb 25 08:14:23 2013 15 10.X.X.X TCP_REFRESH_UNMODIFIED/304
> 283 GET http://imagesrv.adition.com/banners/750/683036/dummy.gif
> user_at_EXAMPLE.COM HIER_DIRECT/217.79.188.10 image/gif
>
>
>
> "with_407.txt" has the following configuration:
> ...
> ...
> external_acl_type SQUID_KERB_LDAP ttl=7200 children-max=10
> children-startup=1 children-idle=1 negative_ttl=7200 %LOGIN
> /usr/local/squid/libexec/ext_kerberos_ldap_group_acl -g
> "INTERNET_USERS"
> acl INTERNET_ACCESS external SQUID_KERB_LDAP
> acl AUTHENTICATED proxy_auth REQUIRED
> http_access deny !INTERNET_ACCESS
> http_access deny !AUTHENTICATED
> http_access allow INTERNET_ACCESS
> http_access allow localhost
> http_access deny all
> ...
> ...
>
>
> In this case, the access.log shows the following:
> Mon Feb 25 08:14:22 2013 0 10.X.X.X TCP_DENIED/407 4136 GET
> http://imagesrv.adition.com/banners/750/683036/dummy.gif - HIER_NONE/-
> text/html
> Mon Feb 25 08:14:22 2013 56 10.X.X.X TCP_REFRESH_UNMODIFIED/304
> 354 GET http://imagesrv.adition.com/banners/750/683036/dummy.gif
> user_at_EXAMPLE.COM HIER_DIRECT/217.79.188.10 image/gif
>
> The only different between config1 and config2 is the
> "AUTHENTICATED"-flag on the "http_access allow INTERNET_ACCESS" line.
>
> Many thanks.
> Kind regards,
> Tom

Thank you. I have an explanation for you. But I'm not exactly happy with
it how it is working in practice ...

The difference is the fine boundary between authentication and
authorization with a couple of factors (* marked) leading into the
behaviour:

* Negotiate auth protocol credentials, once delivered, are tied to the
TCP connection state.

Seems simple at face value, but HTTP is stateless - ie there is no TCP
connection state persistence between requests. So we have to jack up all
sorts of pinning an connection persistence just to make our HTTP
connections stateful for each client using Negotiate.

Keep in mind that Negotiate satetfulness is the anomally haunting us here.

* both your traces look like the connection is already setup and had
previous traffic so the request credentials should be checked against
the existing validated credentials.

* external_acl_type with %LOGIN is simply an authorization test. Are the
credentials we have allowing permission for this request to continue?
yes/no.

IMPORTANT: authorization takes no notice of validity of the credentials.
Or of their accuracy. Only existence and permissions assigned to it matters.

It locates credentials anywhere it can and uses those. In *both* your
traces the external ACL test locates credentials already tied to the TCP
connection state, which it validates with the helper as _authorized_.
The helper says OK, as you would expect since these connection
credentials were okay on previous traffic.

This is fine and consistent with external ACL definition as an
authorization API. It is not intended for use as authenticator.

  * proxy_auth ACL is an authentication test. Is the request user who
they claim to be? yes/no.

For this the request requires credentials which can be verified against
either the backend or against the tied credentials. To say yes the
credentials for this request are valid.
Your without-407 trace is the one doing proxy_auth test and detecting
that the HTTP request in fact has *no* credentials --> therefore fail
with 407 to get some.

In summary,
  * using only an external_acl_type login check with Negotiate (or NTLM)
authentication is equivalent to performing a IP-based authentication
bypass, but limited to bypass only on the TCP connection which has
already been authenticated.

All nice and consistent with the individual ACL tests and what they
mean. The part I'm not happy with is that with this config Squid lets
requests through without validating every single one has a credentials
token matching the tied connection credentials. I will have to look it
up in details and double-check but AFAIK that test SHOULD be done
regardless of what ACLs you configure just to ensure no requests are
injected into the stream by an attacker. For now I do recommend using
explicit proxy_auth tests before anything which requries credentials.

PS. I note that your ealier messages about the without-AUTHENTICATED
traffic being the ones getting 407 was incorrect. Which brings me to the
difference between 3.1 and 3.2.
  If the squid-3.1 proxy_auth test was using the connection tied
credentials and permitting requests through without validating the
request header properly, you would see the without-407 behaviour. That
would be a bug in 3.1 which was fixed in 3.2.

Amos
Received on Tue Feb 26 2013 - 01:31:21 MST

This archive was generated by hypermail 2.2.0 : Thu Feb 28 2013 - 12:00:04 MST