Re: Simple way to bypass squid ACLs [preleminary patch]

Henrik Nordstrom (hno@HEM.PASSAGEN.SE)
Sat, 21 Feb 1998 01:28:45 +0100

This is a multi-part message in MIME format.

--Boundary_(ID_6GoC4lVP5xZB7hGkgNTZpQ)
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: quoted-printable

Vitaly V. Fedrushkov wrote:

> Software: Squid Internet Object Cache
> Version: 1.1.20 (at least)
> Summary: any URL-based ACLs can be bypassed using
> simple rewriting
> Impact: renders any access control based on url_regex
> and/or urlpath_regex unusable

Confirmed for all current Squid releases (1.1.20 and 1.2beta15).

[some examples and details deleted]

> Workaround
> ~~~~~~~~~~
[rexep workaround deleted]
> 2. Use some request-rewriting software at proxy port to canonify
> request and forward it to squid. This breaks port- and IDENT-based
> rules.

This breaks HTTP 1.1. In HTTP 1.1 a proxy is explicitly forbidden to
transform URLs. If a client has escaped a URL in a certain way it is
required that it arrives on the same format to the server, since a
escaped url may result in a different object.

What should be done is to temporarily unescape the URL for ACL
processing only. I have attached preleminary patches for Squid 1.1.2 and
1.2beta15 (preleminary =3D=3D only basic testing completed, not official)=
=2E

The patches is available from http://hem.passagen.se/hno/squid/ as well.

---
Henrik Nordstr=F6m
Sparetime Squid Hacker

--Boundary_(ID_6GoC4lVP5xZB7hGkgNTZpQ) Content-type: text/plain; name=squid-1.1.20.escaped_url_acl.patch; charset=us-ascii Content-disposition: inline; filename=squid-1.1.20.escaped_url_acl.patch Content-transfer-encoding: 7bit

Index: squid-1.1.20/src/acl.c --- squid-1.1.20/src/acl.c Mon Nov 3 20:27:08 1997 +++ squid-1.1.20.henrik/src/acl.c Sat Feb 21 00:42:01 1998 @@ -1105,10 +1105,10 @@ return aclMatchTime(acl->data, squid_curtime); /* NOTREACHED */ case ACL_URLPATH_REGEX: - return aclMatchRegex(acl->data, r->urlpath); + return aclMatchRegex(acl->data, checklist->urlpath); /* NOTREACHED */ case ACL_URL_REGEX: - return aclMatchRegex(acl->data, urlCanonical(r, NULL)); + return aclMatchRegex(acl->data, checklist->url); /* NOTREACHED */ case ACL_URL_PORT: return aclMatchInteger(acl->data, r->port); Index: squid-1.1.20/src/acl.h --- squid-1.1.20/src/acl.h Thu Feb 20 22:03:10 1997 +++ squid-1.1.20.henrik/src/acl.h Sat Feb 21 00:43:41 1998 @@ -124,6 +124,8 @@ struct in_addr dst_addr; char src_fqdn[SQUIDHOSTNAMELEN]; request_t *request; + char url[MAX_URL]; + char *urlpath; char ident[ICP_IDENT_SZ]; char browser[BROWSERNAMELEN]; acl_lookup_state state[ACL_ENUM_MAX]; Index: squid-1.1.20/src/client_side.c --- squid-1.1.20/src/client_side.c Wed Nov 19 17:44:51 1997 +++ squid-1.1.20.henrik/src/client_side.c Sat Feb 21 01:03:07 1998 @@ -31,6 +31,8 @@

#include "squid.h"

+extern void rfc1738_unescape _PARAMS((char *)); + static void clientRedirectDone _PARAMS((void *data, char *result)); static void icpHandleIMSReply _PARAMS((int fd, StoreEntry * entry, void *data)); static void clientLookupDstIPDone _PARAMS((int fd, const ipcache_addrs *, void *data)); @@ -155,6 +157,19 @@ icpState->aclChecklist = xcalloc(1, sizeof(aclCheck_t)); icpState->aclChecklist->src_addr = icpState->peer.sin_addr; icpState->aclChecklist->request = requestLink(icpState->request); + strcpy(icpState->aclChecklist->url, + urlCanonical(icpState->request, NULL)); + rfc1738_unescape(icpState->aclChecklist->url); + icpState->aclChecklist->urlpath = + strchr(icpState->aclChecklist->url, '/'); + if (icpState->aclChecklist->urlpath != NULL) + icpState->aclChecklist->urlpath = + strchr(icpState->aclChecklist->url+1, '/'); + if (icpState->aclChecklist->urlpath != NULL) + icpState->aclChecklist->urlpath = + strchr(icpState->aclChecklist->url+1, '/'); + if (icpState->aclChecklist->urlpath == NULL) + icpState->aclChecklist->urlpath = ""; browser = mime_get_header(icpState->request_hdr, "User-Agent"); if (browser != NULL) { xstrncpy(icpState->aclChecklist->browser, browser, BROWSERNAMELEN); Index: squid-1.1.20/src/neighbors.c --- squid-1.1.20/src/neighbors.c Sat Nov 1 02:34:19 1997 +++ squid-1.1.20.henrik/src/neighbors.c Sat Feb 21 01:00:37 1998 @@ -105,6 +105,8 @@

#include "squid.h"

+extern void rfc1738_unescape _PARAMS((char *)); + /* count mcast group peers every 15 minutes */ #define MCAST_COUNT_RATE 900

@@ -246,6 +248,15 @@ } checklist.src_addr = request->client_addr; checklist.request = request; + strcpy(checklist.url, urlCanonical(request, NULL)); + rfc1738_unescape(checklist.url); + checklist.urlpath = strchr(checklist.url, '/'); + if (checklist.urlpath != NULL) + checklist.urlpath = strchr(checklist.urlpath+1, '/'); + if (checklist.urlpath != NULL) + checklist.urlpath = strchr(checklist.urlpath+1, '/'); + if (checklist.urlpath == NULL) + checklist.urlpath = ""; for (a = e->acls; a; a = a->next) { if (aclMatchAcl(a->acl, &checklist)) return a->op;

--Boundary_(ID_6GoC4lVP5xZB7hGkgNTZpQ) Content-type: text/plain; name=squid-1.2.beta15.escaped_url_acl.patch; charset=us-ascii Content-disposition: inline; filename=squid-1.2.beta15.escaped_url_acl.patch Content-transfer-encoding: 7bit

Index: squid/src/acl.c diff -u squid/src/acl.c:1.1.1.12 squid/src/acl.c:1.1.1.12.2.1 --- squid/src/acl.c:1.1.1.12 Sat Feb 14 01:00:20 1998 +++ squid/src/acl.c Sat Feb 21 01:05:32 1998 @@ -1300,10 +1300,10 @@ return aclMatchTime(acl->data, squid_curtime); /* NOTREACHED */ case ACL_URLPATH_REGEX: - return aclMatchRegex(acl->data, r->urlpath); + return aclMatchRegex(acl->data, checklist->urlpath); /* NOTREACHED */ case ACL_URL_REGEX: - return aclMatchRegex(acl->data, urlCanonical(r, NULL)); + return aclMatchRegex(acl->data, checklist->url); /* NOTREACHED */ case ACL_URL_PORT: return aclMatchInteger(acl->data, r->port); @@ -1547,6 +1547,16 @@ cbdataLock(A); checklist->request = requestLink(request); checklist->src_addr = src_addr; + /* Build a unescaped URL & path */ + strcpy(checklist->url, urlCanonical(request, NULL)); + rfc1738_unescape(checklist->url); + checklist->urlpath=strchr(checklist->url, '/'); + if (checklist->urlpath != NULL) + checklist->urlpath=strchr(checklist->urlpath+1, '/'); + if (checklist->urlpath != NULL) + checklist->urlpath=strchr(checklist->urlpath+1, '/'); + if (checklist->urlpath == NULL) + checklist->urlpath = ""; for (i = 0; i < ACL_ENUM_MAX; i++) checklist->state[i] = ACL_LOOKUP_NONE; if (user_agent) Index: squid/src/structs.h diff -u squid/src/structs.h:1.1.1.13 squid/src/structs.h:1.1.1.13.2.1 --- squid/src/structs.h:1.1.1.13 Sat Feb 14 01:00:34 1998 +++ squid/src/structs.h Sat Feb 21 01:05:34 1998 @@ -111,6 +111,8 @@ struct in_addr src_addr; struct in_addr dst_addr; request_t *request; + char url[MAX_URL]; + char *urlpath; char ident[ICP_IDENT_SZ]; char browser[BROWSERNAMELEN]; acl_lookup_state state[ACL_ENUM_MAX];

--Boundary_(ID_6GoC4lVP5xZB7hGkgNTZpQ)--