start	end	text
0	5180	Welcome to my talk, broadcasting from my quarantine bunker to yours.
5260	9940	My talk is Yippee-ki-yay MFA-er, bypassing multi-factor authentication with real-time
9940	12520	replay session instantiation attacks.
13600	15960	So before we get started, I'll go ahead and introduce myself.
15960	17220	My name is Hutch.
17220	20460	I am the consulting services practice lead at a company called Set Solutions.
20460	26940	I lead our government's risk and compliance, cyber incident response, threat hunting,
26940	29520	penetration testing, and red teaming operations at the company.
29520	33400	I have a master's in information systems and multiple different certifications on both
33400	35480	the blue and red team side.
35620	41100	I got into information security in the United States Air Force, did many years of consulting,
41100	45400	went in industry for about three years into the financial sector, and now back at the
45400	46580	consulting game.
47160	51900	Aside from my hacktivity interests, I do enjoy spending time with my family.
51900	56280	I enjoy country life and getting away from the big city, algorithmic trading, and last
56280	58300	but not least, street tacos.
62060	65560	So when I got started in penetration testing and red teaming, I remember that it was fairly
65560	70380	easy to breach the perimeter and gain unauthorized access to an organization's network using
70380	72740	usually one of two different attacks.
72740	78160	One was password spray attacks, where we would take a large number of different potential
78160	85840	usernames and we would iterate through those usernames and attempt a common guessable password.
85840	92040	And we would usually do this multiple times every few hours in order to prevent any user
92040	96480	accounts from being locked out, but still attempting thousands of different password
96480	98140	attempts every hour.
98880	102900	The other attack that we would commonly use would be credential harvesting attacks, where
102900	108840	we would send a phishing email to our different targets, and we would set up a fake evil twin
108840	111640	replica site of their login portal.
111640	117200	We would use that site to harvest their usernames and passwords, and then we would subsequently
117200	122580	use those compromised credentials to log into the actual site and gain remote access to
122580	123920	those networks.
125540	132080	So the security industry's response to these types of attacks was multi-factor authentication.
132400	136580	And by multi-factor authentication, the common understanding is that that's any combination
136580	140220	of at least two of the following authentication factors.
140220	142600	Something you know, such as a password.
142600	146480	Something you have, such as a mobile device or a hardware token.
146480	149100	Or something you are, such as biometrics.
149380	155160	So the thinking was that even if an attacker was to gain usernames and passwords through
155160	160240	credential harvesting attacks, or even if they were to perform password sprays against
160240	166560	an external service, they would not be able to gain access to the network because there
166560	169520	would still be that second factor standing in their way.
172020	178880	So now things become a lot harder for red teamers these days because they can no longer
178880	183680	easily perform those basic password sprays or those credential harvesting attacks in
183680	187120	order to immediately gain access to a corporate network.
187120	193980	Multi-factor authentication stands in the way and is better securing remote access services.
195780	199260	Fortunately, not all hope is lost for the red team.
199260	203520	When it comes to multi-factor authentication implementation, the right way is also the
203520	204260	hard way.
204260	211680	And what I mean by the right way is FIDO compliant UTF or universal second factor authentication.
212180	220000	And this is a legitimate form of something you have because the hardware device that
220000	226180	you use for UTF authentication does an actual cryptographic authentication sequence within
226180	232540	the same authentication sequence that you are performing to access the remote service.
233520	240300	Unfortunately, the overhead involved in supporting a UTF program at an enterprise level is extremely
240300	242880	difficult for most organizations to achieve.
242880	248400	So the reality is most organizations are doing multi-factor authentication the wrong way.
248400	252620	And the two most common types of multi-factor authentication that we're seeing for remote
252620	258080	access services are either one-time pass or push-based notifications.
258220	262480	And the reason that I say that this is the wrong way is because in reality, if you look
262480	268020	at the way that these two different authentication sequences are performed, it's not actual multi-factor
268020	268900	authentication.
268920	272720	You have the factor of something that you know, which is the username and password.
273340	278000	And the assumption is with these two types of authentication that the second factor is
278000	278900	something that you have.
278900	280360	But in reality, it's not.
280360	285600	Because with the one-time pass, while you do have possession of the phone, the phone
285600	288600	is not the thing that's actually authenticating to the service.
288680	293780	Instead, you look at that one-time password that's good for, say, 30 seconds.
293780	298900	And within that 30 seconds, that becomes something you know, and then you supply to the access
298900	301900	portal in the same way that you would supply your username and password.
302080	307420	And so it becomes subject to the same types of attacks that those username and passwords
307420	307720	are.
307720	309920	Specifically, they are replayable.
310380	316420	And the other type of multi-factor authentication, which is push notifications, actually doesn't
316420	322400	even operate within the same sequence as the original authentication sequence to access
322400	323520	that service.
323520	327300	Instead, it's done completely out of band, and your phone just receives a notification.
327300	330060	So it makes it very easy to bypass as well.
330740	336460	So because most organizations are using one-time pass or push-based notifications, this makes
336460	343300	it very easy for the red team to still bypass these remote access services and gain access.
343580	349560	So for an example to demonstrate the types of attacks that we're discussing, let's consider
349860	353500	a scenario of a life and a guy of a typical white-collar office worker.
353500	357340	For the sake of conversation, we will call this office worker Dwight Schrute.
357560	362500	And Dwight, like most white-collar workers, occasionally does work from home, and when
362500	368240	he does, he has to access his corporate remote access service by using his username and password
368240	372480	to access corporate resources like email, file shares, or VPN.
373920	379820	Unfortunately, for Dwight, there are bad people in this world that seek to do harm to business
379820	381020	organizations.
381280	386680	So let's suppose, hypothetically, that we have a hardened cyber criminal that has sent
386680	391680	an email to our office worker, and this email indicates that Dunder Mifflin is making an
391680	396660	update on its servers and that it needs the employee to log in in order to ensure that
396660	398760	their account is migrated properly.
398960	404140	Because this email looks like legitimate email, Dwight Schrute then clicks the link and browses
404140	411120	to what is actually an evil twin clone server hosted by the hardened cyber criminal.
412180	416840	And because this server looks identical to the original server that Dwight is accustomed
416840	420100	to log into, he then supplies its credentials.
421100	427360	So those credentials are then forwarded to the attacker, and the attacker is able to
427360	431280	use those to log in to the legitimate remote access service.
433700	437720	And so, unfortunately, without multi-factor authentication, this leaves our employees
437720	438700	vulnerable.
439580	446020	This gets the attention of upper-level management, who then decides to call in the IT department
446020	449100	to implement multi-factor authentication.
449100	453400	And now, when Dwight logs in to his remote access portal, he doesn't just have to supply
453580	456640	a username and password, but he also has to supply a token passcode.
458560	463000	So multi-factor authentication saves the day, the fortress is impenetrable, and all of the
463000	464440	hackers have given up, right?
464740	465780	Not exactly.
466360	470480	So now let's talk about how this attack can be performed in order to bypass that multi-factor
470480	471300	authentication.
471600	475700	So, similarly, we have our white-collar worker, the attacker that sends the email.
476110	483000	The email looks exactly the same, and the victim then clicks the update account link,
486130	495490	accesses the site, and, similar to before, enters his credentials, and this time to include
495490	497990	his multi-factor authentication token.
501400	506280	So then, upon logging in to the malicious evil twin site, instead of sending those credentials
506280	513700	to the cyber criminal, the site replays them in real time while that one-time pass multi-factor
513700	516700	authentication token is still valid to the actual server.
516700	523180	This establishes a legitimate login session with the actual server, and the session token
523180	525960	is then forwarded back to the attacker.
526140	532060	The attacker is then able to use that session token in his browser in order to assume the
532060	538520	compromised session, and thereby gain remote access to the legitimate remote access server.
540980	543140	So, now let's look through a couple demonstrations.
543140	547760	First, we're going to look through a way that we can use this type of attack to defeat multi-factor
547760	549820	authentication on a common web service.
550000	554600	And then we're going to look at a more unique scenario where we can use the same methodology in
554600	560400	order to defeat multi-factor authentication using a binary remote access client.
563910	567840	So, for the first scenario where we are attempting to bypass multi-factor authentication on a web
567840	573720	service, the stack that we're going to use is Flask as our micro framework for our web service.
573720	580200	We are going to use Apache to independently host the copied or replicated content from the
580200	582260	legitimate remote access server.
582260	589420	And then we are going to be using Selenium in order to emulate and execute browser operations
589420	594700	that will allow us to replay those credentials and execute a login in real time.
597420	604680	For this demo, I have used a Flask one-time pass multi-factor authentication proof of concept that
604680	610200	was published by Miguel Grinberg, who does some fantastic Python and Flask stuff.
610200	612300	And so, definitely worth checking out.
612320	619460	But fortunately for us, it makes a convenient option to test different attacks on multi-factor
619460	623460	authentication without having to do a full deployment ourselves.
623460	629340	So, you can essentially just git clone this repository, run it through Python, and you will have a
629340	633860	one-time pass multi-factor authentication portal that you can perform testing on.
633860	644110	Of course, we did some slight cosmetic changes in order to fit with the theme.
644110	651870	So, first we're going to look at how we can use Python and Selenium in order to execute real-time
651870	656050	logins to the actual multi-factor authentication remote access service.
658440	661520	So, the first thing that we're going to need to do in order to achieve the multi-factor
661520	665560	authentication bypass is we are going to need to be able to programmatically
665560	668980	log in to the actual multi-factor authentication service.
668980	670520	So, we're going to do that with Python.
670680	676840	And we're going to start with from Selenium import WebDriver.
678220	680940	Then we are going to create an instance of WebDriver.
680940	684760	So, driver equals WebDriver.firefox.
685980	690020	And you should see a browser open in the graphical interface.
692510	695230	And next, we're going to browse to the actual site.
695230	699190	So, we will do driver.get and then the URL.
707220	711820	It's worth noting that for this demo, I did modify my Etsy hosts file,
711820	713760	and I do not actually own this domain.
713760	718980	So, then what we want to do is we want to enter text values in each of these
718980	721540	different parameters, username, password, and token.
722000	724660	So, in order to do this, we're going to inspect the element.
725540	731160	And here, you'll see the Firefox inspector, which shows you the HTML element and also
731160	734120	shows you the ID for the element is username.
734160	740440	So, in order to interact with it, we will just do driver.findElementById
740440	742860	and then pass it that value, username.
743480	748860	And then we want to send it the keys of the username we want to send.
748860	750020	So, I'll put Hutch.
750320	754120	And as you can see, it programmatically populates that field.
754120	757300	We can then do the same thing for password by inspecting it.
757520	762180	And here, we can see that the ID value for password is also password.
762180	776880	So, we'll do driver.findElementById password, then send keys, and my password.
780260	782620	And as you can see, it then populates the password field.
782620	784440	And finally, for token, we can do the same thing.
784440	785580	Inspect element.
785720	787520	The ID is token.
787940	792320	So, we can do the same thing, but this time, we'll make our token value
792320	796740	1, 2, 3, 4, 5, 6, and the ID is token.
799700	802680	So, now that all the fields are populated, we just need to click the login button.
802680	806380	So, we just right-click this and inspect element.
806380	811740	And here, we can see that the ID value for that login button is the word submit.
811840	820260	So, all we have to do is driver.findElementById submit.
821220	825180	And then this time, instead of send keys, we'll use dot click.
828820	832780	And as you can see, by the error returned, invalid username, password, or token,
832780	837540	we were able to programmatically make a login attempt to the actual site.
838040	842540	So, now that we've created our Selenium login script, we also need to create a replica
842540	846560	of the site that we are attempting to gain remote access to.
846560	850280	So, in order to make the replica website, we'll start by opening up a web browser.
850280	854060	And then we will browse to the page that we want to clone.
861760	864180	And then to save a recursive copy of the page,
864180	869220	all you have to do is go over to the menu bar over here and do save page as.
870920	874960	And this will save a full recursive copy of the website.
874960	880080	If you want to drop it directly into your web root, browse to var www.html.
880140	884920	And then even better yet, if you want it to be the web root index file,
884920	888340	then you can just name this file as index.html.
889180	890680	Then save.
893220	896060	And then next, you'll want to go to that directory.
896060	898140	So, var www.html.
898400	901960	You'll see that we've now saved the index.html.
901960	908620	And then all the supporting files to include JavaScript and CSS files in this index files page.
908620	913420	And actually, what's helpful about this is it actually rewrites all of the links in the
913420	918160	HTML content to these different paths dynamically.
920410	925290	So, essentially, the only thing that we need to do is chmod 755.
926050	927510	Make this recursive.
927510	930010	Dash r 755 everything.
931310	935550	And then we can open up a web browser.
939350	942210	And make sure that the Apache service is on.
942210	944070	So, apache2 start.
944070	948590	And then we access 127.0.0.1.
950050	950750	And there you have it.
950750	954410	You now are hosting a cloned website that looks identical to the original login.
954410	958890	Now that we have the target website cloned, and we also have our Selenium login scripts,
958890	963230	the next step is to create a Flask authentication handler that will receive
963230	966590	any authentication attempts to our evil clone,
966590	972010	and then connect those to the Selenium logins to replay those credentials in real time.
975370	979770	So, I have a proof of concept that I have published on GitHub.
979770	981450	I have the link available here.
982390	986690	In order to test this out, what you're going to want to do is just git clone the repository.
986970	992710	If you want to test this for yourself, extract the app from the OTP target app.zip file.
993030	995610	And then you can run that via Python.
995930	1000290	You'll need to register a victim user with an OTP client,
1000450	1004530	a one-time pass client, at the slash register URL.
1004870	1009770	And then you can use this proof of concept to host the malicious clone
1009770	1015810	that will then target and bypass the multi-factor authentication on that target app.
1015810	1018110	So real quick, let's just step through the code here.
1018110	1021670	First, we do our imports JSON for parsing.
1021670	1024750	We've got a few Selenium functions that are imported.
1024790	1028250	And then we also have our Flask functions that are imported.
1030790	1035630	We you'll also need to update the login URL to wherever you're hosting the target app
1035630	1037070	that you extracted.
1037110	1040410	In this case, I'm using a modified version of Etsy hosts
1040410	1044270	to have it hosted at dundermifflin.com slash login.
1044610	1046210	And we have a couple different functions.
1046210	1047570	The first is create browser.
1047570	1051130	So this is very similar to what we did previously in step one.
1051130	1053850	However, the one difference is that we've changed it to headless
1053850	1058470	so that it isn't visibly apparent within the GUI.
1059590	1063830	Then we have a login function that receives the username, password, and token.
1063830	1068860	And it performs the same Selenium login that we coded in step one of the process.
1069230	1073670	And then finally, the last part is the Flask component.
1073670	1076390	And this is actually the Flask receiver.
1076390	1081750	We have a intent mapped to the slash harvester location.
1081750	1087990	And this will receive from a post method request the username, password, and token.
1087990	1089410	That is sent.
1089410	1092710	It will print those to the user.
1092710	1096210	And then it will also use that login function.
1097730	1101930	Pass it those credentials in real time and execute the real time relay.
1101930	1104190	It will then print the cookies back to us.
1104190	1110290	And we can then use these cookies as the attacker to hijack the compromised session.
1110430	1116530	So finally, we also have the malicious Flask handler
1116530	1118290	hosted on a separate port.
1118290	1120310	In this case, I have it hosted on 8080.
1120310	1126930	But a separate port than the content that we're hosting for the cloned Evil Twin replica site.
1126930	1129250	And the reason that we have these hosted on two different ports
1129250	1134890	is because of the fact that we are running the clone content through Apache.
1134890	1141790	And then we are hosting the handler through a separate service, which is used by Flask.
1141790	1145690	Now, you could actually do this all within the Flask app by just
1145690	1153990	having the HTML, CSS, and JavaScript content that you cloned within static files in the Flask app.
1153990	1156550	Unfortunately, this becomes a lot more complicated
1156550	1159710	than just using the relative links that exist whenever you save it.
1159710	1162670	Because you then have to update all of the different links
1162670	1165590	and map them to the static directories within Flask.
1165590	1168990	So it's actually much easier to just host it on two separate ports.
1170910	1175810	So now let's go ahead and look at how we can git clone this bypass script
1175810	1178230	and execute it within our own environment.
1178730	1182610	Okay, so now we are going to clone the repository and launch the bypass script.
1182610	1185830	So we'll go to the GitHub repository.
1186730	1198890	And then we will copy the clone path and do git clone paste selection.
1200450	1201610	All right.
1201610	1204500	And then we now have our cloned directory.
1205070	1209350	And we can do python3 bypass.
1210170	1212950	And it is now running on port 8080.
1214450	1219250	Okay, so now we have our cloned web app content for the target web app.
1219270	1221190	And we are hosting that on Apache.
1221190	1224630	We also have our harvester that will gather credentials.
1224630	1227110	And that's running on Flask on a separate port.
1227110	1231490	What we need to do is now update the cloned content
1231490	1235270	to where whenever a post is submitted with that form,
1235270	1239490	it then submits it to our Flask harvester on port 8080.
1242570	1245870	Okay, so we are going to go into our web root directory
1245870	1248490	where we previously cloned the web content.
1248490	1253210	So var www.html, then list the contents.
1253430	1258470	And again, we had written the HTML file to index.html.
1258470	1262790	All of the recursive supporting files, such as CSS, JavaScript,
1263410	1266850	are all here within the index files directory.
1267330	1269530	And all the content is automatically mapped.
1270170	1273050	So the only thing that we need to change in this Apache directory
1273050	1276350	is where the form will post to.
1276350	1277850	So we can use any text editor.
1277850	1280810	I'll use nano, then index.html.
1280810	1283710	And then I'll use ctrl w for the find function
1283710	1285610	and search for the word action.
1286250	1292250	Now action in an HTML form tag defines where the post will
1292970	1295130	or where the form will be submitted to.
1295130	1296850	And here, when it's empty,
1296850	1300110	it actually just submits it to the same directory
1300110	1303570	or the same URL path as it's currently on.
1303570	1305430	So what we need to do is update this to say
1305430	1309890	http colon backslash backslash dunder mif.
1309890	1314750	And I used a one for the L for the malicious app.
1314750	1320370	So dunder miflin looks almost identical dot com slash harvester.
1320830	1323410	And you also need to specify the port.
1323410	1325550	So we're hosting it on port 8080.
1325650	1331350	So it would be HTTP, your malicious app that you're hosting through Flask.
1331590	1334690	And then the port that you're hosting it on.
1334690	1336730	By default, I have it set to 8080.
1336770	1342350	And then the path of the Flask receiver, which is slash harvester.
1342690	1344650	Otherwise, there's nothing else that we need to change.
1344650	1348590	We can do control X and then Y to save the content.
1351590	1353850	So now whenever an authentication form is submitted
1353850	1358330	to your evil twin copied content,
1358330	1362010	it will submit the authentication request to your Flask handler
1362010	1365230	in order to be able to be replayed in real time.
1365970	1367470	Okay, so we now have everything set up.
1367470	1371010	The only thing left to do is use our social engineering techniques,
1371010	1376050	most likely phishing, to entice our victim to access the fake site
1376050	1377970	and convince them that it's the real site.
1377970	1380290	And then when they enter their credentials,
1380290	1383250	all should work as planned and we should be able to hijack their session.
1384950	1387150	So now it's time to exploit our target.
1387150	1388770	You will look at two different screens here.
1388770	1392490	First, we have the victim that has accessed
1392490	1398050	or been enticed to access our fake dundermifflin.com login site.
1398050	1402710	And then, as you recall, we have our Apache service hosting the clone content.
1402710	1410590	And we also have the Flask bypass that is running our harvester on port 8080.
1410590	1414390	And as you can see, the attacker currently is not logged in,
1414390	1418490	if we refresh this page, to the actual dundermifflin site.
1443400	1445140	Okay, so once the hijack is completed,
1445140	1450540	it will actually send the initial user back to the actual dundermifflin.com login page
1450540	1453860	so they don't suspect that anything has gone wrong.
1453860	1458880	However, on our attacking side, we can now see that we have received the username.
1458900	1460740	We have received the password.
1460740	1462640	We have intercepted the token.
1462640	1465640	We also replayed the token in real time.
1465640	1470020	And we're able to acquire the session token for that user.
1470020	1474220	So once again, we are not currently logged into the actual site as the attacker.
1474220	1477000	And we are going to attempt to hijack that user session.
1477000	1480640	So what we're going to do is we're going to open a cookie manager.
1480640	1483160	And there's a bunch of different plugins that you can use for this.
1483160	1487100	And we're going to manage cookies for dundermifflin.
1487420	1491540	And then the only thing that we have to do is we have to modify this session token
1491540	1495740	so that it has the value of the compromised session.
1495740	1497800	So we will copy this.
1501450	1507790	And then drop this into the value of the previous session token.
1507890	1510570	And then we save the contents of the cookie.
1510570	1513390	And we go back to dundermifflin.com, the actual site.
1513390	1514010	Click enter.
1514010	1517890	And we have now successfully bypassed the multi-factor authentication
1517890	1521830	without having to enter the username, password, or token.
1523030	1527450	Undoubtedly, at this point, somebody is thinking that this sounds an awful lot like EvilGinX.
1527450	1530490	And admittedly, the first proof of concept that we discussed
1530490	1533550	is something that you could accomplish with EvilGinX.
1533670	1538590	For any that aren't familiar, EvilGinX is a multi-factor authentication bypass toolkit
1539210	1543990	that allows you to perform very similar attacks to the ones that we just discussed.
1544010	1548550	With the only difference being that instead of operating at the application layer,
1548550	1554370	it operates as an HTTP proxy relaying communication for the authentication sequence
1554370	1558350	and then also thereby intercepting the session tokens
1558350	1565470	and providing those back to the attacker in order to allow them to assume the compromised sessions.
1566390	1571330	But there's an inherent problem with relying on ScriptKitty toolkits and red teaming.
1571330	1577430	For one, if the developers of the toolkit decides to stop supporting it and it no longer works,
1577430	1578950	then you're dead in the water.
1578950	1582630	Similarly, if something breaks in that toolkit and you don't understand
1582630	1585370	the underlying components well enough to be able to troubleshoot it,
1585370	1587910	there's also nothing else that you can do.
1588150	1593710	But most importantly, anytime that you're relying on a cookie cutter toolkit,
1593710	1600230	it will likely address the bulk number of instances where you need to use that exploit.
1600230	1605090	But the reality is because you don't have control over all of the integral components
1605090	1609210	of that exploit, it makes it very difficult for you to be able to
1609210	1613390	tailor those attacks to unique and unconventional environments.
1615670	1622210	So EvilGenX is an HTTP proxy, which means it can only operate within the context of
1623470	1627650	relaying multi-factor authentication sequences over a web service.
1627650	1633370	However, a lot of times these days where we're entering our multi-factor authentication credentials
1633370	1635370	are not web services at all.
1635370	1640550	But instead, they are login clients that exist on your local operating system,
1640550	1643570	such as operating system level multi-factor authentication,
1643570	1646490	VPN clients, or remote access clients.
1648830	1653670	So for our second proof of concept, we're going to look at just such a scenario
1653670	1656650	where we would want to take the credentials that were compromised
1656650	1660550	via our phishing web service and be able to relay those
1660550	1665070	to a local login client that requires multi-factor authentication.
1665610	1669350	So our attack stack in this scenario is slightly different.
1669350	1673370	We are still using Flask to handle the authentication requests
1673370	1677570	and map those to the replay functions.
1677570	1682730	And we're still using Apache in order to host the login content.
1682730	1686930	The only real difference is that instead of using Selenium to hook into the browser,
1686930	1691030	we're instead using something called Auto-IT to hook into the operating system
1691030	1693890	in order to control operating system functions,
1693890	1697170	such as mouse movement or entering text or clicking,
1697570	1703990	and thereby performing authentication sequences within local authentication clients.
1704750	1709730	So first, let's look at how we can use Auto-IT in order to perform
1709730	1716230	operating system login functions that we could potentially use in a real-time replay attack.
1716530	1719270	So in order to perform a real-time replay attack
1719270	1723030	that includes the one-time pass-based multi-factor authentication
1723570	1727230	with a login client as opposed to a login web service,
1727230	1731510	we need to be able to programmatically interact with the underlying operating system
1731510	1733370	instead of just the web browser.
1733410	1737190	So in order to do that, we're going to use a different Python library this time.
1737190	1739690	So instead of Selenium, we're going to use Auto-IT.
1739730	1744750	And in order to import that, we're going to do import and then pyAutoGUI.
1747310	1749710	And a few different functions that we need to be aware of.
1749710	1752550	There is the moveTo function, which allows us to specify
1753110	1757290	where it will move the mouse on the screen.
1757410	1761190	There is the typeWrite function, which allows us to type text.
1761190	1764670	And then there's a click function that allows us to click the mouse button.
1764870	1767970	And one other function that's worth mentioning is the position function,
1767970	1773770	which tells you what the coordinates are for the mouse at any given time.
1773910	1776630	So we will demonstrate that real quick.
1777810	1779490	pyAutoGUI.position.
1780150	1786630	And we can see that the X and Y coordinates for the current cursor location is 674,334.
1786630	1791530	Now, what we want to do is determine what the coordinates are of the cursor
1791530	1794030	whenever it's hovering over the username field
1794030	1797510	so that we can tell the mouse to go over to the username field to click
1797510	1799130	and then to enter text.
1799430	1803930	So what we'll do is we will use the same command, the same function,
1803930	1805790	but this time before executing it,
1805790	1808750	we will hover the mouse over the username field and press enter.
1809150	1811690	And now we know that the coordinates of the mouse
1811690	1815510	hovering over the username field is 227,369.
1815510	1818570	Now, with that knowledge, we can easily create a quick function
1818570	1823890	that allows us to enter text into that particular location.
1823890	1826270	So to do that, we'll create a function with def
1826270	1829250	and we'll call this supply username
1830330	1833450	and then we'll pass it a username value.
1834270	1838330	So first we'll do py autogui.moveTo
1838890	1845110	and then we'll supply it those X and Y values of 227,369.
1846190	1849450	Then the next thing that we want to do after we hover it over the usernames,
1849450	1853890	we want it to click in that field to activate that particular input field.
1853890	1859350	So for that, we'll do py autogui.click.
1859910	1863450	And finally, now that the field is clicked and activated,
1863450	1865790	we want to supply it the text that we provided.
1865790	1869530	So we'll do py autogui.typeWrite
1870210	1873490	and then the username that's supplied.
1875050	1877970	Okay, so now that we've created that very basic function,
1877970	1880590	we can execute that function with a given username.
1880590	1888610	We'll do supply username and then we'll try the username Hutch and press enter.
1888910	1891850	And as you can see, it automatically moves the mouse over,
1891850	1894530	activates that field and types in the word Hutch.
1894530	1898390	Now we can use all of these different functions of moving the mouse around,
1898390	1902010	clicking and entering text in order to fully populate
1902010	1906670	the different parameters within the multi-factor authentication sequence
1906670	1911030	in order to relay communications from a malicious web app
1911030	1917510	that's phishing credentials into a client in order to gain access via the client login.
1918070	1925150	So now that we know that we can interact with and authenticate to a local login client
1925150	1930470	using AutoIT, we want to use a similar process to what we did before
1930470	1933730	where we create a phishing web service.
1933730	1939650	But this time we modify the authentication replay sequence
1939650	1943650	so that rather than replaying it to a separate web service,
1943650	1948670	we simply use AutoIT in order to replay those credentials real-time
1948670	1952170	to include the multi-factor authentication token to the login client
1952170	1954470	in order to gain remote access.
1955910	1960210	Now we have slightly modified the previous proof of concept
1960210	1963310	in order to accomplish precisely this.
1963730	1968370	So let's quickly look at what we've done here that is different.
1968990	1973670	This time, instead of importing Selenium, we're using PyAuto GUI.
1974330	1976870	We do have a few additional parameters.
1976870	1982550	We are doing a two-step multi-factor authentication sequence process
1982550	1987770	where in the first step, the username and the multi-factor authentication token is supplied.
1987770	1990670	And then in the second step, the password is supplied.
1990670	1993330	So because of this, we have two different redirects.
1993330	1998830	The first redirect from the initial authentication sequence step.
1998830	2004450	And then the other redirect URL is where the victim will be redirected
2004450	2011610	after they complete the entire malicious multi-factor authentication sequence.
2013450	2017610	Now, in order for this to be successful, we do have to define the specific coordinates
2017610	2025970	of where different login components and buttons are within the GUI login interface.
2025970	2029890	And again, we accomplish this the same way as what we just looked at.
2030810	2038210	We have a function for validating the token using the username and token value.
2038210	2041710	And this is accomplished, once again, by using Auto-IT
2041710	2046550	and just moving the mouse to the location of specific fields,
2046550	2050820	clicking on those fields to activate them, supplying the text, and then moving on.
2051630	2054830	The second step in the process is essentially doing the same thing,
2054830	2057750	but this time supplying the user password.
2059630	2068850	And then we have a Flask app that has two different URL receivers or routes at this point.
2068850	2072750	The first is the initial harvester one that represents that first step in the process
2072750	2076730	of the username and the multi-factor authentication token.
2078690	2084830	And as you can see, that then invokes the validate token function from above.
2084830	2091690	And then the second is the second step in that multi-factor authentication sequence,
2091690	2094670	which is validating the password for that particular user.
2094670	2099810	And again, you see that we then invoke the validate password function that we created above.
2099810	2105770	And similar to before, we are executing this or hosting this on a port that is different
2105770	2111190	from the one that we are hosting the malicious replica web service on.
2113010	2116430	So a few different things to take note of here on this proof concept.
2116430	2120870	On the right side here, we have the malicious app that we are using to
2120870	2125010	phish the victim's credentials to include their multi-factor authentication token.
2125010	2130550	On the left side, we have the actual client that we would use in order to
2130550	2134350	enter the intercepted username, passcode, and password.
2134550	2141310	And here at the bottom left corner, you can see the bypass code running with client bypass.py.
2141310	2144050	So we're going to run that once again running on port 8080.
2144050	2147150	And then we're going to simulate the victim entering their credentials.
2160410	2167210	And here you can see that using auto-IT, it was able to successfully migrate the client on our
2167210	2174110	desktop. And then we're going to simulate the user entering the second component of
2174110	2176310	the authentication, which is the password.
2177810	2179910	And then they click login.
2180010	2183510	And similarly, credentials are intercepted, replayed.
2183870	2188290	The victim is redirected to a VMware Horizon client website.
2189370	2192190	The password is disclosed at the bottom left corner.
2192190	2197970	And it successfully loads our desktop and allows us to bypass multi-factor authentication.
2199270	2203750	So we've now established that it is possible to bypass one-time pass-based multi-factor
2203750	2206710	authentication for both web and non-web clients.
2206710	2209790	But what about push-based multi-factor authentication?
2209790	2212910	For anybody that's not familiar, push-based multi-factor authentication
2213430	2218010	is a second factor that's initiated by the server side instead of the client side.
2218010	2223290	So you enter your username and password, just as you would with any type of authentication
2223290	2227910	sequence. And then for the second factor, instead of sending a temporary password that
2227910	2232550	you retrieve from your mobile device to the server, the server instead sends a request
2232550	2235870	to an app that you have loaded onto your device.
2235870	2241430	And that request indicates that an authentication attempt was performed and then asks whether
2241430	2245510	or not you approve or authorize that authentication attempt.
2245510	2250450	Now, on the surface, this may seem like the more secure solution because there is no temporary
2250450	2252470	password to be replayed.
2252610	2258930	The problem is because of the out-of-band nature of this authentication sequence, it
2258930	2260830	makes it just as easy to bypass.
2260870	2265370	So let's look at our attack sequence and look at it within the context of push-based
2265370	2266890	multi-factor authentication.
2266890	2272810	So similar to before, we have a cybercriminal that sends a phishing email to our victim.
2272810	2278390	The phishing email has a link that leads that victim to an evil twin clone server.
2278390	2282470	The victim supplies their credentials and attempts to log in to what they think is the
2282470	2284890	legitimate remote access service.
2284970	2291490	That evil twin clone site replays in real time those credentials to the legitimate remote
2291490	2292990	access service.
2293190	2299170	The remote access service sees that it has an authentication attempt, so now it sends
2299590	2302790	a push authorization to our victim.
2302810	2308010	Now again, keep in mind that our victim believes that they've just logged into the legitimate
2308010	2309490	remote access service.
2309490	2313170	So they're fully expecting that they're going to get an authentication authorization
2313170	2314090	request.
2314530	2319370	So not thinking twice about it, the victim is going to click yes, it's me and approve
2319370	2321470	this authentication attempt.
2321470	2326650	So our victim is now informed of the server that the authentication request is good and
2326650	2329290	the session is established.
2329290	2331810	Just like before, the rest is history.
2331810	2337450	We are able to use the evil twin server in the established session to harvest those session
2337450	2341810	tokens and thereby hijack the session of the victim user.
2344010	2347930	So we've now demonstrated that it's possible to bypass multi-factor authentication for
2347930	2351910	one-time pass and push-based multi-factor authentication.
2352390	2355950	So I'll close out here with just a few final parting thoughts.
2356810	2361170	If you're on the blue team, we've probably established that your multi-factor authentication
2361170	2365330	solution sucks and that you're likely not getting out of it what you want to get out
2365330	2365930	of it.
2365930	2370110	And don't feel bad because almost everybody in the industry is in that boat because everybody
2370110	2375490	is using either push-based or one-time pass-based multi-factor authentication with only a very
2375490	2380290	small percentage of organizations that have now moved to U2F.
2380290	2386850	The obvious best thing that you can do is to use U2F for prevention.
2386850	2392390	But if you can't do that at this time, then you probably need to focus more on your detection
2392390	2395410	skills and identifying these types of attacks.
2395410	2399150	And if you're looking for any other recommendations, because I don't want to spend too much time
2399150	2406430	solutioning in red team village, you can look to FidoAlliance.org, which has a lot of good
2406430	2410950	recommendations around how to effectively do multi-factor authentication.
2410970	2415510	Or you can also check out some blogs that we did and that I authored at SetSolutions
2416110	2418770	called Doing MFA the Right Way.
2421730	2425390	If you're on the red team, I encourage you to remain flexible anytime you're doing
2425390	2427890	penetration testing or red team engagements.
2427890	2431970	Remember that penetration testing is more art than audit.
2432050	2436230	And what I mean by that is that you're never going to get anywhere by going into an organization
2436230	2443230	and attempting to perform such an assessment by checking off a series of tests in a list.
2443230	2444950	You need to be flexible.
2444950	2449770	You need to familiarize yourself with the environment that you're in and then be ready
2449770	2456690	to adapt and create your own tools and solutions in order to exploit the ways that different
2456690	2459350	components are communicating within that organization.
2460030	2463530	One of the great things that I love about InfoSec is the fact that
2464370	2470910	there is so much knowledge within this field and so much potential information in so many
2470910	2473530	different areas that you can potentially specialize in.
2473530	2477210	No matter how good you get, there's always more that you can learn.
2477890	2482370	So obviously, continue to improve yourself in any way that you can.
2482370	2484490	Be creative and think outside the box.
2484670	2488570	I know that it's somewhat controversial to say this because some people will tell you
2488570	2492590	that you can be just as effective of a penetration tester without being able to code.
2492590	2497270	Learning to code is like a superpower whenever you're doing red teaming and penetration testing
2497270	2502370	because of scenarios just like this where you can adaptively and quickly prototype
2503030	2507430	exploits that are unique to the environment that you are attempting to assess.
2507730	2511330	And always kind of approach things with that mentality of picking it apart,
2511330	2514270	understanding how it works, and then putting it back together.
2515750	2519690	To the staff at DEF CON and also for the Red Team Village staff,
2519690	2521090	I really appreciate the opportunity.
2521090	2522130	This has been awesome.
2522970	2526590	Thank you for making this happen despite everything that's going on.
2528430	2532810	And to everyone else, stay happy, stay healthy, stay hacking.
2533610	2536130	This definitely has sucked, I think, for everybody.
2537110	2542690	I admittedly was somewhat disappointed to not be going to Vegas this year for DEF CON
2543230	2546130	and definitely will miss seeing all you guys out there.
2546850	2549810	But I think this is something that we can all get through together.
2549810	2553210	We'll put behind us and hopefully we'll see you guys next year.
2554610	2555910	Quick shameless plug.
2555910	2559170	Check out our podcast, Ready, Set, Secure, from Set Solutions.
2559470	2562670	Also, feel free to follow my research at sociosploit.com
2562670	2565090	or follow me on Twitter at Hackett Hutch.
2566550	2567870	And that's a wrap.
2568310	2568970	CREASE CLOSED!
