{
	"id": "64581bf3-5dfa-4973-9be8-f45001ccb322",
	"created_at": "2026-04-29T02:20:42.392486Z",
	"updated_at": "2026-04-29T08:21:31.059611Z",
	"deleted_at": null,
	"sha1_hash": "1428b84816e7ed5659ef20099e3bc9bfec29f139",
	"title": "Evilginx 2 - Next Generation of Phishing 2FA Tokens",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1376196,
	"plain_text": "Evilginx 2 - Next Generation of Phishing 2FA Tokens\r\nBy Kuba Gretzky\r\nPublished: 2018-07-26 · Archived: 2026-04-29 02:11:06 UTC\r\nIt's been over a year since the first release of Evilginx and looking back, it has been an amazing year. I've received\r\ntons of feedback, got invited to WarCon by @antisnatchor (thanks man!) and met amazing people from the\r\nindustry. A year ago, I wouldn't have even expected that one day Kevin Mitnick would showcase Evilginx in his\r\nlive demos around the world and Techcrunch would write about it!\r\nAt WarCon I met the legendary @evilsocket (he is a really nice guy), who inspired me with his ideas to learn GO\r\nand rewrite Evilginx as a standalone application. It is amazing how GO seems to be ideal for offensive tools\r\ndevelopment and bettercap is its best proof!\r\nThis is where Evilginx is now. No more nginx, just pure evil. My main goal with this tool's release was to focus on\r\nminimizing the installation difficulty and maximizing the ease of use. Usability was not necessarily the strongest\r\npoint of the initial release.\r\nUpdated instructions on usage and installation can always be found up-to-date on the tool's official GitHub project\r\npage. In this blog post I only want to explain some general concepts of how it works and its major features.\r\nUpdate: Check also version 2.1 release post\r\nTL;DR What am I looking at?\r\nEvilginx is an attack framework for setting up phishing pages. Instead of serving templates of sign-in pages\r\nlookalikes, Evilginx becomes a relay between the real website and the phished user. Phished user interacts\r\nwith the real website, while Evilginx captures all the data being transmitted between the two parties.\r\nEvilginx, being the man-in-the-middle, captures not only usernames and passwords, but also captures\r\nauthentication tokens sent as cookies. Captured authentication tokens allow the attacker to bypass any form of\r\n2FA enabled on user's account (except for U2F - more about it further below).\r\nEven if phished user has 2FA enabled, the attacker, outfitted with just a domain and a VPS server, is able to\r\nremotely take over his/her account. It doesn't matter if 2FA is using SMS codes, mobile authenticator app or\r\nrecovery keys.\r\nTake a look at the video demonstration, showing how attacker's can remotely hack an Outlook account with\r\nenabled 2FA.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 1 of 17\n\nSorry\r\nThis video does not exist.\r\nDisclaimer: Evilginx project is released for educational purposes and should be used only in\r\ndemonstrations or legitimate penetration testing assignments with written permission from to-be-phished parties. Goal is to show that 2FA is not a silver bullet against phishing attempts and people\r\nshould be aware that their accounts can be compromised, nonetheless, if they are not careful.\r\n[\u003e\u003e Download Evilginx 2 from GitHub \u003c\u003c](https://github.com/kgretzky/evilginx2)\r\n**Remember - 2FA is not a silver bullet against phishing!**\r\n2FA is very important, though. This is what head of Google Threat Intelligence had to say on the subject:\r\nOld phishing tactics\r\nCommon phishing attacks, we see every day, are HTML templates, prepared as lookalikes of popular websites'\r\nsign-in pages, luring victims into disclosing their usernames and passwords. When the victim enters his/her\r\nusername and password, the credentials are logged and attack is considered a success.\r\nI love digging through certificate transparency logs. Today, I saw a fake Google Drive landing page\r\nfreshly registered with Let's Encrypt. It had a hardcoded picture/email of presumably the target. These\r\ncan be a wealth of info that I recommend folks checking out. pic.twitter.com/PRweQsgHKD\r\n— Justin Warner (@sixdub) July 22, 2018\r\nThis is where 2FA steps in. If phished user has 2FA enabled on their account, the attacker would require an\r\nadditional form of authentication, to supplement the username and password they intercepted through phishing.\r\nThat additional form of authentication may be SMS code coming to your mobile device, TOTP token, PIN number\r\nor answer to a question that only the account owner would know. Attacker not having access to any of these will\r\nnever be able to successfully authenticate and login into victim's account.\r\nOld phishing methods which focus solely on capturing usernames and passwords are completely defeated by\r\n2FA.\r\nPhishing 2.0\r\nWhat if it was possible to lure the victim not only to disclose his/her username and password, but also to provide\r\nthe answer to any 2FA challenge that may come after the credentials are verified? Intercepting a single 2FA\r\nanswer would not do the attacker any good. Challenge will change with every login attempt, making this approach\r\nuseless.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 2 of 17\n\nAfter each successful login, website generates an authentication token for the user's session. This token (or\r\nmultiple tokens) is sent to the web browser as a cookie and is saved for future use. From that point, every request\r\nsent from the browser to the website will contain that session token, sent as a cookie. This is how websites\r\nrecognize authenticated users after successful authentication. They do not ask users to log in, every time when\r\npage is reloaded.\r\nThis session token cookie is pure gold for the attacker. If you export cookies from your browser and import\r\nthem into a different browser, on a different computer, in a different country, you will be authorized and get full\r\naccess to the account, without being asked for usernames, passwords or 2FA tokens.\r\nThis is what it looks like, in Evilginx 2, when session token cookie is successfully captured:\r\nNow that we know how valuable the session cookie is, how can the attacker intercept it remotely, without having\r\nphysical access to the victim's computer?\r\nCommon phishing attacks rely on creating HTML templates which take time to make. Most work is spent on\r\nmaking them look good, being responsive on mobile devices or properly obfuscated to evade phishing detection\r\nscanners.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 3 of 17\n\nEvilginx takes the attack one step further and instead of serving its own HTML lookalike pages, it becomes a\r\nweb proxy. Every packet, coming from victim's browser, is intercepted, modified and forwarded to the real\r\nwebsite. The same happens with response packets, coming from the website; they are intercepted, modified and\r\nsent back to the victim. With Evilginx there is no need to create your own HTML templates. On the victim side\r\neverything looks as if he/she was communicating with the legitimate website. User has no idea idea that Evilginx\r\nsits as a man-in-the-middle, analyzing every packet and logging usernames, passwords and, of course, session\r\ncookies.\r\nYou may ask now, what about encrypted HTTPS connection using SSL/TLS that prevents eavesdropping on the\r\ncommunication data? Good question. Problem is that the victim is only talking, over HTTPS, to Evilginx server\r\nand not the true website itself. Evilginx initiates its own HTTPS connection with the victim (using its own\r\nSSL/TLS certificates), receives and decrypts the packets, only to act as a client itself and establish its own\r\nHTTPS connection with the destination website, where it sends the re-encrypted packets, as if it was the victim's\r\nbrowser itself. This is how the trust chain is broken and the victim still sees that green lock icon next to the\r\naddress bar, in the browser, thinking that everyone is safe.\r\nWhen the victim enters the credentials and is asked to provide a 2FA challenge answer, they are still talking to the\r\nreal website, with Evilginx relaying the packets back and forth, sitting in the middle. Even while being phished,\r\nthe victim will still receive the 2FA SMS code to his/her mobile phone, because he/she is talking to the real\r\nwebsite (just through a relay).\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 4 of 17\n\nAfter the 2FA challenge is completed by the victim and the website confirms its validity, website generates the\r\nsession token, which it returns in form of a cookie. This cookie is intercepted by Evilginx and saved. Evilginx\r\ndetermines that authentication was a success and redirects the victim to any URL it was set up with (online\r\ndocument, video etc.).\r\nAt this point the attacker holds all the keys to the castle and is able to use the victim's account, fully bypassing\r\n2FA protection, after importing the session token cookies into his web browser.\r\nBe aware that: Every sign-in page, requiring the user to provide their password, with any form of 2FA\r\nimplemented, can be phished using this technique!\r\nHow to protect yourself?\r\nThere is one major flaw in this phishing technique that anyone can and should exploit to protect themselves - the\r\nattacker must register their own domain.\r\nBy registering a domain, attacker will try to make it look as similar to real, legitimate domain as possible. For\r\nexample if the attacker is targeting Facebook (real domain is facebook.com ), they can, for example, register a\r\ndomain faceboook.com or faceb00k.com , maximizing their chances that phished victims won't spot the\r\ndifference in the browser's address bar.\r\nThat said - always check the legitimacy of website's base domain, visible in the address bar, if it asks you to\r\nprovide any private information. By base domain I mean the one that precedes the top-level domain.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 5 of 17\n\nAs an example, imagine this is the URL and the website, you arrived at, asks you to log into Facebook:\r\nhttps://en-gb.facebook.cdn.global.faceboook.com/login.php\r\nThe top-level domain is .com and the base domain would be the preceeding word, with next . as a separator.\r\nCombined with TLD, that would be faceboook.com . When you verify that faceboook.com is not the real\r\nfacebook.com , you will know that someone is trying to phish you.\r\nAs a side note - Green lock icon seen next to the URL, in the browser's address bar, does not mean that you\r\nare safe!\r\nGreen lock icon only means that the website you've arrived at, encrypts the transmission between you and the\r\nserver, so that no-one can eavesdrop on your communication. Attackers can easily obtain SSL/TLS certificates\r\nfor their phishing sites and give you a false sense of security with the ability to display the green lock icon as well.\r\nFiguring out if the base domain you see is valid, sometimes may not be easy and leaves room for error. It became\r\neven harder with the support of Unicode characters in domain names. This made it possible for attackers to\r\nregister domains with special characters (e.g. in Cyrillic) that would be lookalikes of their Latin counterparts. This\r\ntechnique recieved a name of a homograph attack.\r\nAs a quick example, an attacker could register a domain facebooĸ.com , which would look pretty convincing\r\neven though it was a completely different domain name ( ĸ is not really k ). It got even worse with other\r\nCyrillic characters, allowing for ebаy.com vs ebay.com . The first one has an Cyrillic counterpart for a\r\ncharacter, which looks exactly the same.\r\nMajor browsers were fast to address the problem and added special filters to prevent domain names from being\r\ndisplayed in Unicode, when suspicious characters were detected.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 6 of 17\n\nIf you are interested in how it works, check out the IDN spoofing filter source code of the Chrome browser.\r\nNow you see that verifying domains visually is not always the best solution, especially for big companies, where\r\nit often takes just one employee to get phished and allow attackers to steal vast amounts of data.\r\nThis is why FIDO Alliance introduced U2F (Universal 2nd Factor Authentication) to allow for unphishable 2nd\r\nfactor authentication.\r\nIn short, you have a physical hardware key on which you just press a button when the website asks you to.\r\nAdditionally it may ask you for account password or a complementary 4 digit PIN. The website talks directly with\r\nthe hardware key plugged into your USB port, with the web browser as the channel provider for the\r\ncommunication.\r\nYubiKey slide\r\nWhat is different with this form of authentication, is that U2F protocol is designed to take the website's domain\r\nas one of the key components in negotiating the handshake. This means that if the domain in the browser's\r\naddress bar, does not match the domain used in the data transmission between the website and the U2F device, the\r\ncommunication will simply fail. This solution leaves no room for error and is totally unphishable using\r\nEvilginx method.\r\nCiting the vendor of U2F devices - Yubico (who co-developed U2F with Google):\r\nWith the YubiKey, user login is bound to the origin, meaning that only the real site can authenticate\r\nwith the key. The authentication will fail on the fake site even if the user was fooled into thinking it was\r\nreal. This greatly mitigates against the increasing volume and sophistication of phishing attacks and\r\nstops account takeovers.\r\nIt is important to note here that Markus Vervier (@marver) and Michele Orrù (@antisnatchor) did demonstrate a\r\ntechnique on how an attacker can attack U2F devices using the newly implemented WebUSB feature in modern\r\nbrowsers (which allows websites to talk with USB connected devices). It is also important to mention that Yubico,\r\nthe creator of popular U2F devices YubiKeys, tried to steal credit for their research, which they later apologized\r\nfor.\r\nYou can find the list of all websites supporting U2F authentication here.\r\nCoinciding with the release of Evilginx 2, WebAuthn is coming out in all major web browsers. It will introduce\r\nthe new FIDO2 password-less authentication standard to every browser. Chrome, Firefox and Edge are about to\r\nreceive full support for it.\r\nTo wrap up - if you often need to log into various services, make your life easier and get a U2F device! This will\r\ngreatly improve your accounts' security.\r\nUnder the hood\r\nInterception of HTTP packets is possible since Evilginx acts as an HTTP server talking to the victim's browser\r\nand, at the same time, acts as an HTTP client for the website where the data is being relayed to. To make it\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 7 of 17\n\npossible, the victim has to be contacting Evilginx server through a custom phishing URL that will point to\r\nEvilginx server. Simply forwarding packets from victim to destination website would not work well and that's why\r\nEvilginx has to do some on-the-fly modifications.\r\nIn order for the phishing experience to be seamless, the proxy overcomes the following obstacles:\r\n1. Making sure that the victim is not redirected to phished website's true domain.\r\nSince the phishing domain will differ from the legitimate domain, used by phished website, relayed scripts and\r\nHTML data have to be carefully modified to prevent unwanted redirection of victim's web browser. There will\r\nbe HTML submit forms pointing to legitimate URLs, scripts making AJAX requests or JSON objects containing\r\nURLs.\r\nIdeally the most reliable way to solve it would be to perform regular expression string substitution for any\r\noccurrence of https://legit-site.com and replacing it with https://our-phishing-site.com . Unfortunately\r\nthis is not always the case and it requires some trial and error kung-fu, working with web inspector to track down\r\nall strings the proxy needs to replace to not break website's functionality. If target website uses multiple options\r\nfor 2FA, each route has to be inspected and analyzed.\r\nFor example, there are JSON objects transporting escaped URLs like https:\\/\\/legit-site.com . You can see\r\nthat this will definitely not trigger the regexp mentioned above. If you replaced all occurrences of legit-site.com you may break something by accident.\r\n2. Responding to DNS requests for multiple subdomains.\r\nWebsites will often make requests to multiple subdomains under their official domain or even use a totally\r\ndifferent domain. In order to proxy these transmissions, Evilginx has to map each of the custom subdomains to\r\nits own IP address.\r\nPrevious version of Evilginx required the user to set up their own DNS server (e.g. bind ) and set up DNS zones\r\nto properly handle DNS A requests. This generated a lot of headache on the user part and was only easier if the\r\nhosting provider (like Digital Ocean) provided an easy-to-use admin panel for setting up DNS zones.\r\nWith Evilginx 2 this issue is gone. Evilginx now runs its own in-built DNS server, listening on port 53, which acts\r\nas a nameserver for your domain. All you need to do is set up the nameserver addresses for your domain\r\n( ns1.yourdomain.com and ns2.yourdomain.com ) to point to your Evilginx server IP, in the admin panel of your\r\ndomain hosting provider. Evilginx will handle the rest on its own.\r\n3. Modification of various HTTP headers.\r\nEvilginx modifies HTTP headers sent to and received from the destination website. In particular the Origin\r\nheader, in AJAX requests, will always hold the URL of the requesting site in order to comply with CORS.\r\nPhishing sites will hold a phishing URL as an origin. When request is forwarded, the destination website will\r\nreceive an invalid origin and will not respond to such request. Not replacing the phishing hostname with the\r\nlegitimate one in the request would make it also easy for the website to notice suspicious behavior. Evilginx\r\nautomatically changes Origin and Referer fields on-the-fly to their legitimate counterparts.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 8 of 17\n\nSame way, to avoid any conflicts with CORS from the other side, Evilginx makes sure to set the Access-Control-Allow-Origin header value to * (if it exists in the response) and removes any occurrences of Content-Security-Policy headers. This guarantees that no request will be restricted by the browser when AJAX\r\nrequests are made.\r\nOther header to modify is Location , which is set in HTTP 302 and 301 responses to redirect the browser to\r\ndifferent location. Naturally the value will come with legitimate website URL and Evilginx makes sure this\r\nlocation is properly switched to corresponding phishing hostname.\r\n4. Cookies filtering.\r\nIt is common for websites to manage cookies for various purposes. Each cookie is assigned to a specific domain.\r\nWeb browser's task is to automatically send the stored cookie, with every request to the domain, the cookie was\r\nassigned to. Cookies are also sent as HTTP headers, but I decided to make a separate mention of them here, due to\r\ntheir importance. Example cookie sent from the website to client's web browser would look like this:\r\nSet-Cookie: qwerty=219ffwef9w0f; Domain=legit-site.com; Path=/; Expires=Wed, 30 Aug 2019 00:00:00 GMT\r\nAs you can see the cookie will be set in client's web browser for legit-site.com domain. Since the phishing\r\nvictim is only talking to the phishing website with domain our-phishing-site.com , such cookie will never be\r\nsaved in the browser, because of the fact the cookie domain differs from the one the browser is communicating\r\nwith. Evilginx will parse every occurrence of Set-Cookie in HTTP response headers and modify the domain,\r\nreplacing it with the phishing one, as follows:\r\nSet-Cookie: qwerty=219ffwef9w0f; Domain=our-phishing-site.com; Path=/;\r\nEvilginx will also remove expiration date from cookies, if the expiration date does not indicate that the cookie\r\nshould be deleted from browser's cache.\r\nEvilginx also sends its own cookies to manage the victim's session. These cookies are filtered out from every\r\nHTTP request, to prevent them from being sent to the destination website.\r\n5. SSL splitting.\r\nAs the whole world of world-wide-web migrates to serving pages over secure HTTPS connections, phishing pages\r\ncan't be any worse. Whenever you pick a hostname for your phishing page (e.g.\r\ntotally.not.fake.linkedin.our-phishing-domain.com ), Evilginx will automatically obtain a valid SSL/TLS\r\ncertificate from LetsEncrypt and provide responses to ACME challenges, using the in-built HTTP server.\r\nThis makes sure that victims will always see a green lock icon next to the URL address bar, when visiting the\r\nphishing page, comforting them that everything is secured using \"military-grade\" encryption!\r\n6. Anti-phishing tricks\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 9 of 17\n\nThere are rare cases where websites would employ defenses against being proxied. One of such defenses I\r\nuncovered during testing is using javascript to check if window.location contains the legitimate domain. These\r\ndetections may be easy or hard to spot and much harder to remove, if additional code obfuscation is involved.\r\nImprovements\r\nThe greatest advantage of Evilginx 2 is that it is now a standalone console application. There is no need to\r\ncompile and install custom version of nginx, which I admit was not a simple feat. I am sure that using nginx site\r\nconfigs to utilize proxy_pass feature for phishing purposes was not what HTTP server's developers had in mind,\r\nwhen developing the software.\r\nEvilginx 1 was pretty much a combination of several dirty hacks, duct taped together. Nonetheless it\r\nsomehow worked!\r\nAdditionally to fully responsive console UI, here are the greatest improvements:\r\nTokenized phishing URLs\r\nIn previous version of Evilginx, entering just the hostname of your phishing URL address in the browser, with root\r\npath (e.g. https://totally.not.fake.linkedin.our-phishing-domain.com/ ), would still proxy the connection to\r\nthe legitimate website. This turned out to be an issue, as I found out during development of Evilginx 2. Apparently\r\nonce you obtain SSL/TLS certificates for the domain/hostname of your choice, external scanners start scanning\r\nyour domain. Scanners gonna scan.\r\nThe scanners use public certificate transparency logs to scan, in real-time, all domains which have obtained valid\r\nSSL/TLS certifcates. With public libraries like CertStream, you can easily create your own scanner.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 10 of 17\n\nFor some phishing pages, it took usually one hour for the hostname to become banned and blacklisted by\r\npopular anti-spam filters like Spamhaus. After I had three hostnames blacklisted for one domain, the whole\r\ndomain got blocked. Three strikes and you're out!\r\nI began thinking how such detection can be evaded. Easiest solution was to reply with faked response to every\r\nrequest for path / , but that would not work if scanners probed for any other path.\r\nThen I decided that each phishing URL, generated by Evilginx, should come with a unique token in the URL as a\r\nGET parameter.\r\nFor example, Evilginx responds with redirection response when scanner makes a request to URL:\r\nhttps://totally.not.fake.linkedin.our-phishing-domain.com/auth/signin\r\nBut it responds with proxied phishing page, instead, when the URL is properly tokenized, with a valid token:\r\nhttps://totally.not.fake.linkedin.our-phishing-domain.com/auth/signin?tk=secret_l33t_token\r\nWhen tokenized URL is opened, Evilginx sets a validation cookie in victim's browser, whitelisting all\r\nsubsequent requests, even for the non-tokenized ones.\r\nThis works very well, but there is still risk that scanners will eventually scan tokenized phishing URLs when these\r\nget out into the interwebz.\r\nHiding your phishlets\r\nThis thought provoked me to find a solution that allows manual control over when the phishing proxy should\r\nrespond with proxied website and when it should not. As a result, you can hide and unhide the phishign page\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 11 of 17\n\nwhenever you want. Hidden phishing page will respond with a redirection 302 HTTP code, redirecting the\r\nrequester to predefined URL (Rick Astley's famous clip on Youtube is the default).\r\nTemporarily hiding your phishlet may be useful when you want to use a URL shortener, to shorten your phishing\r\nURL (like goo.gl or bit.ly ) or when you are sending the phishing URL via email and you don't want to\r\ntrigger any email scanners, on the way.\r\nPhishlets\r\nPhishlets are new site configs. They are plain-text ruleset files, in YAML format, which are fed into the Evilginx\r\nengine. Phishlets define which subdomains are needed to properly proxy a specific website, what strings should be\r\nreplaced in relayed packets and which cookies should be captured, to properly take over the victim's account.\r\nThere is one phishlet for each phished website. You can deploy as many phishlets as you want, with each phishlet\r\nset up for a different website. Phishlets can be enabled and disabled as you please and at any point Evilginx can be\r\nrunning and managing any number of them.\r\nI will do a better job than I did last time, when I released Evilginx 1, and I will try to explain the structure of a\r\nphishlet and give you brief insight into how phishlets are created (I promise to release a separate blog post about it\r\nlater!).\r\nI will dissect the LinkedIn phishlet for the purpose of this short guide:\r\nname: 'linkedin'\r\nauthor: '@mrgretzky'\r\nmin_ver: '2.0.0'\r\nproxy_hosts:\r\n - {\r\n phish_sub: 'www',\r\n orig_sub: 'www',\r\ndomain: 'linkedin.com',\r\nsession: true,\r\nis_landing: true\r\n}\r\nsub_filters:\r\n - {\r\n hostname: 'www.linkedin.com',\r\nsub: 'www',\r\ndomain: 'linkedin.com',\r\nsearch: 'action=\"https://{hostname}',\r\nreplace: 'action=\"https://{hostname}',\r\nmimes: ['text/html', 'application/json']\r\n}\r\n - {\r\n hostname: 'www.linkedin.com',\r\nsub: 'www',\r\ndomain: 'linkedin.com',\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 12 of 17\n\nsearch: 'href=\"https://{hostname}',\r\nreplace: 'href=\"https://{hostname}',\r\nmimes: ['text/html', 'application/json']\r\n}\r\n - {\r\n hostname: 'www.linkedin.com',\r\nsub: 'www',\r\ndomain: 'linkedin.com',\r\nsearch: '//{hostname}/nhome/',\r\nreplace: '//{hostname}/nhome/',\r\nmimes: ['text/html', 'application/json']\r\n}\r\nauth_tokens:\r\n - domain: 'www.linkedin.com'\r\n keys: ['li_at']\r\nuser_regex:\r\n key: 'session_key'\r\n re: '(.*)'\r\npass_regex:\r\n key: 'session_password'\r\n re: '(.*)'\r\nlanding_path:\r\n - '/uas/login'\r\nFirst things first. I advise you to get familiar with YAML syntax to avoid any errors when editing or creating your\r\nown phishlets.\r\nStarting off with simple and rather self-explanatory variables. name is the name of the phishlet, which would\r\nusually be the name of the phished website. author is where you can do some self promotion - this will be\r\nvisible in Evilginx's UI when the phishlet is loaded. version is currently not supported, but will be very likely\r\nused when phishlet format changes in future releases of Evilginx, to provide some way of checking phishlet's\r\ncompatibility with current tool's version.\r\nFollowing that, we have proxy_hosts . This array holds an array of sub-domains that Evilginx will manage. This\r\nprovides an array of all hostnames for which you want to intercept the transmission and gives you the capability to\r\nmake on-the-fly packet modifications.\r\nphish_sub : subdomain name that will be prefixed in the phishlet's hostname. I advise to leave it the same\r\nas the original subdomain name, due to issues that may arise later when doing string replacements properly,\r\nas it often requires additional work to support custom subdomain names.\r\norig_sub : the original subdomain name as used on the legitimate website.\r\ndomain : website's domain that we are targeting.\r\nsession : set this to true ONLY for subdomains that will return authentication cookies. This indicates\r\nwhich subdomain Evilginx should recognize as the one that will initiate the creation of Evilginx session\r\nand sets Evilginx session cookie for the domain name of this entry.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 13 of 17\n\nis_landing : set this to true if you want this subdomain to be used in generation of phishing URLs\r\nlater.\r\nIn the LinkedIn example, we only have one subdomain that we need to support, which is www . The phishing\r\nhostname for this subdomain will then be: www.totally.not.fake.linkedin.our-phishing-domain.com .\r\nNext are sub_filters , which tell Evilginx all about string substitution magics.\r\nhostname : original hostname of the website, for which the substitution will take place.\r\nsub : subdomain name from the original hostname. This is will be only used as a helper string in\r\nsubstitutions that I will explain below.\r\ndomain : domain name of the original hostname. Same as sub - used as a helper string in substitutions.\r\nsearch : the regular expression of what to search for in HTTP packet's body. You can use some variables\r\nin {...} that Evilginx will prefill for you. I listed all supported variables below.\r\nreplace : the string that will act as a replacement for all occurrences of search regular expression\r\nmatches. {...} variables are also supported here.\r\nmimes : an array of MIME types that will only be considered before doing search and replace. Any of\r\nthese defined MIME types must show up in Content-Type header of the HTTP response, before Evilginx\r\nconsiders to do any substitutions, for that packet. Most common MIME types to use here are: text/html ,\r\napplication/json , application/javascript or text/javascript .\r\nredirect_only : use this sub_filter only if redirection URL is set in generated phishing URL ( true\r\nor false ).\r\nThe following is a list of bracket variables that you can use in search and replace parameters:\r\n{hostname} : a combination of subdomain, defined by sub parameter, and a domain, defined by\r\ndomain parameter. In search field it will be translated to the original website's hostname (e.g.\r\nwww.linkedin.com ). In the replace field, it will be translated to corresponding phishing hostname of\r\nmatching proxy_hosts entry (e.g. www.totally.not.fake.linkedin.our-phishing-domain.com ).\r\n{subdomain} : same as {hostname} but only for the subdomain.\r\n{domain} : same as {hostname} but only for the domain.\r\n{domain_regexp} : same as {domain} but translates to properly escaped regular expression string. This\r\ncan sometimes be useful when replacing anti-phishing protections in javascript, that try to verify if\r\nwindow.location contains the legitimate domain.\r\n{hostname_regexp} : same as above, but for the hostname.\r\n{subdomain_regexp} : same as above, but for the subdomain.\r\nIn the example we have:\r\n - {\r\n hostname: 'www.linkedin.com',\r\nsub: 'www',\r\ndomain: 'linkedin.com',\r\nsearch: 'action=\"https://{hostname}',\r\nreplace: 'action=\"https://{hostname}',\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 14 of 17\n\nmimes: ['text/html', 'application/json']\r\n}\r\nThis will make Evilginx search for packets with Content-Type of text/html or application/json and look\r\nfor occurrences of action=\"https://www\\.linkedin\\.com (properly escaped regexp). If found, it will replace\r\nevery occurrence with action=\"https://www.totally.not.fake.linkedin.our-phishing-domain.com .\r\nAs you can see this will replace the action URL of the login HTML form to have it point to Evilginx server, so\r\nthat the victim does not stray off the phishing path.\r\nThat was the most complicated part. Now it should be pretty straight forward.\r\nNext up are auth_tokens . This is where you define the cookies that should be captured on successful login,\r\nwhich combined together provide the full state of the website's captured session. The cookies defined here, when\r\nobtained, can later be imported to any browser (using this extension in Chrome) and allow to be immediately\r\nlogged into the victim's account, bypassing any 2FA challenges.\r\ndomain : original domain for which the cookies will be saved for.\r\nkeys : array of cookie names that should be captured.\r\nIn the example, there is only one cookie that LinkedIn uses to verify the session's state. Only li_at cookie,\r\nsaved for www.linkedin.com domain will be captured and stored.\r\nOnce Evilginx captures all of the defined cookies, it will display a message that authentication was successful and\r\nwill store them in the database.\r\nThe two following parameters are similar user_regex and pass_regex . These define the POST request keys\r\nthat should be searched for occurrences of usernames and passwords. Searching is defined by a regular expression\r\nthat is ran against the contents of the POST request's key value.\r\nkey : name of the POST request key.\r\nre : regular expression defining what data should be captured from the key's value (e.g. (.*) will\r\ncapture the whole value)\r\nLast parameter is landing_path array, which holds URL paths to login pages (usually one), of the phished\r\nwebsite.\r\nIn our example, there is /uas/login which would translate to https://www.totally.not.fake.linkedin.our-phishing-domain.com/uas/login for the generated phishing URL.\r\nHope that sheds some light on how you can create your own phishlets and should help you understand the ones\r\nthat are already shipped with Evilginx in the ./phishlets directory.\r\nFuture development\r\nI'd like to continue working on Evilginx 2 and there are some things I have in mind that I want to eventually\r\nimplement.\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 15 of 17\n\nOne of such things is serving an HTML page instead of 302 redirect for hidden phishlets. This could be a page\r\nimitating CloudFlare's \"checking your browser\" that would wait in a loop and redirect, to the phishing page, as\r\nsoon as you unhide your phishlet.\r\nAnother thing to have at some point is to have Evilginx launch as a daemon, without the UI.\r\nUpdate: You can find out about version 2.1 release here\r\nBusiness Inquiries\r\nIf you are a red teaming company interested in development of custom phishing solutions, drop me a line and I\r\nwill be happy to assist in any way I can.\r\nIf you are giving presentations on flaws of 2FA and/or promoting the use of FIDO U2F/FIDO2 devices, I'd love to\r\nhear how Evilginx can help you raise awareness.\r\nIn any case, send me an email at: kuba@breakdev.org\r\nI'll respond as soon as I can!\r\nCredits\r\nSince the release of Evilginx 1, in April last year, a lot has changed in my life for the better. I met a lot of\r\nwonderful, talented people, in front of whom I could exercise my impostor syndrome!\r\nI'd like to thank few people without whom this release would not have been possible:\r\n@evilsocket - for letting me know that Evilginx is awesome, inspiring me to learn GO and for developing so\r\nmany incredible products that I could steal borrow code from!\r\n@antisnatchor and @h0wlu - for organizing WarCon and for inviting me!\r\n@juliocesarfort and @Mario_Vilas - for organizing AlligatorCon and for being great reptiles!\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 16 of 17\n\n@x33fcon - for organizing x33fcon and letting me do all these lightning talks!\r\nVincent Yiu (@vysecurity) - for all the red tips and invitations to secret security gatherings!\r\nKevin Mitnick (@kevinmitnick) - for giving Evilginx a try and making me realize its importance!\r\n@i_bo0om - for giving me an idea to play with nginx's proxy_pass feature in his post.\r\nCristofaro Mune (@pulsoid) \u0026 Denis Laskov (@it4sec) - for spending their precious time to hear out my\r\nconcerns about releasing such tool to the public.\r\nGiuseppe \"Ohpe\" Trotta (@Giutro) - for a heads up that there may be other similar tools lurking around in the\r\ndarkness ;)\r\n#apt - everyone I met there, for sharing amazing contributions.\r\n**Thank you!**\r\nThat's it! Thanks for being able to read this overly long post!\r\nEnjoy the tool and I'm waiting for your feedback!\r\n[\u003e\u003e Follow me on Twitter \u003c\u003c](https://twitter.com/mrgretzky)\r\n[\u003e\u003e Download Evilginx 2 from GitHub \u003c\u003c](https://github.com/kgretzky/evilginx2)\r\nSource: https://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nhttps://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/\r\nPage 17 of 17",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/"
	],
	"report_names": [
		"evilginx-2-next-generation-of-phishing-2fa-tokens"
	],
	"threat_actors": [
		{
			"id": "1a76ed30-4daf-4817-98ae-87c667364464",
			"created_at": "2022-10-25T16:47:55.891029Z",
			"updated_at": "2026-04-29T06:58:57.509467Z",
			"deleted_at": null,
			"main_name": "IRON LIBERTY",
			"aliases": [
				"ALLANITE ",
				"ATK6 ",
				"BROMINE ",
				"CASTLE ",
				"Crouching Yeti ",
				"DYMALLOY ",
				"Dragonfly ",
				"Energetic Bear / Berserk Bear ",
				"Ghost Blizzard ",
				"TEMP.Isotope ",
				"TG-4192 "
			],
			"source_name": "Secureworks:IRON LIBERTY",
			"tools": [
				"ClientX",
				"Ddex Loader",
				"Havex",
				"Karagany",
				"Loek",
				"MCMD",
				"Sysmain",
				"xfrost"
			],
			"source_id": "Secureworks",
			"reports": null
		}
	],
	"ts_created_at": 1777429242,
	"ts_updated_at": 1777450891,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/1428b84816e7ed5659ef20099e3bc9bfec29f139.pdf",
		"text": "https://archive.orkl.eu/1428b84816e7ed5659ef20099e3bc9bfec29f139.txt",
		"img": "https://archive.orkl.eu/1428b84816e7ed5659ef20099e3bc9bfec29f139.jpg"
	}
}