Archive for category Security

Setting IP options in Scapy

Dur­ing this year iCTF (the world largest online hack­ing com­pe­ti­tion — very cool) my team faced the prob­lem of set­ting an IP header option in Scapy. That was needed to break a ser­vice that was rely­ing on IP addresses for authentication.

Now, Scapy is an awe­some project, but it lacks a bit on the doc­u­men­ta­tion side, as most of it is com­posed by a bunch of slides. Since IP options are over­looked in the docs and there is noth­ing find­able on the web that shows how to set them, I’ll post it here hop­ing to help some future fel­low googler — that might as well be future me.

Option to set: Loose Route/Record Route (the oth­ers work just the same):

>>> ip=IP(src="", dst="", options=IPOption('\x83\x03\x10'))
>>> ip.show2()
###[ IP ]###
version= 4L
ihl= 6L
tos= 0x0
len= 24
id= 1
frag= 0L
ttl= 64
proto= ip
chksum= 0xd4d0
|###[ IP Option Loose Source and Record Route ]###
|  copy_flag= 1L
|  optclass= control
|  option= loose_source_route
|  length= 3
|  pointer= 16
|  routers= []
|###[ IPOption_EOL ]###
|  copy_flag= 0L
|  optclass= contro
|  option= end_of_list

The ‘\x83\x03\x10’ has been cre­ated fol­low­ing the linked specs (\x83 is the type of the option, \x03 is the length, \x10 is the pointer).

Note that if you for­get the IPOp­tion() bit, your packet will be printed cor­rectly with show()/show2() but will refuse to be sent on the net­work. Instead, it will show this error (here for the sake of search engine indexing):

>>> send(IP(src="", dst="", options='\x83\x03\x10'))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/pymodules/python2.6/scapy/", line 247, in send
    __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose, realtime=realtime)
  File "/usr/lib/pymodules/python2.6/scapy/", line 230, in __gen_send
  File "/usr/lib/pymodules/python2.6/scapy/arch/", line 384, in send
    sx = str(ll(x))
  File "/usr/lib/pymodules/python2.6/scapy/arch/", line 382, in <lambda>
    ll = lambda x:conf.l2types[sn[3]]()/x
  File "/usr/lib/pymodules/python2.6/scapy/", line 260, in __div__
    cloneB = other.copy()
  File "/usr/lib/pymodules/python2.6/scapy/", line 140, in copy
  File "/usr/lib/pymodules/python2.6/scapy/", line 401, in do_copy
    return map(lambda p:p.copy(), x)
  File "/usr/lib/pymodules/python2.6/scapy/", line 401, in <lambda>
    return map(lambda p:p.copy(), x)
AttributeError: 'str' object has no attribute 'copy'


The misterious Web Proxy Automatic Discovery (WPAD) Italian exploit — Part IV

If you use fire­fox on a GNU/Linux machine, you can help us in find­ing which sites are the tar­gets of the Wpad exploit we blogged about (see part 3, part 2 and part 1 ).

Alessan­dro and I have writ­ten a script that checks the WPAD ital­ian reg­u­lar expression,

function FindProxyForURL(url, host) {
        //regular expression/complexity supported?
        if ( (shExpMatch(url, "http://*g*ad*nd*c*m*sh*ds*js")) || (shExpMatch(url, "http*//*s*st*mp*tn*sk*p*") &amp;&amp; !shExpMatch(url, "http*//*n*o.*")) ) { return "PROXY; DIRECT"; }
        return "DIRECT";

against the browser his­tory. Please make sure to close fire­fox before run­ning the script (since it accesses directly its his­tory data­base, which is locked when the browser is run­ning), and please report any pos­i­tive matches. Down­load the script by fol­low­ing this link.

No Comments

The misterious Web Proxy Automatic Discovery (WPAD) Italian exploit — Part III

Some weeks ago I (Jacopo Cor­betta) and Luca Inv­ernizzi wrote about a curi­ous Man-In-The-Middle poten­tial attack explot­ing flaws in the Web Proxy Auto­matic Dis­cov­ery (WPAD) and DNS pro­to­cols. Long story short, if you reg­is­ter a wpad.domain name you might be able to per­form a very stealthy Man-In-The-Middle attack. Now, DNS is com­pli­cated and pro­grams are buggy, so hijack­ing a wpad.Top-Level-Domain name like (or or (!) could expose a lot of com­put­ers to your attack.

You might recall that I was puz­zled by the con­tent of and won­dered what Ital­ian sites were tar­geted. Then Luca pointed out it was reg­is­tered by a pol­ish guy, and that he iden­ti­fied one of the pos­si­ble tar­gets as

We had in mind to run some analy­sis and then alert the reg­is­trars before post­ing again, but since the WPAD topic got atten­tion on Bug­Traq yes­ter­day it may be more timely to pub­lish our results now.

UPDATE: The wpad.dat served by the pol­ish guy changed! It appears they removed the site iden­ti­fied by Luca! The file was still in the orig­i­nal form when we reported our find­ings to the Ital­ian secu­rity mail­ing list (see this mes­sage posted on 21/05, Alessan­dro posted our results on 18/05). This thing is get­ting inter­est­ing... Any­way, here’s the new file:

function FindProxyForURL(url, host) {
        //regular expressions supported?
        if ( shExpMatch(url, "http*//*g*ad*nd*c*m*sh*ds*js") ) return "PROXY";
        return "DIRECT";

Hunt­ing for WPAD exploits

As we wrote before, the only reli­able list of effec­tive top level domains is the one used in the Mozilla code, pub­licly main­tained at Each of these domains — if reg­is­tered — could hide a mali­cious wpad.dat with poten­tially wide reach.

We think security-conscious DNS reg­is­trars should deny any request for these names — regard­less of whether the under­ly­ing WPAD vul­ner­a­bil­ity is wide­spread or not, we should do every­thing in our power to reduce the attack potential.

In our first ran­dom probes, we found the same strange wpad.dat on, and But then we got curi­ous: how com­mon is this prob­lem? How many wpad.dats are found in the wild? So I wrote a small python script which attempted to resolve all wpad.tld names and to retrieve the asso­ci­ated wpad.tld/wpad.dats.

The TLD menace

There are some­thing like 3370 top-level-domains in the list. 122 are actu­ally reg­is­tered and return an IP address. 62 of them return data when asked for a wpad.dat over HTTP.

11 of those wpad.dats look like generic “domain park­ing” pages. I am not com­pletely sure, since I don’t speak all those lan­guages. Here’s the list:

The and also look like some kind of redi­rect pages. This brings the total of innocu­ous1 domains to 13.

The wpad domains for Switzer­land and Liecht­en­stein (.ch and .li) return a “neu­tral” wpad.dat (that is, no proxy for any URL). For and an empty file is returned. I don’t know if this means that the wpad domain name was claimed by some good guy (like the one who reg­is­tered, for exam­ple). To be com­pletely sure we would need to per­form the query from Switzer­land or Rus­sia.2

The wpad.dats for, and look quite com­pli­cated and might even be legit­i­mate prox­y­ing attempts by a regional ISP. Addi­tional inves­ti­ga­tion would be required. Here are the files.

The remain­ing 42 wpad domains were serv­ing exactly the same wpad.dat file (now they have changed it! See our update on top) (indented for clarity):

function FindProxyForURL(url, host) {
        //regular expression/complexity supported?
        if ( (shExpMatch(url, "http://*g*ad*nd*c*m*sh*ds*js")) || 
             (shExpMatch(url, "http*//*s*st*mp*tn*sk*p*") &amp;&amp; 
             !shExpMatch(url, "http*//*n*o.*")) ) 
                return "PROXY; DIRECT";
        return "DIRECT";

All of these domains look have prob­a­bly been reg­is­tered by the same guy (even if WHOIS records are incon­clu­sive). The whois for even has his name (don’t know if it is accu­rate, though, so we’ll avoid post­ing names). Here is the list of affected domains:


As you can see, our friend has been able to grab the global wpad domain for 12 coun­tries includ­ing Poland, Italy, Spain, Aus­tria, Bel­gium, the Czech Repub­lic, Roma­nia and India.

Final thoughts and mysteries

The most obvi­ous rec­om­men­da­tion is that you reg­is­ter in your orga­ni­za­tion DNS (e.g. since our beloved school has and we admin­is­trate the sub­do­main, we have asso­ci­ated with a mean­ing­less IP and we’ll rec­om­mend the net­work staff to do the same with This will imme­di­ately stop the search for a wpad.dat by your clients.

We would also rec­om­mend reg­is­trars to delete wpad.domain entries or at least to avoid accept­ing new ones. As time allows (the exam ses­sion is near!) we’ll bring this mat­ter to the atten­tion of the reg­is­trar admins, let’s hope they lis­ten to us. If some­one with a big name is read­ing this (cool!), you might wish to con­tact some DNS authorities.

While Luca cracked the sec­ond wild­card expres­sion (http*//*s*st*mp*tn*sk*p*), we still have no idea about which sites are tar­geted by the first one (http://*g*ad*nd*c*m*sh*ds*js, maybe a JavaScript file?). And why did they use such a wide exclu­sion pat­tern (http*//*n*o.*) in the orig­i­nal file? Also, the proxy isn’t work­ing for us — maybe they are answer­ing only to IPs in Poland?

Now that some days ago the pol­ish guys changed their wpad.dat we won­der what should be our next move... and what will be their next move! We’ll post updates here, so stay tuned.

  1. The wpad.dat file has to be in a spe­cial Java-Script like for­mat, see for details []
  2. The server might be serv­ing a harm­less wpad.dat to for­eign hunters and a mali­cious one to domes­tic vic­tims (of course, this applies to all domains in this list — with the pos­si­ble excep­tion of Italy, our home coun­try) []

, , , ,


The misterious Web Proxy Automatic Discovery (WPAD) Italian exploit — Part II

After read­ing Jacopo’s arti­cle on WPAD, I’ve tried to under­stand the Ital­ian global

function FindProxyForURL(url, host) {
        //regular expression/complexity supported?
        if ( (shExpMatch(url, "http://*g*ad*nd*c*m*sh*ds*js")) || (shExpMatch(url, "http*//*s*st*mp*tn*sk*p*") &amp;&amp; !shExpMatch(url, "http*//*n*o.*")) ) { return "PROXY; DIRECT"; }
        return "DIRECT";

The proxy

First thing that con­cerned me is that the IP address used as proxy is pol­ish:
$host domain name pointer

It’s reg­is­tered to a guy in Wlo­clawek, and it’s been up since Decem­ber 2008, so it’s pretty new.  The hosted site is syn­da­cated, which it’s usu­ally a fishy sign.

The syn­tax

The scripts pro­vides a fall back pol­icy to direct con­nec­tion to avoid server over­load, as described in wikipedia

 return "PROXY; DIRECT"

The reg­u­lar expression

I’ve down­loaded Alexa top 1-million sites list, which is daily updated, and I dis­cov­ered that the sec­ond reg­u­lar expression,


gets one and only one match: a pol­ish inter­net trad­ing site.

$cat top-1m.csv |sed -ne "s/.*s.*st.*mp.*tn.*sk.*p.*/&amp;/p"

The first reg­u­lar expres­sion, even with­out the ini­tial and final part, does not match any site in Alexa first million.

, , , ,

No Comments

The misterious Web Proxy Automatic Discovery (WPAD) Italian exploit — Part I

The net­work here at Sant’Anna School of Advanced Stud­ies is quite com­pli­cated, so some­times the only way to solve a con­nec­tiv­ity prob­lem is to open Wire­shark and start look­ing around. As you may know, Win­dows boxes are quite chatty and they love to send out Net­BIOS broad­cast pack­ets to resolve names, elect popes, fight back with anti-popes, and so on. But this time I noticed some­thing strange in the broad­cast jam: a PC was con­ti­nously try­ing to reach the inex­is­tent WPAD.SSSUP.IT machine.

I got curi­ous, looked up what WPAD is, and found a cou­ple of inter­est­ing things.

What the heck is this WPAD thing?

It turns out Inter­net Explorer devel­op­ers thought an orga­ni­za­tion might wish to set up elab­o­rate rules for www prox­y­ing. There­fore, they devised a way for net­work admins to auto­con­fig­ure IE proxy set­tings: the Web Proxy Auto­matic Dis­cov­ery Pro­to­col (WPAD).  All major browsers cur­rently sup­port this fea­ture. Note that many appli­ca­tions on Win­dows default to fol­low­ing IE proxy set­tings, so the Man-In-The-Middle poten­tial is very high.

Basi­cally, the browser issues a request for 1, which should con­tain a Javascript-like func­tion called Find­Prox­y­ForURL. The func­tion can use wild­card match­ing to spec­ify dif­fer­ent prox­ies for dif­fer­ent addresses. All the gory details are avail­able at

Exploit­ing WPAD

Things can get com­pli­cated if you have a sub­do­main (e.g. if your com­puter is called then is tried too), but the key point is the same: if some­one hijacks one of your wpad names, sophis­ti­cated Man-In-The-Middle attacks are pos­si­ble. Since net­work admins often for­get to setup a wpad host for their domain, Win­dows may try to query in mul­ti­ple ways — even by broad­cast­ing a Net­BIOS request, which is triv­ial to inter­cept on a local net­work.2

Now, auto-configuration of net­work para­me­ters is very use­ful. Tools like DHCP and traspar­ent prox­ies are in wide use. How­ever, this kind of auto-configuration brings risks: rogue DHCP servers can be trans­par­ent to users and pos­si­bly avoid detec­tion. DHCP is a very well known pro­to­col and net­work admins have long learnt to watch out for sus­pi­cious DHCP activ­ity. WPAD is — in com­par­i­son — a some­what obscure pro­to­col. Buggy pro­grams (and lax poli­cies by domain reg­is­trars) cre­ate a sneaky exploit opportunity.

The DNS beast

As you might have guessed, Win­dows should stop short of the top-level domain .com in its quest for a wpad.dat. How­ever, two issues come into play:

  1. On cer­tain buggy ver­sions, the global is requested. Now, the domain has been taken by a (let’s hope) good guy, who chose not to serve a wpad.dat. But what about other Top-Level-Domains (TLDs) like or
  2. Some coun­tries (like Italy) allow you to reg­is­ter domain names right under their national suf­fix (e.g. our beloved School has Other coun­tries (the United King­dom, for instance) chose to mimic the global TLD struc­ture, so their addresses look like,, and so on. Some even mix the two policies.

Com­bine these two facts, and you get a big mess. Issue #2 means that when you see a domain name it is very hard to tell which is the TLD and which is the spe­cific domain name. It is not imme­di­ately obvi­ous, for instance, that is a global TLD (reserved for the ital­ian province of Pisa) while is the site of our arch-rival, the infa­mous Scuola Nor­male Superiore.

There is no “good” solu­tion to this prob­lem. Mozilla devel­op­ers ended up cret­ing a list of “Effec­tive TLDs“3 which the browser treats like global TLDs.

Each item on this list is an exploit oppor­tu­nity for the WPAD bug. Just reg­is­ter the domain and you poten­tially have con­trol of all buggy machines with a .it name

Attack on Italy: the mistery

You might think reg­is­trars would think twice before assign­ing a “” domain. It turns out that some­times this is not the case.

Some global wpad domains do exist and many of them serve a mali­cious wpad.dat. I’m gath­er­ing data and I’ll post when I have enough to make an inter­est­ing summary.

But take a look at this, the global

function FindProxyForURL(url, host) {
        //regular expression/complexity supported?
        if ( (shExpMatch(url, "http://*g*ad*nd*c*m*sh*ds*js")) || (shExpMatch(url, "http*//*s*st*mp*tn*sk*p*") &amp;&amp; !shExpMatch(url, "http*//*n*o.*")) ) { return "PROXY; DIRECT"; }
        return "DIRECT";

What the hell is this? It appears the attacker is tar­get­ing some spe­cific web­sites, but the wild­card is quite com­pli­cated. Any idea of what it might be?

UPDATE: found this same file on, full analy­sis in progress.

UPDATE: a more in depth analy­sis here and here

  1. Win­dows can also read its set­tings from DHCP and even from a spe­cial DNS entry. The offi­cial Microsoft doc­u­men­ta­tion is some­what sparse, but detailed infor­ma­tion can be found in the draft sub­mit­ted for stan­dard­iza­tion (pre­vi­ous ver­sion), inTech­Net, in some knowl­edge base arti­cles, and of course on Wikipedia. Another file which can be requested is wspad.dat, which has a dif­fer­ent for­mat. []
  2. Even when a WINS server is present, nam­ing your com­puter WPAD.YOURDOMAIN.COM might do the trick. []
  3. Browsers need this list to enforce cookie restric­tions (what if some­one was able a cookie on all “” domains?). The list is now pub­licly main­tained at []

, , , ,

1 Comment