[00:00.780 --> 00:07.780] Hello, my name is Chris Nevin and I work for NCC Group. So this tool is called Carnivore, [00:07.780 --> 00:14.120] so that's a Microsoft external attack tool or assessment tool. So the cryptozoologists [00:14.120 --> 00:20.720] amongst you might know this, so that spells meat, so that's very amusing. And it's basically a tool [00:20.720 --> 00:26.680] to help pen testers find misconfigurations and vulnerabilities in Microsoft on-premises [00:27.220 --> 00:33.480] servers. So also apologies if I talk quickly, but there is quite a lot to get through. [00:35.080 --> 00:40.160] So the basic outline of the presentation. So I'm going to start with a demonstration just [00:40.160 --> 00:44.580] to show what the tool can do and then dive a bit deeper into some of the techniques [00:45.160 --> 00:52.340] and the research behind them after that. So now intro demonstration. [00:52.960 --> 00:59.360] Okay, so first a quick overview just to give you a taste of what the tool can do. So just before [00:59.360 --> 01:04.700] I kick it off, we've selected all services and we're also going to attempt to discover the [01:04.700 --> 01:11.580] internal domain information. You might notice that it's a .nev domain. Obviously that wouldn't [01:11.580 --> 01:17.900] normally be a top-level domain, but this is my training lab. So first of all, it's going to [01:20.100 --> 01:26.260] do DNS lookups for subdomains, which are normally connected with a particular service. So for [01:26.260 --> 01:31.960] example, link discover with Skype, then it verifies there's something there. So it's not just a wild [01:31.960 --> 01:38.780] card resolution. And then it also does some checks to make sure, does it also actually seem to be an [01:38.780 --> 01:47.660] exchange or a Skype server? So I've also built in some kind of bailout options. So for example, [01:47.660 --> 01:52.480] we get back a server header saying that it's Nginx. It's not even Windows. We don't need to [01:52.480 --> 02:00.220] test every possible endpoint just in case one of them is a Skype server. So yes, that's something [02:00.220 --> 02:07.340] that we do. So it also validates the username enumeration and the password spray URL separately. [02:07.720 --> 02:14.940] I'll come on to that in a little bit, but basically there are occasions where an organization might [02:14.940 --> 02:21.320] have hidden most things, but there'll be one password spray URL kind of hidden away. So we try [02:21.320 --> 02:26.860] the most obvious, and then if they don't hit, there are other kind of password spray endpoints [02:26.860 --> 02:32.980] that are possible. So yeah, so hopefully if an organization has something exposed, then we'll be [02:32.980 --> 02:40.980] able to find it to report to them. So we also log everything here, and you've got export options [02:41.640 --> 02:49.860] if you want to kind of manually export things for some reason. I'll cover Office 365 more at the end, [02:49.860 --> 02:57.600] but for this section, if Office 365 is ticked, then it will explicitly check if this has any [02:57.600 --> 03:03.340] kind of cloud presence. Even if it's not ticked, then the response to Skype for Business, for [03:03.340 --> 03:08.940] example, might come back and say, I'm hosted in the cloud, and then we'll still do the standard [03:09.460 --> 03:15.560] checks for, is it federated, and that kind of thing. And then it will add, so say we just did [03:15.560 --> 03:20.280] Skype for Business, it says it's in the cloud, it turns out it's federated, we'll get an Office 365 [03:20.280 --> 03:29.780] and an ADFS option here. So okay, so we've also got global verbosity here, so you can kind of [03:30.320 --> 03:37.900] tweak that up and down depending on what you want to see. Okay, so let me kick this off. [03:39.280 --> 03:45.540] Okay, so the other thing with this discover internal domain, then it does the fairly [03:45.540 --> 03:52.680] standard blank type one NTLM message. And you can see it's pulled back the internal domain name. [03:52.680 --> 03:58.360] So at the moment, it does that individually for each of these services. And that's because, [03:58.360 --> 04:05.080] you know, Skype might be hosted in Germany, and ADFS server, the ADFS server might be in Canada [04:05.080 --> 04:10.800] for some reason. And so when you're hitting, when you're spraying that server, then you've [04:10.800 --> 04:16.780] got the internal domain information for the particular server that you're hitting. And [04:16.780 --> 04:23.240] in fact, even on a job just last week, then these were all different. So it does happen quite [04:23.240 --> 04:29.320] frequently, I might add some kind of advanced options. So you can say, just assume they're all [04:29.320 --> 04:37.320] same. But like say, that's maybe, you know, a recipe for potential disaster. So okay, we've also [04:37.320 --> 04:42.360] got the IP addresses here. So you can obviously check those against your scope. And if you want [04:42.360 --> 04:47.740] to, you can kind of run this once, check the IP addresses against your scope, and then do the more [04:47.740 --> 04:56.760] active kind of blank NTLM one message. And so for the other thing to mention is for Skype. [04:56.760 --> 05:02.620] So link discover is the kind of auto discover service. And that actually points to the real [05:02.620 --> 05:11.580] server, which is what we want to hit. So that's why there's two kind of entries for Skype there. [05:12.620 --> 05:19.620] So we've now got Skype exchange, ADFS and RD web. So I'm going to show you a quick run through of [05:19.620 --> 05:25.400] username enumeration and password spraying, just to give you an idea. So smart enumeration, we'll [05:25.400 --> 05:32.120] leave it on the defaults. We're also going for password one, just kind of standard. So you see, [05:32.120 --> 05:38.000] there's quite a lot of usernames to try here. As it's going through, we found one of a particular [05:38.000 --> 05:44.840] format. So it's now continuing to loop through nine different formats. And you'll see that when [05:44.840 --> 05:51.240] we discover the correct format, then this will drop drastically, because then we switch to just [05:51.240 --> 05:59.320] using usernames of that format. So we've now got two of the same format. So first initial surname, [06:01.980 --> 06:06.820] and now we've got three. So you'll see that it's now selected that format of JSmith. [06:07.080 --> 06:13.000] So everything we do, oh sorry, if we left that continuing, it would just be, as you can see here, [06:13.000 --> 06:19.720] it's now less usernames, and it's just doing usernames of that format. So now I'll quickly [06:19.720 --> 06:28.520] show you a password spray as well. So I'll use that same format, JSmith. So for the password [06:28.520 --> 06:35.340] spray, that will now spray that in the kind of modern style username format. So jsmith at [06:35.340 --> 06:42.640] nevtech.nev. And we'll just try summer 2020, just to see if there happens to be a user [06:42.640 --> 06:46.260] who might have been daft enough to use that as a password. [06:48.710 --> 06:54.250] So here we go. So that's going to take a second. I'm sure we're not going to find anyone, because [06:54.250 --> 07:03.730] of course no one ever uses passwords like this. Who would possibly be that foolish? So here we go. [07:05.170 --> 07:09.590] If we give it another couple of seconds, you can see again, this is just doing that one [07:09.590 --> 07:14.830] username list. So obviously that's the same number of users total that it will be spraying as [07:14.830 --> 07:23.240] the smart enumeration was looking at. So it should be around about now. So there you go. [07:23.240 --> 07:29.100] So we've now uncovered one user with that password. We've used the RD web service, [07:29.100 --> 07:34.860] but obviously we could have sprayed that on any of these other services. And at the moment, [07:34.860 --> 07:40.340] looking at the internal domain information, we can probably assume that they're kind of [07:40.340 --> 07:49.320] be the same across all of them. Okay. So let's have a look. Let's just do one with Skype. So [07:57.540 --> 08:04.400] just to show you, you can also password spray enumerated users. So let's use that same. [08:12.180 --> 08:19.560] Okay. Okay. So for that option, then we were spraying the users in the legacy format, [08:19.560 --> 08:25.760] because those are the ones we've already enumerated. And for username enumeration, [08:25.760 --> 08:30.680] that's incredibly slow because for every invalid user, you might have to wait something like 20 [08:30.680 --> 08:36.680] or 30 seconds. When we're spraying this list of already enumerated users, then we kind of know [08:38.120 --> 08:43.600] already that they exist. And actually that's still quite fast, even when spraying in legacy format, [08:43.600 --> 08:50.220] because you're not having to wait for every invalid user. So obviously we've now got him as [08:50.220 --> 08:55.800] well. You can see we've got this access token here. So I'll quickly show you the address book. [08:55.840 --> 09:01.500] So we'll choose this user who we've already got the access token for. Again, I'll explain in more [09:01.500 --> 09:07.240] detail some of these other settings. But for now, we're just going to let this go, see what happens. [09:11.640 --> 09:16.660] I'm also going to come back to the meeting snooper later. So this is just to kind of show [09:18.320 --> 09:31.050] the address book functionality. Here we go. And so you can see now all of these other users [09:31.050 --> 09:38.730] popping up. So we get the SIP username, the email address, title, department. We can kind of tick [09:38.730 --> 09:43.710] these on and off. The default settings I've got here are basically the ones we can get relatively [09:43.710 --> 09:50.570] quickly. So if I actually expand that and choose to pull some of this other information, it can [09:50.570 --> 09:56.150] take quite a long time, especially with quite a large domain. So in this instance, we just go for [09:56.150 --> 10:03.550] the default. It's fairly quick. Obviously for my test lab, this is quite a small number of users, [10:03.550 --> 10:08.130] but there you go. You can see the general gist of what's possible with this tool. [10:08.530 --> 10:16.230] Okay, so now for some just general statistics. So first of all, I basically ran a version of this [10:16.230 --> 10:24.110] against the Alexa, well, the top 100,000 of the Alexa top a million. Of those, 11.79% [10:24.110 --> 10:30.970] were attackable at all. And so this shows that of that 11%, about 11%, [10:31.510 --> 10:37.390] so how many had each service. So obviously some could have had more than one service. [10:37.950 --> 10:44.750] This started, Carnivore started initially as a Skype attacking assessment tool. So that's [10:44.750 --> 10:50.210] secretly my favorite, but you can see it's kind of still getting beaten out by Exchange and ADFS, [10:50.210 --> 10:58.550] maybe not by all that much. So one caveat with the cloud element here is that there are some [10:58.550 --> 11:05.050] false positives in there, because for this assessment, I didn't explicitly check whether [11:05.050 --> 11:12.250] they were hosted in Office 365. So this is just listing if when I made a link discover request, [11:12.250 --> 11:17.170] did it come back and say it was hosted in the cloud. So actually that number might even be [11:17.170 --> 11:22.430] higher if we'd have explicitly asked. And for some of them, it kind of seems to suggest that [11:23.250 --> 11:27.310] they're hosted in the cloud, but then maybe everything isn't properly configured and [11:27.310 --> 11:33.990] that service isn't there. It's like I say, the cloud kind of maybe take with a pinch of salt, [11:33.990 --> 11:38.850] but the others, that's what was found and what was kind of verified as existing. [11:39.850 --> 11:45.590] So the first part, subdomain enumeration, we'll go into that in a little bit more detail. [11:47.530 --> 11:55.570] Okay, so as I said before, I split the username enumeration URL and the pass spray or the endpoint [11:55.570 --> 12:00.790] validation. Previously, it bailed if the username enumeration wasn't there, [12:00.790 --> 12:08.590] but then I found multiple times, and in fact on that wider kind of mass assessment I did, [12:08.590 --> 12:14.270] then quite often you would find an organization to have just one or just the other. [12:14.750 --> 12:23.650] So for example, here you can see actually there's 53% had a password spray endpoint over 47% [12:23.650 --> 12:31.710] with a username enumeration. So kind of 6% more had a password spray endpoint than had both. [12:31.710 --> 12:36.250] There were some that just had username enumeration. What's interesting about this is that [12:36.250 --> 12:42.390] it means that for those organizations with just a kind of weird password spray NTLM authentication [12:42.390 --> 12:48.610] endpoint somewhere, then it seems likely that they potentially might not even be aware of that [12:48.610 --> 12:53.890] because they've kind of firewalled off or hidden away all of the well-known, [12:53.890 --> 13:00.190] the username enumeration, the standard login points, but then they have this one password [13:00.190 --> 13:06.270] spray endpoint that kind of seems to have eluded that. So yeah, that's kind of interesting. [13:08.010 --> 13:15.250] So Carnival looks for subdomains in the order shown here. So these statistics are taken from [13:15.250 --> 13:22.290] that 11% of the 100,000. So hopefully it means that we'll do as few requests as possible [13:22.290 --> 13:28.930] because obviously we're looking at the one that's highly likely to exist and then only looking at [13:28.930 --> 13:34.650] the others if it doesn't. So in future I might add an option for a kind of, you know, you can [13:34.650 --> 13:40.210] choose between light or full enumeration. So maybe you could choose to just look at the top [13:40.210 --> 13:48.230] two and then discount it. And yeah, so then again, maybe managing to kind of cut that down even more [13:48.230 --> 13:55.750] as to how many requests you need to send. So now username enumeration in a little bit more detail. [13:56.730 --> 14:02.850] So we're going to start with a demonstration. Okay, so we've got various options here that I'm [14:02.850 --> 14:08.770] going to go through. So firstly, smart enumeration that we saw before. So basically that will take [14:09.410 --> 14:15.090] these nine different formats of username taken from the top statistically likely [14:15.830 --> 14:24.530] usernames lists. And it will basically try the top username in each list and then the top of [14:24.530 --> 14:29.850] the next list, top of the next list. And essentially as you saw before, it's looking for three valid [14:29.850 --> 14:35.930] usernames of the same format. So that's using the timing based difference, which is fairly well [14:35.930 --> 14:43.850] known for Skype and Exchange. I've added it here for ADFS and RDWeb as well. So we've got this [14:43.850 --> 14:48.910] advanced option here as well, that if you want, you can kind of pick a format and where you want [14:48.910 --> 14:55.530] to start in that list, or you can leave it as it is. You can also do an individual username, or you [14:55.530 --> 15:00.930] can provide your own list. Or there's these pre-built ones. So these are kind of standard [15:00.930 --> 15:07.730] and service accounts. And Council Killer was created by my colleague Owen Bellis. So that's [15:07.730 --> 15:14.670] kind of a list of maybe fairly standard user accounts that might be in there. So you can set [15:14.670 --> 15:20.730] the password. So obviously also it works on the timing based difference. And then also if you get [15:20.730 --> 15:27.830] the password right, then great. So again, I would just show you, obviously this is fairly similar to [15:27.830 --> 15:35.630] what we saw before. One interesting additional point to note is additional information you can [15:35.630 --> 15:41.990] get depending on the service. So for Skype, then we can actually determine quite a bit of additional [15:41.990 --> 15:49.590] information. So SIP enabled basically just means... so actually, sorry, some of these will only come up [15:49.590 --> 15:54.910] if you get the password right as well. So SIP enabled would mean you've got the username and [15:54.910 --> 16:01.310] the password right, and that user is basically set up on Skype. So account disabled, whatever [16:01.310 --> 16:07.910] password you give, you would get that if the account is disabled. You should see that in a second. [16:08.990 --> 16:10.630] Now that it's switched over... [16:12.770 --> 16:18.350] in fact, I might have re-enabled that user. But so basically if you get a disabled account, [16:18.350 --> 16:24.350] then essentially we won't do anything else with it because basically whatever you put in, you're [16:24.350 --> 16:31.190] not going to be able to kind of do anything. For Skype, you can also tell if the password's expired [16:31.710 --> 16:37.130] and it's possible that you might actually then be able to take that password. And if you found an [16:37.130 --> 16:43.190] endpoint, you know, maybe for the VPN, it might be you can even kind of put that password in and it [16:43.190 --> 16:49.750] will ask you to reset it. Obviously on a test, that's probably a little bit too crazy of a thing [16:49.750 --> 16:57.250] to do, maybe for a red team or with the kind of technical point of contacts, you know, green light. [16:57.730 --> 17:01.330] And then for Skype, we can also get this server error. But again, that means you've got the [17:01.330 --> 17:07.490] password right. And as I said before, you'll get the access token there if you do. So yeah, [17:07.490 --> 17:14.970] username enumeration. OK, so as you've just seen, smart enumeration will take nine lists of [17:14.970 --> 17:20.550] statistically likely usernames and it will go through those until it finds three of the same [17:20.550 --> 17:26.470] and then automatically select that format and then carry on. Now, one interesting thing is this [17:26.470 --> 17:33.470] difference between legacy and modern formats. So legacy is domain slash username. Modern kind of [17:33.470 --> 17:39.630] email style is username at domain. So that can match, that they can match, but they don't [17:39.630 --> 17:44.970] necessarily have to. And again, the modern format could match the email, but doesn't necessarily [17:44.970 --> 17:51.250] have to. Now for username enumeration, we can only use the legacy format and that's to get that [17:51.250 --> 17:58.510] timing based difference. So one interesting thing is that that causes a little hiccup when rolling [17:58.510 --> 18:05.210] over to password spraying. So previously I used username enumeration to discover the format [18:05.210 --> 18:11.130] and then just assumed that it would be the same for the modern format for when we spray. Now, [18:11.130 --> 18:16.810] because technically that might not be the case, I don't do that anymore. The problem is it means [18:16.810 --> 18:23.590] on password spraying, if you choose to use the discovered username format, then invalid usernames [18:23.590 --> 18:32.610] will still take ages to do. So what I would suggest as a way of doing this, because basically, [18:33.010 --> 18:39.410] yes, so username enumeration, every invalid user, 30 to 40 seconds. So if you waited for that to [18:39.410 --> 18:44.790] finish anyway, that's going to take the rest of the day, a couple of days. So ideally what you [18:44.790 --> 18:51.130] want to do anyway is use username enumeration to get the potential, the likely format. [18:52.070 --> 18:58.430] That might take five minutes, say. Then pause that, switch over to password spray, [18:58.990 --> 19:05.490] and then instead of using the discovered format, which because we've only discovered that in the [19:05.490 --> 19:12.650] legacy style, then that will take a long time. So instead, pick the same format and password [19:12.650 --> 19:18.350] spray those. Hopefully you should get some credentials or some invalid, sorry, disabled [19:18.350 --> 19:24.890] accounts, which give you a pointer that that is the correct format. But if you don't, then it is [19:24.890 --> 19:30.290] possible that the formats don't match. And you might need to do a little bit more kind of manual [19:30.290 --> 19:36.630] going through different potential formats to discover which it is. So the other thing to say [19:36.630 --> 19:43.390] is that, so obviously with username enumeration, we discover a valid username, even if the password [19:43.390 --> 19:50.070] is wrong. Whereas password spraying, we only find out anything if we get both correct. [19:50.790 --> 19:58.350] So you can, if you want to, stay with username enumeration. You get a nice list and it takes 48 [19:58.350 --> 20:04.070] hours. However, because you will essentially be hitting the same users with the password that [20:04.070 --> 20:11.410] you're trying, then actually in terms of progressing the test, then you're not going to really lose [20:11.410 --> 20:16.130] anything by switching over to password spraying. You'd be hitting the same users. So you're going [20:16.130 --> 20:21.410] to find the same users that might have password one as their password. Just it would take 10 [20:21.410 --> 20:27.390] minutes instead of two days. So yeah, so that would be my suggested method. So now I'm going to [20:27.390 --> 20:34.130] show where we get the time-based difference and some other things for ADFS and RDWeb, because I [20:34.130 --> 20:40.650] don't think there's much publicly written about those, whereas there is for Skype and Exchange. [20:40.650 --> 20:47.370] So this is maybe more interesting. So this is where we get the time-based difference for ADFS. [20:47.910 --> 20:53.310] Now for ADFS, there's this extra kind of interesting extra bit, which is that it needs [20:53.310 --> 21:01.770] an MSIS SAML cookie to be sent in the request. So basically, in order to get that, I first send [21:01.770 --> 21:08.630] the request here, sorry, to the same place, but with this single sign out parameter. And basically [21:08.630 --> 21:15.650] the response to that will give us the cookie that we need, which we then here include when we make [21:15.790 --> 21:26.250] a password guess, as you can see. And then here you'll see the invalid response. So it's just 200 [21:26.250 --> 21:33.510] OK. And so that's told us nothing, or with the timing difference, maybe it's told us if the [21:33.510 --> 21:42.030] user's valid. And this is a valid response. We get the 302 redirect, and it sets this MSIS auth cookie. [21:42.650 --> 21:51.090] So for RDWeb, we make a POST request like this. So there's the username and the password to this URL. [21:52.270 --> 22:00.290] And if it's invalid, then we get the 200 OK again. And for TSWA auth HTTP only cookie, [22:00.290 --> 22:05.590] that either isn't there or it's blank. So again, we can use timing-based difference [22:05.590 --> 22:12.750] with the username. Or if it's completely valid, so the username and password are correct, [22:12.750 --> 22:21.690] again, it's the 302 redirect, and that TSWA auth HTTP only cookie now has a value as shown there. [22:22.170 --> 22:28.550] OK, so now password spraying. So as I said before, there's a little hiccup here with [22:28.550 --> 22:33.710] the discovered format. So obviously, that's up to you if you want to stick with that discovered [22:33.710 --> 22:40.810] format, or just simply choose it from the list, and we'll spray that in the user at domain style [22:40.810 --> 22:47.110] instead. So for password spraying, it basically defaults to using that style if possible, [22:47.110 --> 22:55.710] because it's quicker. And also, if you provide a list of usernames, you can, if you want, [22:55.710 --> 23:00.430] provide it with domain slash user or user at domain, and it will use what you've given. [23:02.810 --> 23:07.270] So let me have a look. Yep, so also, as I said, you can use these pre-built lists [23:08.030 --> 23:14.190] if you want to go for that, or you can give it a file of your own. And as I've said, if you want to, [23:14.190 --> 23:20.450] you can kind of pre-add whatever you want in there, and it will use that instead. [23:20.450 --> 23:25.930] So another thing to say is that if you want to, you can just go straight to password spraying. [23:25.930 --> 23:31.250] You don't have to do the username enumeration first. So yeah, basically, if you've done the [23:31.250 --> 23:35.830] subdomain enumeration, you've got the internal domain information, you can just go straight here. [23:35.830 --> 23:40.490] Maybe you've done some OSINT, and you have an idea what the format might be, you can just go [23:40.490 --> 23:46.030] straight here and spray it. Okay, so now a little demonstration of password spraying, [23:46.030 --> 23:52.370] so I can show you that in a bit more detail as well. Okay, so as you can see here, the top option [23:52.910 --> 23:58.150] is use discovered username format. So if we'd already done the username enumeration, [23:58.150 --> 24:03.570] then we'd be able to basically just tip that here. And as I've said, that will spray in the [24:03.570 --> 24:08.750] legacy format, so you need to be careful. The other choice you've got is that you can just pick what [24:08.750 --> 24:14.510] list you want to spray. Again, you can spray these kind of inbuilt lists, you can give it a file of [24:14.510 --> 24:22.290] your own, or you can also spray just enumerated users, which again will use the username [24:22.890 --> 24:27.450] that we've already discovered, the format that we've already discovered that user in, because [24:27.450 --> 24:33.390] obviously we know that that exists. So again, you can put the password in here, that's obviously [24:33.390 --> 24:39.410] distinct to the username enumeration password. And then if I click spray, you'll see that this is [24:39.410 --> 24:46.330] much quicker, because this is able to be multi-threaded, you're not waiting to check that [24:46.330 --> 24:55.610] the kind of time-based information is accurate, which multi-threading the username enumeration [24:55.610 --> 25:01.010] can kind of throw that off, because you're making it do multiple ones at the same time. [25:01.330 --> 25:06.230] And as you can see, so it's gone through the list, and as we saw before, it's found this user [25:06.230 --> 25:11.650] and access token here, and we've also got one with the disabled account. [25:13.090 --> 25:18.970] Okay, so as you saw there, we've got these different columns. So for Office 365 spraying, [25:18.970 --> 25:26.930] I'll come on to how we do that at the end. But basically, if we can spray the Microsoft login [25:26.930 --> 25:34.550] portal, then we can determine a valid user versus an invalid user, and valid credentials versus [25:34.550 --> 25:40.290] invalid credentials, and we can also actually tell if you've got the right username and password, [25:40.290 --> 25:47.830] but the organization has MFA enabled. So SIP enabled just means they have Skype access, [25:47.830 --> 25:52.690] and then depending on the service, we can tell some additional things. So again, Skype is actually [25:52.690 --> 25:59.550] my favorite service to look at, because you can actually tell the most from Skype. So we can tell [25:59.550 --> 26:04.890] if the account's disabled, you can tell if they're SIP enabled, and you can tell if even if the [26:04.890 --> 26:10.890] password is expired. So you've got password right, but it's expired, and also this server error, [26:10.890 --> 26:17.030] we can still tell that that's a valid username and password. For Exchange and RDWeb, then we can [26:17.030 --> 26:24.830] also still tell if the password is expired or if it's correct, but not some of the additional [26:24.830 --> 26:34.610] information. So username enumeration is timing based, so I only have one location for each of [26:34.610 --> 26:39.790] those where that's possible, but for password spraying, there's multiple places we can kind of [26:39.790 --> 26:48.550] spray. So again, from the 100,000 that I looked at, that's where these statistics have come from. [26:48.550 --> 26:54.370] So this is the order in the subdomain enumeration, and when we're validating if the password [26:54.370 --> 27:00.550] spray endpoints there, this is the order that Carnivore will look for those in. Again, hopefully [27:00.550 --> 27:06.650] this will reduce how many requests we need to make, and in the future, again, maybe that advanced [27:06.650 --> 27:11.930] option to say just look at the top two. Obviously you can see here the top two would actually get [27:11.930 --> 27:18.210] the vast majority of, you know, would have found it in the vast majority of cases, and then we've [27:18.210 --> 27:26.350] got some where there's literally just one out of that 11% that had slash web ticket was there. [27:27.410 --> 27:34.970] So this is a mix of known endpoints, kind of publicly written about, ones taken from IIS, [27:34.970 --> 27:42.330] from the server itself, and which allow NTLM authentication. So NTLM authentication, I'm [27:42.330 --> 27:47.910] going to go into a bit more detail now. So yeah, so just to mention briefly, when I had a look, [27:47.910 --> 27:54.350] there kind of doesn't seem to be that much for NTLM, web-based NTLM authentication spraying. [27:54.350 --> 27:58.950] It's possible Hydra or something similar might do it, but there didn't seem to be that many tools [27:58.950 --> 28:06.190] for it. So here's a little bit of code, very simple for C-sharp, so we can literally just create the [28:06.190 --> 28:12.330] new network credential, give it the username and password, and then in response, if it's 401 [28:12.330 --> 28:20.250] unauthorized, it's bad, otherwise you're good to go. So yeah, incredibly simple, and Carnivore [28:20.250 --> 28:28.690] is able to password spray NTLM auth endpoints. So for those, you can still do the blank type [28:28.690 --> 28:34.070] one message, but actually, it's part of the protocol is kind of determining and including [28:34.070 --> 28:40.090] the domain name. So here, when we're giving the username and password, we can literally just say [28:40.090 --> 28:48.510] cscot password one, and actually, as part of this request, it will add the nevtech element of that. [28:48.910 --> 28:56.230] So an interesting thing to note is that, as I said before, when I included some NTLM authentication [28:56.230 --> 29:02.730] endpoints with the list of subdomains that I look at, then there were some quite big organizations [29:02.730 --> 29:09.970] where everything else seemed to not be accessible, and then you've got one kind of weird NTLM auth [29:09.970 --> 29:16.330] endpoint hidden away, meaning that they're still susceptible to password spraying against [29:16.330 --> 29:21.370] the internal domain. Essentially, I mean, this could even be used for denial of service, [29:21.370 --> 29:27.590] because yes, we hit the normal password lockout policies, but essentially, if you purposefully [29:27.590 --> 29:33.010] hit that, and you've locked out everyone in the domain, so that's obviously something that [29:33.010 --> 29:39.750] an organization would want to be aware of, because that would be a bad day for them as well. [29:39.970 --> 29:45.830] So a quick sidetrack into a note on some of these different services, just in case you haven't seen [29:45.830 --> 29:54.830] them before. So ADFS, it's a portal that can be present to allow you to sign into different [29:54.830 --> 30:02.010] third-party services. Sometimes these might be assumed to be internal, so on past red teams, [30:02.010 --> 30:08.730] then this is given access to full job posting applications, so third-party applications, [30:08.730 --> 30:15.290] that were linked to the company's Twitter and LinkedIn, all of their job postings. So obviously, [30:15.290 --> 30:21.890] for kind of phishing or ongoing attacks, then having access through ADFS to that company's [30:21.890 --> 30:28.730] kind of LinkedIn job postings, or even reputational damage, could have been fairly troubling. So [30:28.730 --> 30:35.850] basically, you go to the same URL that I gave earlier, and that would give, or would normally [30:35.850 --> 30:39.870] give a kind of drop-down list, where you'll see the different applications that you can [30:41.810 --> 30:49.830] authenticate into. So I've also seen internal service desks that you can get into. I was [30:49.830 --> 30:55.610] logging all call center queries, so that contained incredibly sensitive customer details and [30:55.610 --> 31:00.990] information, because it was everyone on their call center putting in, you know, this customer [31:00.990 --> 31:06.390] this bank account number, and this credit card number has this question. And that was basically [31:06.390 --> 31:14.930] accessible externally through ADFS, and also things like HR, user admin portals. [31:15.410 --> 31:22.230] And so one other thing to note there is that if it's Office 365 and federated equals win, [31:22.230 --> 31:29.850] so basically Office 365's password spraying avoidance and defense mechanisms are fairly [31:29.850 --> 31:36.830] brutal. But basically, if the organization is federated, it means that you, not just that you [31:36.830 --> 31:44.010] can, but that you have to hit the ADFS server. And the response to a request I'll show in a bit [31:44.610 --> 31:51.190] will tell you where that ADFS server is. And basically, yeah, so if that exists, it's actually [31:51.350 --> 31:57.810] a lot better for us, because it means we can avoid Office 365's robust defense mechanisms, [31:57.810 --> 32:05.050] and we're just hitting ADFS the same as we would before. And for RDP, that one's fairly simple. [32:05.050 --> 32:10.290] It's literally just remote desktop through the web. Depending on how that's configured, maybe you'll [32:10.290 --> 32:17.570] be able to RDP into a workstation in the domain, you know, things like that. And yeah, so hopefully [32:17.570 --> 32:23.390] you'll have seen Skype and Outlook before. So now, post-compromise, we're going to look at the [32:23.390 --> 32:29.630] address list pulling first with a quick demonstration. Okay, so just as a reminder, [32:30.010 --> 32:37.330] so this is used to pull the address book through the UCWA API, just to remind you [32:37.330 --> 32:44.530] what that looked like. So we have these options here. So if you untick both of those, that means [32:44.530 --> 32:50.070] you're just looking for the compromised user. Personal contacts is the personal contacts of [32:50.070 --> 32:56.910] that compromised user, so their favorites. That's an interesting one for, say, ongoing social [32:56.910 --> 33:02.750] engineering, because then you know, and from the other information you've got here, then you know, [33:02.750 --> 33:09.150] okay, my compromised user has this job. His favorites include these people, and they have [33:09.150 --> 33:17.630] these jobs. So in terms of kind of fashioning a good phishing payload, then obviously that would [33:17.630 --> 33:23.870] be incredibly useful. We can kind of run this on the personal contacts first, and then add in the [33:23.870 --> 33:31.150] full address list, just to make that distinction, or yes, just pick the full address list. The data [33:31.150 --> 33:37.790] here, as I said before, so the ones that are chosen by default, those are the ones that are quicker to [33:37.790 --> 33:45.110] get. So for some reason, the way that the UCWA API works, then we get different pieces of information [33:45.110 --> 33:51.430] depending on where we've queried that person. So if they're you, you get this information. [33:51.430 --> 33:56.010] If they're your personal contact, you get this information. If it's through the people search [33:56.010 --> 34:01.350] function, you get that information. So this is kind of the stripped down list of what you get [34:01.350 --> 34:08.970] in every case. Then if you want to kind of go on and pull everything back, we can, but that can take [34:08.970 --> 34:15.670] numerous additional requests per user. So obviously for a domain of say 6,000 people, [34:15.670 --> 34:23.050] that could take an incredibly long amount of time. So what we do is if we kick this off, [34:23.050 --> 34:30.050] I might have just missed the button, that's a good sign. So you'll see it will pull back the [34:32.770 --> 34:36.850] standard information for the users first, and then it will kick off some additional threads [34:36.850 --> 34:43.670] to pull that additional information. And then as we go, you'll see that start to fill in. [34:44.290 --> 34:50.870] And then I'll go over some of these things later. And the additional settings here, [34:50.870 --> 34:56.670] I'll go over in more detail. Okay, so as you just saw, the information that we can get back [34:56.670 --> 35:03.010] through Skype for Business is a bit of a social engineer's dream. So you've got the department, [35:03.010 --> 35:09.630] you've got the office location they work in, and you've got even whether they're online or [35:09.630 --> 35:18.350] offline. Additionally, this does say online mobile, online desktop. So I've never fully [35:18.350 --> 35:26.210] seen that work in a useful way, but that option's there. So we also get email address, phone number, [35:26.210 --> 35:33.430] and this note here is any status message that they've set. So those quite frequently I've seen [35:33.430 --> 35:37.530] people will put on there about annual leave, if they're going to be out of the office. [35:37.670 --> 35:42.310] So obviously, again, as far as social engineering goes, you know what office they're in, [35:42.310 --> 35:46.790] you know their name, email address, what their job title is, you know they're going to be out [35:46.790 --> 35:52.370] of the office. So quite a lot of information for maybe even being able to turn up and say, [35:52.370 --> 35:58.210] oh, I'm supposed to be meeting so-and-so or even impersonating someone and you know that [35:58.210 --> 36:03.630] they're definitely not going to be in the office. So as I was saying, the problem is some of this [36:03.630 --> 36:11.890] extra information does take a large number of additional requests. So yeah, by all means, [36:11.890 --> 36:18.650] tick all, but just beware, that might take a very long time. And yeah, those are the options [36:18.650 --> 36:25.990] you've got. So Carnivore pulls the internal address book back using people search on the UC [36:25.990 --> 36:32.830] with the UCWA API. So this does mean that we're essentially having to search letter by letter, [36:32.830 --> 36:38.910] A through Z. However, there's an upper limit of 100 on the amount of responses it returns, [36:38.910 --> 36:45.310] and there isn't a next link that we can say, here's the first 100, now go to the next link [36:45.310 --> 36:51.550] for the next, you know, however many and so on. So basically, what we have to resort to [36:51.550 --> 36:59.010] is searching by digraphs and trigraphs. So essentially, A, B, A, C, A, D, and then even [36:59.010 --> 37:12.090] A, B, C, A, B, D, A, B, E. And so basically, we can then take either from the top statistically [37:12.090 --> 37:19.790] likely usernames list, we can do all of the likely and unique kind of three letters that are there, [37:19.790 --> 37:26.210] or you can do all possible two character combinations. So what's interesting and fun [37:26.210 --> 37:32.870] about the UCWA API is that there doesn't seem to be much rhyme or reason as to the way that works [37:32.870 --> 37:39.350] in terms of what we get back. So to take an example, if we're looking for every pull in the [37:39.350 --> 37:45.370] domain, so we know that there's four, and we search for P, you get back 150 results. So we're just [37:45.370 --> 37:51.090] going to get the top 100, there's two pulls in there. So then we search for PA, we get back 20 [37:51.090 --> 37:56.030] results, but this time there's three pulls. So we've got one extra, but for some reason, even [37:56.030 --> 38:00.690] though we haven't hit the upper limit, we've still not actually got back every pull who's in the [38:00.690 --> 38:07.130] domain. So then we search for PAU, and now we get this mysterious rogue fourth pull that we've never [38:07.130 --> 38:14.630] seen before. So essentially, in the interest of me keeping my sanity, I've stuck with diagraphs [38:14.630 --> 38:21.070] and trigraphs. It's possible you might want to go on and do quad graphs and quint graphs and whatever [38:21.070 --> 38:28.870] else they're called. However, so when I looked at this with the common trigraphs, and then with [38:28.870 --> 38:34.450] every possible three character combination, that actually only added an additional, I think it was [38:34.450 --> 38:44.990] maybe even one user, in a domain of 6,000. And the difference is common does 2,249 requests, [38:44.990 --> 38:53.250] whereas every possible was about 17,500. So all of that for one additional user that, as I've said, [38:53.250 --> 38:59.430] was kind of hiding away, and we weren't able to get otherwise. So essentially, hopefully that [38:59.430 --> 39:07.290] explains the kind of options on the address list a little bit more. One additional kind of side [39:07.290 --> 39:13.590] note. So it's fairly uncommon, but I've seen it where a misconfigured Microsoft web app proxy [39:13.590 --> 39:19.530] basically meant that when you auth to the first server, and it gives you back the token, and then [39:19.530 --> 39:25.140] you try and use that against the application's endpoint, then it essentially sends it to the [39:25.140 --> 39:32.480] wrong place, or you've been authed to the wrong box, and so it then doesn't like it. That actually [39:32.480 --> 39:40.080] also stops the legitimate Skype client from being able to authenticate, you know, to Skype. [39:40.080 --> 39:46.680] However, now Carnivore is able to detect that. It re-auths to the correct box and carries on. [39:46.680 --> 39:52.740] So basically Carnivore is able to connect and carry on using the API, even when the legitimate [39:52.740 --> 40:00.320] client actually couldn't. Okay, so now the final post-compromise function, which is MeetingSnooper. [40:00.520 --> 40:06.740] So unfortunately, my lab servers stopped working for this, so we have to make do with screenshots. [40:08.380 --> 40:15.760] Okay, so as you can see here, this is the MeetingSnooper tab. So once you've compromised the [40:15.760 --> 40:23.180] user, if you've got Skype available, so this uses the UCWA API as well, then you can go here [40:23.180 --> 40:29.520] and you have to choose, you have to pick the compromised user that you want to use there. [40:30.200 --> 40:35.820] So now we can either choose, basically we can do this for all compromised users or just a [40:35.820 --> 40:42.760] selected user. Now one thing to say is that this only picks up currently scheduled meetings, [40:43.200 --> 40:48.620] obviously. So basically we can run this throughout the day multiple times or, you know, at the start [40:48.620 --> 40:52.900] of the day you could run it, see if any new meetings have been added, and then kind of keep [40:52.900 --> 41:00.500] running it to pull back new information. So first of all, it dumps the standard dial-in information [41:00.500 --> 41:06.000] to the output log. So if you've ever had an email inviting you to a Skype meeting, this will look [41:06.000 --> 41:10.920] fairly familiar to you. So you've got the internal number you can dial and then a number for each [41:10.920 --> 41:19.720] country or city within that country. And so now apologies for how utterly rubbish this looks. [41:19.740 --> 41:25.760] As I said, my training lab unfortunately kind of packing in at the key moment there. But yeah, [41:25.760 --> 41:30.880] so to stress this isn't an exploit or a zero day, it's basically highlighting what's already [41:30.880 --> 41:38.220] possible through kind of weaponization of the UCWA API for attackers. Obviously it does depend [41:38.220 --> 41:45.320] on compromised credentials, but basically so far this tool has shown how we can go from external [41:45.320 --> 41:51.520] over the internet to kind of complete compromise and to this point of being able to dump out [41:53.080 --> 41:58.820] scheduled meetings for compromised users. So one thing to say is that when kind of using [41:58.820 --> 42:04.960] this tool on jobs, then often you find if you're going to get anyone, you probably are going to get [42:04.960 --> 42:12.300] like 50 to 100 users. And obviously in that case, then this becomes more interesting because, [42:12.300 --> 42:17.280] you know, one user might have one meeting that week, but if you've got 50 users, then maybe [42:17.280 --> 42:24.700] you've got someone who's a little bit more interesting. So you can then see here what [42:24.700 --> 42:29.880] happens when you run this tool is that it gives you information for each meeting that compromised [42:29.880 --> 42:37.660] user has scheduled. So the conference ID there is the PIN. So basically when you dial in, [42:37.660 --> 42:43.460] you dial into the phone number and it asks you for a PIN and that's that conference ID. [42:43.620 --> 42:49.400] And basically that conference ID is unique to that user. So when you dial in, you'll be [42:49.400 --> 42:56.780] impersonating whoever it is that you've compromised. So for example, you dial in, [42:56.780 --> 43:04.920] then you show up as being, say, a Chris Nevin guest. Now, obviously, if the people in the [43:04.920 --> 43:11.880] meeting are kind of using the desktop application, then maybe it would look weird to have multiple [43:11.880 --> 43:18.020] Chris Nevin guests there. If everyone's using the phone to dial in, I'm not sure that they [43:18.020 --> 43:25.000] would notice this at all. And in fact, even if they did see these two Chris Nevin guests, [43:25.000 --> 43:30.200] how likely is it that people are going to assume, oh, this is someone impersonating and joining in [43:30.200 --> 43:37.040] and listening, as opposed to maybe there's some weird bug that's happening. So the information [43:37.040 --> 43:42.940] we get here includes the subject of the meeting and the attendees. So obviously these meetings [43:42.940 --> 43:48.980] here I've scheduled just to kind of demonstrate, but obviously this could be a lot more juicy. [43:49.020 --> 43:53.100] So for example, you've compromised a user, you know from their address book that they're the [43:53.100 --> 43:59.260] head of financial fraud. And this meeting subject shows it's the weekly financial crime investigation [43:59.260 --> 44:05.960] update. So obviously you can see why this would be kind of concerning for an organization if this [44:05.960 --> 44:12.380] was possible. And because, again, without any exploit, any need for any further phishing or [44:12.380 --> 44:18.580] payloads being executed, you've basically gone from being over the internet to being able to [44:18.580 --> 44:24.500] listen in on and even record the sensitive meetings, essentially impersonating that user. [44:25.740 --> 44:31.340] So on the right, you can see the lobby bypass enabled. That basically means that if you [44:31.340 --> 44:38.700] dial in, does it bypass the lobby? If that's enabled, that means you're not even in a [44:38.700 --> 44:45.660] waiting room that someone has to let you in. So the join URL, if you go to that, you can join [44:45.660 --> 44:50.920] the meeting and you can basically enter a name of your choice. So obviously one thing you could do [44:50.920 --> 44:57.840] is, again, you've done the address book, you know, is there a social engineering angle? Maybe you [44:57.840 --> 45:03.840] could kind of choose your name based on that. Potentially it might be more likely to get caught, [45:03.840 --> 45:08.940] whereas actually just dialing in and there being two of the compromised user is maybe less [45:09.740 --> 45:16.940] troubling. So another thing to say is that the API basically only seems to give the meeting [45:16.940 --> 45:23.920] expiry. So that's two weeks after the meeting ends. So Carnivore will take off, it will remove the two [45:23.920 --> 45:30.480] weeks for you automatically, and then it's kind of maybe you'll need to do some kind of common [45:30.480 --> 45:37.280] sense around that. So for example, you see the top meeting there. All we actually have been able to [45:37.280 --> 45:43.620] is that the meeting ends at 11.30. Now I've set the subject for that one to be the time while I [45:43.620 --> 45:49.800] was troubleshooting. So you can see that actually that meeting starts at 11. As I say, normally you [45:49.800 --> 45:57.080] wouldn't get that information because that's the subject. So obviously, yeah, if you apply some [45:57.080 --> 46:02.580] common sense to it, then you can see, OK, the meeting ends at 11.30. It probably starts at 11 [46:03.080 --> 46:11.400] or even 10.30. So yeah, so that's the meeting snooping, what you get back from it basically. [46:11.520 --> 46:17.200] So there are a couple of extra points to mention, which are that this only seems to be able to pull [46:17.200 --> 46:23.460] back self-scheduled meetings. So again, doesn't fully make sense to me because obviously in [46:23.460 --> 46:27.720] Outlook or something, you don't just see meetings you've scheduled. You see every meeting [46:28.380 --> 46:33.100] that you're scheduled to be a part of. Unfortunately, we're not able to get that [46:33.100 --> 46:40.300] through this tool. And so, yeah, and then also meeting end time only, as I said before. [46:40.620 --> 46:47.040] Now, there are some weird edge cases with that. So, for example, I set a recurring meeting. [46:47.040 --> 46:52.300] And so the only information we get back is that it ends on the 26th of December 2022, [46:53.060 --> 46:58.160] which obviously isn't that useful. Again, maybe you could figure out, OK, that's a Friday. It's [46:58.160 --> 47:04.540] at half ten. So maybe it's every Friday. But again, we can't get that back through the API, [47:04.540 --> 47:12.680] unfortunately. OK, so Office 365. So I'm not going to demo this. So what I've been showing so far is [47:12.680 --> 47:18.520] basically just my lab. And so, yeah, we're not going to demo Office 365, but I'm going to talk [47:18.520 --> 47:25.560] you through how Carnivore works. So, for example, or sorry, one thing to say is that username [47:25.560 --> 47:31.780] enumeration that doesn't require a password guess has been quite widely covered. So there's things [47:31.780 --> 47:38.900] like O365 or O365enum. So I'm just going to quickly kind of get into password spraying [47:38.900 --> 47:46.520] and give some key pointers. So, as I said before, federated is a win. So just the usual [47:46.520 --> 47:53.120] Active Directory rules will apply to lockouts. But again, that kind of doesn't include the [47:54.540 --> 48:02.840] extremely robust Office 365 rules. So, as I've said, there's a link that I'm about to show you [48:02.840 --> 48:08.200] where you can find out if an organization is federated or not. If it is, you'll get back the [48:08.200 --> 48:15.560] ADFS server location and Carnivore will add that automatically. So if it's not federated, we can [48:15.560 --> 48:23.500] still spray, sorry, we have to spray the Office portal, but then we can also determine if a user [48:23.500 --> 48:28.940] and password is valid, even if we have MFA on there. I'm sorry, I should have said again, [48:28.940 --> 48:34.460] with federated, if it's federated, you have to spray ADFS and you can't spray the Office portal [48:34.460 --> 48:40.580] and you won't get back anything interesting, anything useful. So password spray counter [48:40.580 --> 48:47.580] measures for Office 365. So they have things like trusted versus untrusted network, have separate [48:47.580 --> 48:53.840] bad password counts. So again, if you're from the untrusted side, which presumably you would be [48:54.700 --> 49:01.040] from an untrusted network, then, you know, your password spray is adding to account of everyone [49:01.040 --> 49:10.240] else in the world. So again, lockout is fairly frequent and quick. But from the Microsoft side, [49:10.240 --> 49:14.900] obviously that's designed so that then the genuine user can still sign in while on their [49:14.900 --> 49:21.600] corporate VPN or something like that. So obviously good security measures, but difficult from a red [49:21.600 --> 49:28.920] team perspective. So first of all, to find out if the organization is federated. So this is an [49:28.920 --> 49:35.260] example request here. So the username itself is irrelevant. It's just the appdomain.com that we're [49:35.260 --> 49:41.880] looking for. And the response here. So if they were federated, that would say [49:42.740 --> 49:49.400] federated instead of managed. And it can also include some kind of boilerplate text. So, [49:49.400 --> 49:55.040] for example, is keep me signed in disabled? Obviously, that one might be interesting from [49:55.220 --> 50:01.780] a red team perspective, because maybe it hints that they have fairly good security and they've [50:01.780 --> 50:07.300] had their configuration looked at because users can't just stay signed in forever. [50:07.820 --> 50:13.480] You also get the federation brand name there, and you can get back, you know, [50:13.480 --> 50:20.000] logo information and that kind of thing. So also, if they said federated, then we would see the [50:20.940 --> 50:25.640] location of the ADFS authentication endpoint there as well. [50:26.920 --> 50:33.220] So for password spraying, this is how Carnivore does it. So this is the endpoint that we're [50:33.220 --> 50:40.520] hitting. There's the username and the password. So the client ID and the scope, obviously, [50:40.520 --> 50:46.200] that could be tweaked to maybe be a little bit more realistic or representative. But this is [50:46.200 --> 50:53.620] what Carnivore uses. And so this first one is if there's an invalid password. Now, obviously, [50:53.620 --> 50:59.880] the actual response here says invalid username or password. So obviously, that seems like maybe [50:59.880 --> 51:04.360] that's going to be a bit tricky for us. Is it the username or is it the password? We're not fully [51:04.360 --> 51:11.360] sure. But then if the username is incorrect, then we get this message back. The user account does [51:11.360 --> 51:17.480] not exist in that directory. So obviously, from that, we can tell the previous response means the [51:17.480 --> 51:23.560] password's wrong, not the username. And just to also mention there where it says email hidden, [51:23.560 --> 51:29.980] I've not added that. That's the actual response. So then this is a valid user and password without [51:29.980 --> 51:38.400] NFA. So again, this is specific to the request that I make in Carnivore. So because we gave a [51:38.400 --> 51:44.260] client ID that doesn't exist, then if the username and password is correct, you'd get this unauthorized [51:44.260 --> 51:51.480] client and a message that that application doesn't exist, because obviously, it's not a proper [51:51.480 --> 52:01.240] client ID. And again, so if it's valid user and password with MFA, then again, we get this invalid [52:01.240 --> 52:06.920] grant. But now it's telling us that it's due to configuration, meaning that you need to supply [52:06.920 --> 52:13.200] multi-factor authentication. So again, username and password is correct, but you need MFA. [52:14.840 --> 52:22.180] So outro very briefly. Yes, so almost forgot to put it in, but here's a link to the tool itself. [52:22.360 --> 52:27.540] So obviously you can go there and download the latest version and any issues or anything that [52:27.540 --> 52:32.400] you want to bring up there, I'll be happy to try and help wherever I can. So thank you for [52:32.400 --> 52:36.800] listening. Hopefully it's been useful and enjoy carnivoring.