* Intercepted traffic which passes verification is handled
normally.
- For now it also forces suspicious requests to go DIRECT to the
- original destination, overriding client_dst_passthru for
- intercepted requests which fail Host: verification.
+ * Intercepted requests which fail verification are sent
+ to the client original destination instead of DIRECT.
+ This overrides 'client_dst_passthru off'.
For now suspicious intercepted CONNECT requests are always
responded to with an HTTP 409 (Conflict) error page.
-DOC_END
-
-NAME: client_dst_passthru
-TYPE: onoff
-DEFAULT: on
-LOC: Config.onoff.client_dst_passthru
-DOC_START
- With NAT or TPROXY intercepted traffic Squid may pass the request
- directly to the original client destination IP or seek a faster
- source.
- This option (on by default) prevents cache_peer and alternative DNS
- entries being used on intercepted traffic. Both of which lead to
- the security vulnerability outlined below.
- SECURITY WARNING:
-
- This directive should only be disabled if cache_peer are required.
+ SECURITY NOTE:
As described in CVE-2009-0801 when the Host: header alone is used
to determine the destination of a request it becomes trivial for
sandbox only verifies that the applet tries to contact the same IP
as from where it was loaded at the IP level. The Host: header may
be different from the connected IP and approved origin.
+
+DOC_END
+NAME: client_dst_passthru
+TYPE: onoff
+DEFAULT: on
+LOC: Config.onoff.client_dst_passthru
+DOC_START
+ With NAT or TPROXY intercepted traffic Squid may pass the request
+ directly to the original client destination IP or seek a faster
+ source using the HTTP Host header.
+
+ Using Host to locate alternative servers can provide faster
+ connectivity with a range of failure recovery options.
+ But can also lead to connectivity trouble when the client and
+ server are attempting stateful interactions unaware of the proxy.
+
+ This option (on by default) prevents alternative DNS entries being
+ located to send intercepted traffic DIRECT to an origin server.
+ The clients original destination IP and port will be used instead.
+
+ Regardless of this option setting, when dealing with intercepted
+ traffic Squid will verify the Host: header and any traffic which
+ fails Host verification will be treated as if this option were ON.
+
+ see host_verify_strict for details on the verification process.
DOC_END
COMMENT_START
const bool useOriginalDst = Config.onoff.client_dst_passthru || (request && !request->flags.hostVerified);
if (isIntercepted && useOriginalDst) {
selectPeerForIntercepted();
- // destination "found". continue with the forwarding.
+#if STRICT_ORIGINAL_DST
+ // 3.2 does not suppro re-wrapping inside CONNECT.
+ // our only alternative is to fake destination "found" and continue with the forwarding.
startConnectionOrFail();
- } else {
- // do full route options selection
- peerSelect(&serverDestinations, request, entry, fwdPeerSelectionCompleteWrapper, this);
+ return;
+#endif
}
+ // do full route options selection
+ peerSelect(&serverDestinations, request, entry, fwdPeerSelectionCompleteWrapper, this);
}
/// bypasses peerSelect() when dealing with intercepted requests
if (ConnStateData *client = request->pinnedConnection())
p = client->validatePinnedConnection(request, NULL);
- if (p != NULL && Comm::IsConnOpen(p)) {
- debugs(17, 3, HERE << "reusing a pinned conn: " << *p);
+ if (Comm::IsConnOpen(p)) {
/* duplicate peerSelectPinned() effects */
p->peerType = PINNED;
entry->ping_status = PING_DONE; /* Skip ICP */
- } else {
- p = new Comm::Connection();
- p->peerType = ORIGINAL_DST;
- p->remote = clientConn->local;
- getOutgoingAddress(request, p);
- debugs(17, 3, HERE << "opening a new conn: " << *p);
+
+ debugs(17, 3, HERE << "reusing a pinned conn: " << *p);
+ serverDestinations.push_back(p);
}
+ // use client original destination as second preferred choice
+ p = new Comm::Connection();
+ p->peerType = ORIGINAL_DST;
+ p->remote = clientConn->local;
+ getOutgoingAddress(request, p);
+
+ debugs(17, 3, HERE << "using client original destination: " << *p);
serverDestinations.push_back(p);
}
{
FwdServer *fs = psstate->servers;
+ // Bug 3243: CVE 2009-0801
+ // Bypass of browser same-origin access control in intercepted communication
+ // To resolve this we must use only the original client destination when going DIRECT
+ // on intercepted traffic which failed Host verification
+ const HttpRequest *req = psstate->request;
+ const bool isIntercepted = !req->flags.redirected &&
+ (req->flags.intercepted || req->flags.spoof_client_ip);
+ const bool useOriginalDst = Config.onoff.client_dst_passthru || !req->flags.hostVerified;
+ const bool choseDirect = fs && fs->code == HIER_DIRECT;
+ if (isIntercepted && useOriginalDst && choseDirect) {
+ // construct a "result" adding the ORIGINAL_DST to the set instead of DIRECT
+ Comm::ConnectionPointer p = new Comm::Connection();
+ p->remote = req->clientConnectionManager->clientConnection->local;
+ p->peerType = fs->code;
+ p->setPeer(fs->_peer);
+
+ // check for a configured outgoing address for this destination...
+ getOutgoingAddress(psstate->request, p);
+ psstate->paths->push_back(p);
+
+ // clear the used fs and continue
+ psstate->servers = fs->next;
+ cbdataReferenceDone(fs->_peer);
+ memFree(fs, MEM_FWD_SERVER);
+ peerSelectDnsPaths(psstate);
+ return;
+ }
+
// convert the list of FwdServer destinations into destinations IP addresses
if (fs && psstate->paths->size() < (unsigned int)Config.forward_max_tries) {
// send the next one off for DNS lookup.
for (size_t i = 0; i < psstate->paths->size(); ++i) {
if ((*psstate->paths)[i]->peerType == HIER_DIRECT)
debugs(44, 2, " DIRECT = " << (*psstate->paths)[i]);
+ else if ((*psstate->paths)[i]->peerType == ORIGINAL_DST)
+ debugs(44, 2, " ORIGINAL_DST = " << (*psstate->paths)[i]);
+ else if ((*psstate->paths)[i]->peerType == PINNED)
+ debugs(44, 2, " PINNED = " << (*psstate->paths)[i]);
else
debugs(44, 2, " cache_peer = " << (*psstate->paths)[i]);
}