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

From: Tom Tom <tomtux007_at_gmail.com>
Date: Thu, 28 Feb 2013 13:45:48 +0100

On Tue, Feb 26, 2013 at 2:31 AM, Amos Jeffries <squid3_at_treenet.co.nz> wrote:
> 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.
I think that the "without-407.txt" file HAS AUTHENTICATED access
control definition. The "without-407.txt" means (for me), that there
is NO 407 response. So this trace should show the behavior, where
squid accepts the request without firing the 407.
2013/02/25 07:26:30.936 kid1| Acl.cc(250) cacheMatchAcl:
ACL::cacheMatchAcl: cache hit on acl 'AUTHENTICATED' (0xaafa60)
2013/02/25 07:26:30.936 kid1| Acl.cc(312) checklistMatches:
ACL::ChecklistMatches: result for 'AUTHENTICATED' is 1

Is it possible, that squid uses his already filled up
credentials-cache (mapping of ie. username+ip with
kerberos-credentials) in the "without-407.txt"-trace? (look above:
cache hit on acl 'AUTHENTICATED'...)

>
>
>> 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.
Yes, before I took the traces, I made a few requests before (to
enforce the behavior).
>
>
> * 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.
No, this is in the "with-407.txt"-trace. In the
"without-407.txt"-trace squid doesn't fail with 407.

>
>
> 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.

In the trace/behavior, which provides me the 407 for each request,
there are "freeing"-tasks:
2013/02/25 07:36:51.392 kid1| UserRequest.cc(311) HandleReply:
authenticated user user_at_example.com
2013/02/25 07:36:51.392 kid1| User.cc(101) absorb: auth_user
'0xe6bef0*3' into auth_user '0x15a58b0'.
2013/02/25 07:36:51.392 kid1| User.cc(14) ~User: doing nothing to
clear Negotiate scheme data for '0xe6bef0'
2013/02/25 07:36:51.392 kid1| User.cc(154) ~User: Freeing auth_user '0xe6bef0'.

The things, which are unclear for me are:

<<config, which doesn't throw a 407 (which is working without 407)>>
...
http_access deny !AUTHENTICATED
http_access allow INTERNET_ACCESS AUTHENTICATED
...
- Does this config "activates" a kind of persistent credentials-cache?
If yes, what are the persistent-parameters (ie. ip-address, port,
user..)? With "squidclient mgr:username_cache", the username entry
persists until the the TTL expires or squid is reloading. If no
credentials-cache is present, why does squid accepts the request
without firing a 407 (although there is no proxy-authorization
provided in the request-header)?
- TCP-Traces are not showing any 407 (only in the the first
initial-request!) or any "proxy-authorization:"-headers in the
http-packet (for my example-request:
http://imagesrv.adition.com/banners/750/683036/dummy.gif)

<<config, which ends in a 407>>
http_access allow INTERNET_ACCESS
...
- This makes sens for me to fire a 407, if the client doesn't provide
the necessary credentials. EXCEPT: Squid should use a
credential-cache.
- With this config, after EVERY request, "squidclient
mgr:username_cache" resets the TTL counter. Does this probably relate
with the "freeing"-tasks above?

When I change the line from 'http_access allow INTERNET_ACCESS
AUTHENTICATED' to 'http_access allow AUTHENTICATED INTERNET_ACCESS',
then I always got a 407. Squidclient then also resets the TTL
respectively cleans the entry and creates a new one...).

Do I understand correctly, that in your point of view squid should
always throw a 407, If no credentials are provided within the
requests? Even squid has an entry in his credential/username cache?
Does the "username_cache" also means "credentials-cache"? Is there
generally a credentials-cache existing?

Many thanks for your help and explanations.
Tom

>
>
> 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 Thu Feb 28 2013 - 12:45:54 MST

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