[00:00.000 --> 00:03.460] Hello. Well, hello and welcome to what is a day, [00:03.460 --> 00:07.160] one of Red Team Village at DEF CON. [00:07.560 --> 00:10.720] I'm Ben Sadegopour and I have Tanner Barnes, [00:10.720 --> 00:12.180] aka Staticflow here with me. [00:12.180 --> 00:16.100] We want to talk about how to identify assets in the cloud. [00:16.380 --> 00:18.300] And we did some really cool research, [00:18.300 --> 00:19.440] but before we jump into it, [00:19.440 --> 00:21.540] we're going to do some agenda, [00:21.920 --> 00:23.160] intro on who we are, [00:23.160 --> 00:24.640] and kind of give you a background [00:24.640 --> 00:25.700] on why we did this project. [00:25.700 --> 00:27.480] So let's just jump into it. [00:30.220 --> 00:31.700] One sec, there we go. [00:31.700 --> 00:34.140] Cool. I'm trying to see where my notes went. [00:34.220 --> 00:36.600] There we go. [00:36.980 --> 00:39.920] So for agenda for today, we talk about who we are, [00:39.920 --> 00:45.560] why we focus so much on the cloud and our solution, [00:46.040 --> 00:47.600] and talk about how we mass exploited [00:47.600 --> 00:51.060] or look for vulnerabilities and mistakes in mass. [00:51.060 --> 00:53.840] And then we'll also have some really cool examples [00:54.760 --> 00:56.000] of things that we accomplished [00:56.000 --> 00:59.360] and got some boundaries with in the past few months. [00:59.720 --> 01:01.400] So originally when we, before we get into it, [01:01.400 --> 01:02.500] I want to give a background. [01:02.500 --> 01:05.220] Tanner and I were going to work on this for an entire year. [01:05.220 --> 01:07.880] So this was supposed to be for next DEF CON, [01:08.420 --> 01:10.260] but unfortunately things happened [01:10.260 --> 01:12.320] and we wanted to go do an experiment with it. [01:12.320 --> 01:15.360] And you can't say no to want to talk at DEF CON. [01:15.360 --> 01:17.720] So we're doing a smaller version of this today [01:18.380 --> 01:19.800] as a part of DEF CON. [01:19.800 --> 01:21.200] And hopefully next year we can come back [01:21.200 --> 01:24.400] with more examples and more in-depth research. [01:24.940 --> 01:26.700] So a quick about me, [01:26.700 --> 01:28.580] I'll also let Tanner introduce himself afterwards. [01:28.580 --> 01:29.820] Again, I'm Ben Sadigapour, [01:29.820 --> 01:31.220] mostly polynomial as Naham said. [01:31.220 --> 01:32.740] You probably have seen me on Twitch. [01:32.740 --> 01:35.200] If you are a, I have a Twitch user. [01:35.540 --> 01:39.780] I currently work at Head of Hacker Education at HackerOne. [01:40.000 --> 01:42.900] I also create content and stream on Twitch. [01:42.900 --> 01:45.260] And again, you can follow me on all social medias [01:45.960 --> 01:47.500] under the name Naham Sec. [01:50.140 --> 01:51.160] Awesome. Yeah. [01:51.160 --> 01:53.380] So like you said, my name is Tanner Barnes, [01:53.380 --> 01:55.500] Static Flow on Twitter and some other things. [01:55.500 --> 01:58.460] So I am, I apologize for my dog. [01:58.640 --> 02:00.600] I hope it's not terribly loud. [02:00.600 --> 02:02.560] There's nothing I can really do about that. [02:03.500 --> 02:06.780] So I'm a developer originally by trade. [02:06.780 --> 02:08.080] And then I've been doing pin testing [02:08.080 --> 02:11.980] for Aon Cyber Solutions for like the last year and a half now [02:11.980 --> 02:14.240] and I'm an occasional bug hunter, [02:14.800 --> 02:18.220] but I help a lot more with some other bug hunters like Ben [02:18.220 --> 02:19.780] and some other people I know, [02:19.780 --> 02:22.020] helping build some tools for them. [02:22.020 --> 02:24.920] So there's my GitHub where a lot of the stuff I make is up. [02:24.920 --> 02:27.980] And then I also have just recently started doing [02:27.980 --> 02:31.660] some live coding on Twitch as a handler. [02:33.260 --> 02:34.920] Tanner, before we jump into this, [02:34.920 --> 02:37.460] I know that DEF CON has this tradition [02:37.460 --> 02:41.120] where when you speak at DEF CON, you have to take a shot. [02:41.540 --> 02:42.840] I don't know if you have one ready, [02:42.840 --> 02:45.460] but I unfortunately picked one for myself. [02:45.460 --> 02:48.280] So cheers. [02:48.420 --> 02:49.220] Go ahead. [02:49.440 --> 02:50.480] Cheers, man. [02:52.820 --> 02:55.880] Sorry, I did not, I could have ran downstairs, [02:55.880 --> 02:57.260] but I don't think we have the time. [03:02.730 --> 03:03.570] Go ahead. [03:03.570 --> 03:07.790] Cool, so that's kind of the big question of this, right? [03:07.790 --> 03:09.430] Is why the cloud? [03:09.430 --> 03:11.170] Like what's the meaning behind, [03:11.170 --> 03:13.170] why did we get into doing all this? [03:13.950 --> 03:17.050] So there's not currently a ton of great solutions [03:17.050 --> 03:18.870] for looking at cloud assets, right? [03:18.870 --> 03:20.910] So you've got things like Census and Shodan, [03:20.910 --> 03:22.510] but some of those can be really expensive. [03:22.510 --> 03:25.670] I know Census can be $900 a month. [03:26.070 --> 03:28.250] Shodan licenses for their APIs [03:28.250 --> 03:29.930] aren't necessarily the cheapest. [03:30.810 --> 03:34.630] And it's definitely worth looking into, right? [03:34.630 --> 03:36.270] And so we wanted to kind of see like, [03:36.270 --> 03:40.030] how could we look into cloud assets? [03:40.030 --> 03:43.290] And then, what would that look like expense-wise? [03:43.370 --> 03:44.690] And the other part is just kind of, [03:44.690 --> 03:46.150] who isn't in the cloud these days, right? [03:46.150 --> 03:47.510] Like, I think you're probably hard-pressed [03:47.510 --> 03:51.390] to find a large Fortune 500, Fortune 50 company [03:51.390 --> 03:54.050] that's not running some part of their infrastructure [03:54.050 --> 03:55.250] out in the cloud. [03:55.250 --> 03:57.970] So it's a huge target-rich environment, right? [03:57.970 --> 04:02.770] If you look at just Azure, AWS, GCP, [04:02.770 --> 04:06.110] you're looking at something like 88 million IP addresses. [04:06.510 --> 04:08.050] And that's just in their, [04:08.050 --> 04:10.430] what I guess I would call like their EC2 space [04:10.430 --> 04:13.150] or their compute space, right? [04:13.150 --> 04:16.450] We're not talking about like stuff for Lambda functions, [04:16.450 --> 04:18.650] right, that have like pooled up IP addresses, [04:18.650 --> 04:21.650] but 88 million IP addresses that could actually be spun up [04:21.650 --> 04:23.410] for somebody's instance. [04:24.450 --> 04:27.950] And this is also a big part of where organizations, [04:27.950 --> 04:30.270] large ones use to spin up their kind of quick [04:30.270 --> 04:33.050] and easy development boxes. [04:33.050 --> 04:35.330] Things are quickly testing on the edge. [04:35.330 --> 04:37.970] It's a great, cheap, easy way to deploy that. [04:38.050 --> 04:40.630] So if we can get really good coverage and insight [04:40.630 --> 04:42.730] into what's happening on the cloud, [04:43.170 --> 04:45.050] we can really find some really cool targets [04:45.050 --> 04:48.410] and get some really useful data out of it. [04:48.910 --> 04:50.110] Next slide, please. [04:50.790 --> 04:52.810] Yeah, so I mean, this is kind of an example, right, [04:52.810 --> 04:56.390] of just some real quick, like dirty, [04:56.390 --> 04:58.550] just some quick data that we grab [04:58.550 --> 05:00.030] from our database real quick. [05:00.030 --> 05:03.770] So when you're looking at like 1,000 corp domains, [05:03.770 --> 05:05.870] 13,000 internal domains, [05:05.870 --> 05:07.650] we found that actually very fascinating [05:07.650 --> 05:11.410] about how a lot of these domains in the cloud, [05:11.430 --> 05:15.150] a lot of their DNS names have stuff like internal corp dev, [05:15.150 --> 05:16.630] and it's odd, you would, I guess, [05:16.630 --> 05:17.790] initially I would have thought [05:17.790 --> 05:19.570] that you wouldn't see a lot of that. [05:19.570 --> 05:22.190] But yeah, so I think that's cool [05:22.190 --> 05:24.990] is that that kind of tells you the type of things [05:24.990 --> 05:27.230] companies are putting out there on the cloud [05:27.230 --> 05:28.590] and on the edge, right? [05:29.130 --> 05:30.810] And then things like API, [05:30.930 --> 05:33.030] a lot of cloud APIs are obvious. [05:33.030 --> 05:35.890] And then if you look at like some specific target options, [05:35.890 --> 05:39.310] right, like anything on Yahoo or OAuth, right, [05:39.310 --> 05:42.490] you're looking at 100,000, 4,000 targets, right, [05:42.490 --> 05:43.850] all out there in the cloud. [05:46.840 --> 05:49.340] Right, so this is my favorite part. [05:49.380 --> 05:53.540] This is when Ben kind of brought this idea to me, [05:53.540 --> 05:55.020] I was immediately hooked [05:55.020 --> 05:57.360] and I thought it was gonna be a real fun challenge. [05:58.620 --> 06:00.820] So yeah, so we're getting to kind of how it works [06:00.820 --> 06:01.900] and what we did. [06:02.220 --> 06:05.940] So it's built in Go, I've been on a huge Go kick, [06:05.940 --> 06:08.760] if anybody knows me, or if you look at my GitHub, [06:08.760 --> 06:09.560] it's kind of funny, [06:09.560 --> 06:12.660] it started out when I really started doing GitHub work, [06:12.720 --> 06:14.320] a lot of Java, a lot of, [06:14.320 --> 06:16.340] I call last year the year of Java for me, [06:16.340 --> 06:19.480] it was a lot of like perf extensions and things like that. [06:19.660 --> 06:23.680] And then I got into writing Golang code [06:23.680 --> 06:25.380] and I just got hooked. [06:25.380 --> 06:27.420] So pretty much everything I've built since then [06:27.420 --> 06:29.860] has been in Go, it's super great. [06:30.000 --> 06:34.180] Go routines make work like this especially easy, [06:34.180 --> 06:35.520] it's incredibly concurrent [06:35.520 --> 06:38.140] and it's a language built for concurrency. [06:38.740 --> 06:39.820] So if you look at like, [06:39.820 --> 06:43.320] what is the tool that we built do as kind of a core thing, [06:43.320 --> 06:45.300] so what we're doing is we're taking IP addresses [06:46.700 --> 06:50.500] and we are hitting them on a certain port over TLS [06:50.500 --> 06:54.220] and then we're pulling the CNAME and DNS name records [06:54.220 --> 06:55.960] out of the certificate it returns [06:55.960 --> 06:58.820] and storing that tied to the IP address. [06:58.820 --> 07:03.840] So we're building a huge database of domain names [07:03.840 --> 07:05.780] to IP addresses in the cloud. [07:05.780 --> 07:10.040] So kind of unmasking who owns these 88 million IP addresses [07:10.040 --> 07:10.860] out in the cloud [07:10.860 --> 07:14.360] and to try to differentiate targets from them. [07:14.680 --> 07:16.980] As far as the actual code goes, [07:16.980 --> 07:20.000] not really incredibly, there's not a lot of magic there. [07:21.260 --> 07:23.840] Mainly, it was just kind of starting ground [07:23.840 --> 07:25.780] for like reaching that data. [07:25.880 --> 07:29.060] The real magic comes from scanning it at scale, right? [07:29.060 --> 07:31.220] So again, 88 million IP addresses, [07:31.880 --> 07:33.560] you're not really gonna be able to hit that [07:33.560 --> 07:34.860] from your box, right? [07:34.860 --> 07:39.080] That's a kind of an untenable amount of data to go through. [07:39.220 --> 07:42.000] So scaling it is super important. [07:44.700 --> 07:47.720] So this is my favorite slide, it was a lot of fun typing. [07:47.720 --> 07:49.980] I sent it to like eight people when I wrote it. [07:49.980 --> 07:57.200] So we were looking at about 535,000 slash 24-siders [07:57.200 --> 08:01.780] across large Barn Bunny targets and cloud infrastructure, [08:01.780 --> 08:04.580] and then across 11 main ports. [08:04.580 --> 08:09.080] So you're looking at about 1.4 billion unique scan targets [08:09.080 --> 08:10.720] that we were looking at. [08:11.040 --> 08:14.400] And I just recently, we just created version two of the API [08:14.400 --> 08:17.440] and I was able to get it down to a full scan of that space [08:17.440 --> 08:18.720] in 15 minutes. [08:18.720 --> 08:21.640] So that comes out to a rate of about 1.6 million [08:21.640 --> 08:26.700] unique scan targets a second with 28 to 29 million [08:26.700 --> 08:29.400] identified targets across those 11 ports. [08:29.400 --> 08:32.180] And then my favorite thing is that all of that costs [08:32.180 --> 08:37.500] about $25 in AWS charges, which to me is wild. [08:39.200 --> 08:42.220] So there is a flip side to any coin like that. [08:42.260 --> 08:45.840] There were a lot of lessons learned on this way. [08:46.420 --> 08:49.080] One thing I learned off the bat is do not try this [08:49.080 --> 08:50.020] with Lambda. [08:50.020 --> 08:52.820] Lambda seems like a really simple solution to do this. [08:52.860 --> 08:57.360] Turns out they will not let you spin up 535,000 Lambda [08:57.360 --> 08:59.580] functions at once, which is not shocking. [09:00.060 --> 09:04.360] I tried that once and my AWS bill was insane. [09:05.660 --> 09:07.660] So that was definitely a no-go. [09:07.660 --> 09:10.640] So there's definitely been some heavy hitting AWS bills [09:10.640 --> 09:12.660] along the way working through this, [09:12.660 --> 09:16.980] getting to that mythical $25 bill of scan. [09:17.180 --> 09:20.420] As far as the code goes, when you get to things like this [09:20.420 --> 09:23.700] at scale, the quicker you can make the underlying code [09:23.700 --> 09:25.340] is obviously super important. [09:25.340 --> 09:29.120] So I had a lot of fun building a really simple solution [09:29.120 --> 09:31.200] and then going through with profiling tools [09:31.200 --> 09:33.820] that are built into Go to really carve out every [09:34.520 --> 09:37.480] wasted piece of memory and wasted CPU cycle [09:37.480 --> 09:40.740] to just make it as fast as humanly possible, [09:40.740 --> 09:42.240] or I guess as computer possible. [09:42.240 --> 09:44.480] So when I did put it on the scaling solution, [09:44.480 --> 09:46.260] it would run quicker on the scaling solution [09:46.260 --> 09:48.500] and thus cost us less money. [09:49.540 --> 09:52.160] One part of the funniest lesson we learned from all this [09:52.500 --> 09:54.640] is definitely be careful like who you're scanning [09:54.640 --> 09:59.600] and what you do with the data you get from the scan. [09:59.600 --> 10:03.000] The cooling about this scanner is it actually is very light [10:03.000 --> 10:05.880] on the network of targets because we're actually [10:05.880 --> 10:10.440] not making a full TLS HTTPS connection. [10:12.340 --> 10:14.620] It's rare you would actually probably see this [10:14.620 --> 10:17.440] on your ingress logs to your server [10:17.440 --> 10:19.960] because we're not actually making a full handshake. [10:21.060 --> 10:24.340] What we mistakenly did once was when we had the data, [10:24.340 --> 10:25.680] we decided, and we'll get to in a bit, [10:25.680 --> 10:28.060] we had a really cool fingerprinting tool that we built [10:28.060 --> 10:29.680] and we decided we'd try to go fingerprint [10:29.680 --> 10:31.500] our entire database. [10:31.900 --> 10:34.880] We got some very hilarious LinkedIn messages [10:34.880 --> 10:38.340] and Twitter DMs from some very worried CISOs [10:38.340 --> 10:41.100] who thought we were trying to take over [10:41.100 --> 10:42.640] or attack their entire network. [10:42.640 --> 10:45.180] So definitely important with great power [10:45.180 --> 10:46.380] comes great responsibility, [10:46.380 --> 10:48.840] especially with a data set this large. [10:52.540 --> 10:54.100] So it's cool, right? [10:54.100 --> 10:56.520] Domain IP mappings, it's a lot of fun. [10:56.520 --> 10:57.700] You can get some really cool insight [10:57.700 --> 10:59.100] into what's out there in the cloud, [10:59.100 --> 11:00.500] but it's just a start, right? [11:00.500 --> 11:02.480] So we have all this data, [11:02.480 --> 11:04.220] but what are we going to do with it, right? [11:04.220 --> 11:08.120] And we kind of hinged and found some really core things [11:08.120 --> 11:09.580] that we do with the data, right? [11:09.580 --> 11:12.680] So we have these 28 million hosts [11:12.680 --> 11:15.480] that we found across 11 ports, [11:15.480 --> 11:19.560] but obviously, XYZ Laundromat's website [11:19.560 --> 11:21.720] isn't going to pay us for that sick IDOR [11:21.720 --> 11:24.460] we found in their website, right? [11:24.460 --> 11:28.100] So we need to filter that down to bounty targets. [11:28.760 --> 11:34.420] There's a great repo we'll get to in a bit about just that. [11:35.500 --> 11:37.340] I'm blanking on the guy's name, [11:37.340 --> 11:39.680] but it's basically a bug bounty targets, [11:39.680 --> 11:42.840] like aggregation list that keeps a wildcard list [11:42.840 --> 11:46.520] of wildcard scopes on bug bounty programs. [11:46.520 --> 11:48.180] So we use that as kind of a seed [11:48.180 --> 11:50.300] and then some kind of custom ones [11:50.300 --> 11:52.900] that we put in there as well to run concurrently [11:52.900 --> 11:56.420] with the scan and filter them off into their own database. [11:56.420 --> 12:00.260] So while we have a list of every domain that we found, [12:00.260 --> 12:03.440] we have a specific database just for bug bounty targets. [12:03.620 --> 12:06.820] And that helps us kind of filter the data down [12:06.820 --> 12:09.080] to then point into some of these other tools. [12:09.560 --> 12:11.200] Another really cool thing that we'll get to [12:11.760 --> 12:14.120] is we started diffing scans, right? [12:14.120 --> 12:16.400] So initially we started out just running [12:16.400 --> 12:18.440] kind of one a week or one every other week, [12:18.440 --> 12:21.140] and we realized we could actually get a lot of coverage [12:21.140 --> 12:23.460] and find some even cooler vulnerabilities [12:23.460 --> 12:25.660] if we started doing this twice a week [12:26.240 --> 12:29.280] and looking at what had changed in between those two days. [12:29.280 --> 12:30.820] So obviously a lot of overlap, [12:30.820 --> 12:32.420] but then those really new ones, [12:32.420 --> 12:34.820] we realized we were catching those only, [12:34.820 --> 12:37.020] but they'd only been in existence a day or two. [12:37.120 --> 12:39.280] And that was really helpful to kind of focus [12:39.280 --> 12:41.540] on what we needed to look at first. [12:42.080 --> 12:46.120] Another really cool one is vhost discrepancies [12:46.120 --> 12:48.500] or virtual host discrepancies with the host header, right? [12:48.500 --> 12:51.760] So we have all these targets, but again, [12:51.760 --> 12:53.760] you're looking at millions of them. [12:53.760 --> 12:55.360] What is kind of a key differentiator [12:55.360 --> 12:56.760] for things that might be interesting? [12:56.760 --> 12:59.640] And one of those things is how they might handle virtual hosts. [12:59.640 --> 13:01.860] So, and I'll get to that, [13:01.860 --> 13:03.380] and we'll come to that later in the slides, [13:03.380 --> 13:05.520] but you'll find some hosts in this data. [13:05.520 --> 13:08.300] We found some where you can hit it by IP [13:08.300 --> 13:09.780] and you'll get one result. [13:09.780 --> 13:11.740] If you hit it by its domain, you'll get a different result. [13:11.740 --> 13:14.500] And if you hit it by a local host header, [13:14.500 --> 13:16.520] or a local host host header, [13:16.520 --> 13:18.580] you will get sometimes access to stuff [13:18.580 --> 13:20.360] you wouldn't have normally. [13:21.700 --> 13:24.160] And then the final thing was that fingerprinting, right? [13:24.160 --> 13:26.880] So being able to pull like titles, response links, [13:26.880 --> 13:29.300] status codes, and take that data [13:29.300 --> 13:31.340] and use it to fingerprint specific services [13:31.340 --> 13:35.020] would let us key in on large technologies [13:35.020 --> 13:36.820] that we knew we wanted to go after, [13:36.820 --> 13:39.500] like the Grafana bug that Ben's gonna talk about [13:39.620 --> 13:41.820] a little bit later and stuff like that. [13:41.820 --> 13:44.680] It allows us to kind of hone in on a specific technology. [13:48.490 --> 13:49.610] So, right. [13:49.610 --> 13:51.350] So like I said, this is, that's the repo. [13:51.350 --> 13:51.850] It's great. [13:51.850 --> 13:52.830] I'd recommend everybody, [13:52.830 --> 13:55.150] if you're starting out with a recon set [13:55.150 --> 13:57.650] and you wanna look at like where to start doing recon on, [13:57.650 --> 14:01.210] that repo right there is a great guide [14:01.210 --> 14:02.790] for sure to get started. [14:02.790 --> 14:04.910] Like I said, you got 1.4 billion targets [14:04.910 --> 14:06.610] that creates a lot of noise. [14:06.610 --> 14:09.850] Obviously not all 1.4 billion come back, [14:09.850 --> 14:11.830] but out of that 28 million, [14:11.830 --> 14:13.990] we really need to kind of filter it down pretty quickly [14:13.990 --> 14:17.310] to get to what will actually get us some good bounties. [14:17.850 --> 14:19.590] I'm so sorry, guys. [14:20.670 --> 14:22.630] So being able to filter like that [14:23.250 --> 14:27.630] brings us access to a smaller target set. [14:27.710 --> 14:28.650] Next slide. [14:33.300 --> 14:33.920] Right. [14:33.920 --> 14:35.740] So like I said, the scan diffing, [14:35.740 --> 14:37.560] obviously multiple scans, like I said, [14:37.560 --> 14:39.340] they have some overlap, [14:39.340 --> 14:41.240] but the kind of the big usefulness there [14:41.240 --> 14:44.000] is determining those new hosts, right? [14:44.000 --> 14:46.460] Can we see, we run on Tuesday, right? [14:46.460 --> 14:48.680] And we run again on Thursday, what's changed? [14:48.680 --> 14:50.980] And those new hosts from Tuesday to Thursday [14:50.980 --> 14:52.400] are gonna be really interesting [14:52.400 --> 14:54.600] because they're really fresh, right? [14:56.180 --> 15:00.080] Along with that, we also started doing historical archives. [15:00.600 --> 15:02.780] The way we've kind of been doing it in the past [15:02.780 --> 15:04.120] was basically we would run on Tuesday [15:04.120 --> 15:08.200] and then on Thursday, on Thursday's scan, [15:08.200 --> 15:12.100] we would push Tuesday's off into cold storage, [15:12.620 --> 15:14.620] just in a CSV file, flat file, [15:14.620 --> 15:17.180] and then we would move Thursday's scan, [15:17.180 --> 15:21.740] or we kept two scans of targets, right? [15:21.740 --> 15:23.600] So Tuesday's would go into, [15:23.600 --> 15:25.120] that's what I'm sorry, that's what I was trying to say. [15:25.120 --> 15:27.460] Tuesday's would go into a historical database, [15:27.460 --> 15:29.020] and then the previous Thursday [15:29.020 --> 15:30.360] would go into cold storage, [15:30.360 --> 15:32.180] and then Thursday would be the newest data, [15:32.180 --> 15:33.960] and then it would continually shift, right? [15:34.180 --> 15:35.860] So we can always go back [15:35.860 --> 15:40.140] if we want to kind of do long-run sentiment analysis [15:40.140 --> 15:42.200] of like, not sentiment analysis, [15:42.200 --> 15:44.220] we want to do a long-run months analysis [15:44.220 --> 15:47.780] of how Verizon spins up domains in the cloud. [15:47.780 --> 15:49.600] We can look at all that historical data [15:50.460 --> 15:54.060] and see like, oh, this is how they name their hosts [15:54.060 --> 15:55.960] when they're deploying things to the cloud, [15:55.960 --> 15:57.840] which can help us in further scans. [16:02.430 --> 16:03.890] So yeah, so like I said, [16:03.890 --> 16:06.870] the virtual host discrepancies is a lot of fun. [16:06.870 --> 16:08.430] We found some really cool, [16:11.790 --> 16:12.970] some really cool targets [16:12.970 --> 16:14.210] that I guess you wouldn't have found [16:14.210 --> 16:17.130] or you wouldn't have known were immediately interesting [16:17.130 --> 16:18.930] just from looking at, [16:18.930 --> 16:20.510] if all you had was just here's the domain [16:20.510 --> 16:22.770] and here's the IP, you know, [16:22.770 --> 16:24.450] you're just looking at a wall of text, right? [16:24.450 --> 16:26.010] Like, what's the interesting targets here? [16:26.010 --> 16:26.850] But if you take, like, [16:26.850 --> 16:28.650] this is one is just one I grabbed out of the database [16:28.650 --> 16:30.550] last night, kind of looking through the database. [16:32.310 --> 16:35.850] You couldn't hit this host by going to the domain [16:36.550 --> 16:38.550] and a local host header wouldn't work, [16:38.550 --> 16:40.610] but if you hit it just by IP, [16:40.610 --> 16:42.250] you could get access to there. [16:42.250 --> 16:43.490] It was an AEM instance [16:43.490 --> 16:45.570] that was like definitely meant to be temporary [16:45.570 --> 16:49.830] and had a lot of things exposed on it. [16:50.130 --> 16:52.350] And stuff like doing this vhost checking [16:52.350 --> 16:55.230] lets us see those really quickly at a glance. [16:55.230 --> 16:57.950] So this is a tool we're actually dropping [16:57.950 --> 16:59.890] at the end of the talk, [16:59.890 --> 17:03.550] but it basically, we give it a target [17:03.550 --> 17:07.130] with an IP address, a domain, and a port, [17:07.130 --> 17:08.910] and it will run these three checks. [17:08.910 --> 17:11.370] So it will test visiting the IP [17:11.370 --> 17:13.590] with the host header as the IP. [17:13.590 --> 17:16.150] We'll do the IP address with the domain as the host name [17:16.150 --> 17:18.270] and then local host as the host header. [17:18.490 --> 17:20.430] And you can see all those side-by-side [17:20.430 --> 17:21.910] and really quickly at a glance, [17:21.910 --> 17:25.550] see what might be different in the outputs there. [17:29.040 --> 17:30.480] Yeah, and I'll let Ben take it away [17:30.480 --> 17:33.340] for some of the cool things we found in the data. [17:34.320 --> 17:37.260] Yeah, so again, there is millions [17:37.260 --> 17:38.660] and millions of IP addresses, right? [17:38.680 --> 17:41.960] There's so much of this that one person [17:41.960 --> 17:43.740] or two people can't go through. [17:43.740 --> 17:48.300] So we wanted to be as fast as we could with exploitation [17:48.300 --> 17:52.620] because from the time we decided to do this talk to today, [17:52.620 --> 17:55.440] we had roughly about maybe two, three months. [17:55.440 --> 17:56.980] So we wanted to do things fast. [17:56.980 --> 17:58.640] We have to do things automated. [17:58.660 --> 18:00.340] We have to make sure we know what we're doing. [18:00.340 --> 18:03.040] And that's kind of why we went after [18:03.040 --> 18:04.580] all these automation things, [18:04.580 --> 18:07.980] getting the response headers and the response code, [18:07.980 --> 18:10.800] looking at them based on the V host and the host header [18:11.350 --> 18:13.480] and kind of seeing all these things that could be weird, [18:13.480 --> 18:16.300] that could lead us into getting a vulnerability, right? [18:17.020 --> 18:20.140] So we need to do a few things first. [18:20.680 --> 18:23.520] We need to decide if we're going to just go after targets [18:23.520 --> 18:26.360] that are huge, like for example, Verizon Media, [18:26.360 --> 18:29.180] or do we want to go after targets [18:29.180 --> 18:31.900] that are vulnerable, [18:31.900 --> 18:34.560] but it's across multiple organizations? [18:34.600 --> 18:36.560] But we'll talk about each of those in a little bit. [18:36.560 --> 18:37.820] So the first thing is, [18:37.820 --> 18:39.740] you want to go after a single target, right? [18:39.800 --> 18:41.900] Cool. What do we know about these targets? [18:41.900 --> 18:43.820] If you watch any of my Sunday streams, [18:43.820 --> 18:46.060] I do a lot of hacking on Yahoo. [18:46.400 --> 18:50.540] I know how they deploy things, what mistakes they make, [18:50.540 --> 18:52.600] where do they make those mistakes, [18:52.600 --> 18:55.500] where their APIs are, where do they document, [18:55.500 --> 18:57.080] where are they storing the documentation, [18:57.080 --> 19:00.340] and also like, where are these internal and corporate hosts? [19:00.340 --> 19:01.480] If you hack on Verizon Media, [19:01.480 --> 19:02.940] you know that corporate.yahoo.com [19:02.940 --> 19:04.980] isn't just the only thing, right? [19:04.980 --> 19:06.340] There's other stuff. [19:06.440 --> 19:09.680] So again, I talked about Verizon Media, [19:11.320 --> 19:14.200] application.waddle and Swagger UI, they're notorious for it. [19:14.200 --> 19:15.560] There's other variation of Swagger [19:15.560 --> 19:17.020] that you can find on there. [19:19.160 --> 19:21.540] Port 4443 is very interesting [19:21.540 --> 19:23.860] because from what I've read on blog posts [19:23.860 --> 19:26.020] and from what I've seen on that port, [19:26.020 --> 19:26.980] it looks like a lot of times [19:26.980 --> 19:30.060] it's meant to be internal or accessible by another app [19:30.060 --> 19:33.360] and not directly visited by the user in the browser. [19:33.360 --> 19:34.980] So you want to really understand your target [19:34.980 --> 19:37.160] and understand what are some of the weird things [19:37.160 --> 19:38.700] about this target that's important [19:38.700 --> 19:41.320] and make sure you fingerprint for those [19:41.320 --> 19:43.820] and look for them actively while you're hacking on it. [19:45.040 --> 19:47.560] The next one is obviously the multiple target thing. [19:47.560 --> 19:48.780] You just want to spray and pray. [19:48.780 --> 19:50.860] You spray whatever vulnerability that you want [19:50.860 --> 19:53.820] across the entire boundary table that we have. [19:53.920 --> 19:56.140] We've set up, when our boundary table went up, [19:56.140 --> 19:58.360] we had a set of targets, including private programs [19:58.360 --> 20:00.140] and public programs that we hacked on. [20:01.740 --> 20:02.740] Excuse me. [20:02.840 --> 20:04.880] But we wanted to go after ones that are quick. [20:04.880 --> 20:06.340] We want to get quick wins. [20:06.340 --> 20:07.440] What's going to get us paid? [20:07.440 --> 20:10.120] What is it going to give us some good examples for this talk? [20:10.500 --> 20:13.660] Again, time was not on our best side. [20:13.660 --> 20:14.900] So we looked at CVEs. [20:14.900 --> 20:16.100] There's a ton of good CVEs [20:16.100 --> 20:18.200] that got dropped in the past three months. [20:18.980 --> 20:21.360] There was a lot of stuff about heap dumps [20:21.360 --> 20:23.860] and memory leaks and stuff that comes [20:23.860 --> 20:25.200] with Spring Boot or Jolokia. [20:25.200 --> 20:27.200] You also want to go after API documentation [20:27.200 --> 20:29.680] because if you have API documentation, [20:29.680 --> 20:30.700] then you're ahead of the game. [20:30.700 --> 20:32.960] You know how the API works, what it expects. [20:33.160 --> 20:36.160] So it gives you a little bit of a boost in your work [20:36.160 --> 20:37.680] when it comes up to fuzzing an API. [20:38.140 --> 20:39.820] And of course, you want to also look for sensitive [20:39.820 --> 20:42.280] or internal tooling or applications [20:42.280 --> 20:44.060] that are not meant to be really publicly accessible [20:44.060 --> 20:49.480] like Jenkins, GitLab, GitHub, Jira, Grafana, you name it. [20:49.480 --> 20:50.860] So you want to make sure you understand [20:50.860 --> 20:53.320] what those sensitive apps or internal toolings are [20:53.320 --> 20:54.840] and then make sure you have a fingerprint for it. [20:54.840 --> 20:56.620] We'll talk about all those in a little bit too. [20:59.040 --> 21:01.300] But again, like I've been mentioning this whole time, [21:01.300 --> 21:03.240] fingerprinting is very, very important. [21:03.480 --> 21:05.200] You have to make sure you know [21:05.200 --> 21:07.360] how to identify these things properly. [21:07.880 --> 21:10.500] So the first thing you want to do is, [21:10.500 --> 21:12.580] first of all, understand what you want to go after. [21:12.580 --> 21:16.980] So for our case, we really heavily focused on API docs [21:16.980 --> 21:20.200] because again, APIs could be huge. [21:20.200 --> 21:21.800] You know, it could be 50 endpoints. [21:21.920 --> 21:23.000] If you know how to use them [21:23.000 --> 21:24.740] because you have the documentation, cool. [21:24.740 --> 21:26.300] It's really fast, really easy. [21:26.300 --> 21:27.880] You just have to go through and fuzz them. [21:28.220 --> 21:29.540] Spring boot stuff, really easy. [21:29.540 --> 21:31.120] If they've left it behind as a heap dump, [21:31.120 --> 21:32.400] you drop the heap dump, [21:32.400 --> 21:34.160] you go through, you pull creds, right? [21:34.160 --> 21:36.740] But you have to understand what makes these things unique. [21:36.760 --> 21:38.420] Is it something in the response header? [21:38.420 --> 21:39.780] Is it something in the response body [21:39.780 --> 21:41.500] when it replies on a response? [21:41.800 --> 21:43.260] Or is it a specific endpoint? [21:43.260 --> 21:43.940] Is it an image? [21:43.940 --> 21:45.340] Is it an API endpoint? [21:45.340 --> 21:48.300] Is it whatever you hit that endpoint, [21:48.300 --> 21:50.720] does it come back with a keyword that explains [21:50.720 --> 21:54.140] or that's obvious in this particular application. [21:54.140 --> 21:55.740] And we'll have examples of all this in a little bit. [21:55.740 --> 21:57.000] So Swagger, for example, [21:57.600 --> 22:01.560] if you're looking for a Swagger doc, like here, [22:02.720 --> 22:04.540] if you hit Swagger resources, [22:04.540 --> 22:07.980] it actually tells you where Swagger is being stored. [22:08.380 --> 22:09.420] You don't have to look for this. [22:09.420 --> 22:10.620] You don't have to brute force for it, [22:10.620 --> 22:12.640] but you can fingerprint for Swagger version [22:12.640 --> 22:14.820] because no matter what the version is, [22:14.820 --> 22:17.220] it's going to have this keyword in there, right? [22:17.580 --> 22:19.800] So you want to use it as a part of your fingerprint [22:19.800 --> 22:21.220] and the response body, [22:21.220 --> 22:24.420] if it has Swagger version on their Swagger resources, [22:24.420 --> 22:25.100] then that's a hit. [22:25.100 --> 22:26.140] That's our fingerprint. [22:27.380 --> 22:30.380] If you find a Swagger slash API docs, [22:30.380 --> 22:31.740] and it's a JSON format, [22:31.740 --> 22:34.160] and it doesn't tell you where you got it, [22:34.160 --> 22:35.180] just brute force for it, [22:35.180 --> 22:36.940] but you're brute forcing for it in mass, [22:36.940 --> 22:38.000] you want to look for base path [22:38.000 --> 22:40.000] because every single Swagger documentation [22:40.000 --> 22:42.200] that is in JSON that I've seen so far, [22:42.200 --> 22:44.000] they all have the base path in there [22:44.000 --> 22:45.160] because you have to tell the user [22:45.160 --> 22:47.360] where the API base path is, right? [22:47.360 --> 22:50.160] That's our main way to fingerprint [22:50.160 --> 22:53.620] for the JSON formatted API docs from Swagger. [22:53.780 --> 22:56.020] And obviously, before people start reporting Swagger [22:56.020 --> 22:57.740] vulnerability about running programs, [22:57.740 --> 22:59.380] Swagger by itself is not a vulnerability [23:00.240 --> 23:01.600] unless it's some internal tool [23:01.600 --> 23:02.660] and the company wants to pay for it. [23:02.660 --> 23:04.260] I never report them by themselves, [23:04.260 --> 23:05.540] but it's really helpful [23:05.540 --> 23:07.620] when you're not playing hide and seek with the API, [23:07.620 --> 23:09.660] where you don't have to brute force for these API routes, [23:09.660 --> 23:11.560] then you don't have to brute force for the parameters, [23:11.560 --> 23:12.400] you don't have to brute force [23:12.400 --> 23:15.140] if it's a put, post, or get request. [23:15.260 --> 23:16.620] So all these things add up, right? [23:17.160 --> 23:18.760] So as long as you have this information, [23:18.760 --> 23:20.660] it's easier to enumerate for it. [23:20.900 --> 23:23.280] We also went off to GraphQL at some point. [23:23.560 --> 23:26.980] What we did here was, if you curl to GraphQL, [23:26.980 --> 23:29.240] you host and you hit the GraphQL, [23:29.240 --> 23:31.960] response is gonna come back as 400 bad requests. [23:32.060 --> 23:33.120] And it's going to tell you, [23:33.120 --> 23:35.240] hey, look, the get query is missing. [23:35.240 --> 23:37.380] Again, this is not the only way to do this, [23:37.380 --> 23:39.380] but it was the easiest and the fastest one. [23:39.480 --> 23:43.120] So as long as the response code is coming back as 400, [23:43.120 --> 23:46.140] and it has the words query missing within the body, [23:46.140 --> 23:47.040] then we knew 100%, [23:47.040 --> 23:49.660] there's at least some sort of GraphQL on there, [23:49.660 --> 23:51.480] which you look for a little bit further. [23:53.280 --> 23:55.420] And of course, if you're going after stuff like Jenkins, [23:55.420 --> 23:57.920] Grafana, Jira, easy to enumerate for them. [23:57.920 --> 24:00.200] There's always an endpoint, there's always a logo, [24:00.200 --> 24:02.120] there's always an API endpoint, [24:02.120 --> 24:03.320] or even better in the headers [24:03.320 --> 24:07.320] or in the text response itself, in the HTTP response, [24:07.320 --> 24:10.540] the keywords are in there, like Grafana and Jenkins. [24:10.820 --> 24:11.680] So make it easy. [24:11.680 --> 24:12.680] This is super simple. [24:12.680 --> 24:15.140] As long as it's Grafana coming back, [24:15.740 --> 24:17.840] it's not case sensitive, [24:17.840 --> 24:20.320] whether if it's, you know, capital G [24:20.320 --> 24:22.400] or not capital G down here, [24:22.400 --> 24:24.100] as long as Grafana is somewhere in there, [24:24.100 --> 24:28.880] in the root directory is redirecting us to log in, [24:28.880 --> 24:31.440] then we know that's also a Grafana instance, right? [24:31.680 --> 24:33.020] Those are things that we, [24:33.020 --> 24:35.280] those are examples of things that we've came up with [24:35.280 --> 24:36.280] as a part of our fingerprints [24:37.200 --> 24:39.180] to make sure we're avoiding [24:39.180 --> 24:41.900] as many false positives as possible. [24:42.620 --> 24:45.620] But again, just because you have these fingerprints [24:45.620 --> 24:47.540] doesn't mean you can identify them properly. [24:47.540 --> 24:49.160] Like you have to have some sort of a tooling. [24:49.160 --> 24:52.620] So eventually we ended up releasing a tool, [24:52.620 --> 24:55.120] which we're gonna talk about later on. [24:55.260 --> 24:57.200] But before all of that, you know, in the beginning, [24:57.200 --> 24:58.240] we didn't have enough tooling. [24:58.240 --> 25:00.740] We were still experimenting with what we wanted to use. [25:00.740 --> 25:03.740] So we started to use this tool called Meg. [25:03.740 --> 25:06.240] Big shout out to Tom, if you're watching this. [25:07.020 --> 25:10.120] Tom nom nom, amazing developer, amazing hacker. [25:10.540 --> 25:12.300] Can't say enough good stuff about this guy. [25:12.340 --> 25:14.980] Check him out on Twitter and go to his GitHub repo. [25:15.520 --> 25:16.420] Look for Meg. [25:16.420 --> 25:20.620] So Meg allows you to spray one or more endpoints. [25:20.620 --> 25:22.140] You can either give it one single endpoint [25:22.140 --> 25:25.200] and tell it to hit a number of hosts, [25:25.200 --> 25:28.260] or you can give it, you can customize those. [25:28.260 --> 25:32.200] So it can be one or more hosts or one or more endpoints. [25:32.760 --> 25:36.920] And the good thing about it is it saves the entire, [25:37.540 --> 25:41.420] it saves a file called index under a folder called out. [25:41.880 --> 25:45.740] And within the out index, it tells you the response code. [25:45.740 --> 25:49.940] So if it's 302, as you can see, 404, 401, 503, 200. [25:49.940 --> 25:51.400] This is very useful, right? [25:51.400 --> 25:56.180] But on top of that, as I also showed in the last screen, [25:56.180 --> 25:58.200] it saves the entire response, [25:58.200 --> 25:59.800] the HTTP response within a folder. [25:59.800 --> 26:03.400] So if you go and do a base on IP, [26:03.400 --> 26:05.200] it would save them in the IP address. [26:05.200 --> 26:07.140] If you do it based on the domain, [26:07.140 --> 26:08.580] they would have a domain in the folder [26:09.920 --> 26:12.140] with everything that came back as a response. [26:12.140 --> 26:15.300] This is very, very useful because we can use this data [26:15.300 --> 26:17.760] to see if our fingerprinting is working. [26:19.480 --> 26:21.960] So before I jump into this, [26:21.960 --> 26:24.380] there is 100% a better way to do this [26:24.380 --> 26:28.380] than doing a crappy one-liner in Bash. [26:28.380 --> 26:29.900] But again, the whole thing is to show [26:29.900 --> 26:34.520] you don't have to be a wizard or a monstrous developer. [26:34.520 --> 26:35.440] You don't have to have a huge developer background [26:35.440 --> 26:36.180] to do this. [26:36.180 --> 26:37.940] As long as you know what you're looking for [26:38.380 --> 26:40.560] and you're not going after millions of targets, [26:40.560 --> 26:42.080] then you could do it with Bash. [26:42.080 --> 26:45.020] And I'll explain how this entire thing works. [26:45.580 --> 26:47.560] So the first thing in that code that I showed [26:47.560 --> 26:50.100] is we grep for the response code from out index. [26:50.100 --> 26:53.980] Remember, out index is where it saves the request [26:53.980 --> 26:56.100] that you sent out and it tells you if it came back as 200 [26:56.100 --> 26:57.700] or if it's not there, right? [26:57.820 --> 27:01.020] So right now I'm greping for anything that came back 200 [27:01.020 --> 27:04.100] in out index, a lot of metrics, right? [27:04.620 --> 27:05.700] In that portion. [27:05.700 --> 27:07.180] Then we feed this to cut and we say, [27:07.180 --> 27:08.960] hey, I want you to cut out everything [27:08.960 --> 27:10.120] after this space right here [27:10.120 --> 27:13.380] because I want to know where this response is stored. [27:13.940 --> 27:16.180] And I want you to store it and make sure it's unique. [27:16.180 --> 27:17.040] And you don't need to do this. [27:17.040 --> 27:18.080] It's just a bad habit of mine [27:18.080 --> 27:20.360] that I always have to make sure I don't have any duplicates. [27:20.700 --> 27:24.340] So now we have the location of every single HTTP response [27:24.340 --> 27:26.680] that came back and make a save for us [27:27.080 --> 27:30.060] that was also 200 for this thing that we were looking for. [27:30.280 --> 27:30.880] Cool. [27:31.120 --> 27:32.740] Now I want to loop through all of these [27:32.740 --> 27:34.940] and we want to read every single one of these files [27:34.940 --> 27:37.720] and check it against our fingerprint. [27:37.820 --> 27:39.680] So we do a quick XARG. [27:39.740 --> 27:41.520] We say for every single one of them, [27:41.520 --> 27:44.800] we want to feed it to grep and we're using the dash H [27:44.800 --> 27:47.500] so it shows a file name for where the fingerprint matches. [27:47.980 --> 27:49.720] And we're doing the dash I [27:49.720 --> 27:51.740] because that's where it ignores case. [27:51.740 --> 27:53.020] So if it's, you know, capital [27:53.020 --> 27:55.780] and we didn't give it a capitalized letter, [27:55.780 --> 27:57.360] it's going to ignore it completely. [27:57.860 --> 28:00.000] And it's going to run the fingerprint. [28:00.000 --> 28:01.580] So example, if we're looking for swagger [28:01.580 --> 28:04.540] within the fingerprint, we'll put swagger resources [28:04.540 --> 28:06.240] or sorry, we'll put swagger version [28:06.780 --> 28:08.920] and it will loop through all of those files and say, [28:08.920 --> 28:10.680] okay, this one has swagger version in it. [28:10.680 --> 28:12.300] This one doesn't, this one does it. [28:12.460 --> 28:13.920] And it keeps on giving it to you. [28:14.120 --> 28:15.060] And then you cut it again [28:15.800 --> 28:20.120] because you want to get the path of the ones that match. [28:20.120 --> 28:22.700] Because again, if we do grep dash H, [28:22.700 --> 28:25.720] it's going to give you the location of the file [28:25.720 --> 28:26.920] and it's going to tell you what line. [28:26.920 --> 28:27.940] So you want to cut that out [28:27.940 --> 28:31.520] and only get the path so you can confirm it manually. [28:31.520 --> 28:34.180] I saved this entire thing under search. [28:34.180 --> 28:36.800] So I have a command called search on my box. [28:36.800 --> 28:39.240] So when I type in search, I give it a response code [28:39.240 --> 28:42.300] and I tell it the fingerprint and it does the whole thing. [28:42.300 --> 28:43.300] So let's look at some examples [28:44.100 --> 28:47.820] of how we use Meg to eliminate false positives. [28:48.460 --> 28:50.960] So as you remember on this slide right here, [28:50.960 --> 28:54.460] I was talking about how if you hit swagger resources, [28:54.460 --> 28:56.020] it will give you swagger version. [28:56.020 --> 28:57.240] That's our fingerprint. [28:57.240 --> 28:58.900] And it's going to come back as 200 obviously [28:58.900 --> 29:00.200] because it exists. [29:00.420 --> 29:02.680] Cool. We have a list of hosts from Netflix [29:03.460 --> 29:06.340] and we're going to hit swagger resources [29:06.340 --> 29:08.220] from every single, onto every single host [29:08.220 --> 29:10.980] that we have found through our resources. [29:10.980 --> 29:12.920] In this case is the database that we had [29:12.920 --> 29:14.560] before we started fingerprinting things. [29:15.000 --> 29:16.380] And that immediately came back [29:16.380 --> 29:18.600] with a ton of IP addresses that matched that fingerprint. [29:18.600 --> 29:20.520] So that every IP address that's on here [29:21.200 --> 29:24.400] has come back as 200 right here. [29:24.400 --> 29:25.820] And it has the word swagger version [29:25.820 --> 29:29.380] and it probably has the location of the API docs in it. [29:29.760 --> 29:32.480] Very useful stuff that just extends the attack service [29:32.480 --> 29:36.040] because now you have a ton of APIs to go after, right? [29:36.600 --> 29:38.020] Same thing with GraphQL. [29:38.020 --> 29:40.620] I want to look for, I want to search for it. [29:40.620 --> 29:43.000] I want it to come back, whatever it has 400 [29:43.000 --> 29:45.680] and tell me if it has the word missing [29:45.680 --> 29:48.040] inside of the response. [29:48.240 --> 29:50.000] And I cut it again just because I want [29:50.000 --> 29:51.260] to just get the IP addresses. [29:51.260 --> 29:52.560] So I'm just telling it, hey, I don't care [29:52.560 --> 29:55.300] about the response that you stored it with Meg. [29:55.620 --> 29:56.800] Just give me the IP addresses [29:56.800 --> 29:58.600] because I'm going to automate some stuff on top of it [29:58.600 --> 30:00.940] and see if I can pull information out of it, for example. [30:02.660 --> 30:04.960] But that doesn't really scale with automation. [30:04.960 --> 30:08.060] And I'll let Tanner talk about the fingerprinting tool [30:08.060 --> 30:10.680] that we wrote and why we did it. [30:12.720 --> 30:16.060] Yeah, so it's kind of that same thing, right? [30:16.060 --> 30:19.080] Where we have all this data and it is, [30:19.080 --> 30:21.340] it's like the command line tools are obviously [30:21.940 --> 30:24.800] bash one-liners work, but not when you're feeding it [30:24.800 --> 30:31.340] some giant couple hundred thousand line file of targets. [30:31.340 --> 30:34.580] So the cool thing we were able to do [30:34.580 --> 30:37.800] with this pipeline that we built [30:37.800 --> 30:41.980] and this kind of framework is that we're able [30:41.980 --> 30:43.260] to take the data from the scans [30:43.260 --> 30:45.640] and kind of pipe it directly to these tools [30:45.640 --> 30:47.620] to run through, right? [30:47.620 --> 30:53.640] So the GoFingerprint kind of wraps up [30:54.420 --> 30:56.820] that whole bash one-liner of like, [30:56.820 --> 30:58.820] I want to take a bunch of targets, [30:58.820 --> 31:02.800] get results from their web requests [31:02.800 --> 31:08.320] and look through them for the things I'm interested in, [31:08.320 --> 31:10.280] right, for the targets that I'm interested in. [31:10.640 --> 31:12.660] And so that's really what this does. [31:13.080 --> 31:15.260] We kind of have it set up internally for us [31:15.260 --> 31:16.980] that when new scans come in, [31:16.980 --> 31:18.140] this is triggered automatically [31:18.140 --> 31:20.760] and kind of enriches that data, like I said, [31:20.760 --> 31:23.420] and all of our records that we keep [31:23.420 --> 31:27.180] are internally tagged with these type of things, right? [31:27.180 --> 31:29.560] So you, and you'll see this on the repo. [31:29.560 --> 31:31.620] I have an entire like fingerprints, [31:31.620 --> 31:36.500] JSON file that you can add to or create your own, right, [31:36.500 --> 31:39.380] for finding your own kind of targets [31:39.380 --> 31:42.060] and fingerprints in the data. [31:44.880 --> 31:47.780] Yeah, and then I don't see what Tanner said. [31:47.780 --> 31:49.640] You want to make sure you keep these fingerprints [31:49.640 --> 31:51.420] as simple as you can. [31:51.420 --> 31:54.400] So you just quickly go through them and you tag stuff. [31:54.720 --> 31:57.180] It's very important to do your fingerprinting quickly [31:57.180 --> 31:58.220] so you can go to your data [31:58.220 --> 32:00.660] and make sure you identify these things [32:01.380 --> 32:03.040] as soon as they're spun up. [32:04.400 --> 32:06.380] Should we talk about some bug bounty examples? [32:07.560 --> 32:08.720] Let's do it. [32:08.920 --> 32:11.880] Cool, so again, please remember that a lot of these [32:11.880 --> 32:14.560] are from bug bounty programs that I've hacked on. [32:15.320 --> 32:17.500] It's heavily redacted, unfortunately. [32:17.940 --> 32:19.940] I'm hoping my redactions have done properly [32:19.940 --> 32:21.980] before I start doing all of these. [32:21.980 --> 32:24.340] And we changed a lot of them [32:24.800 --> 32:27.620] and it's really hard to use real life examples. [32:27.620 --> 32:28.920] I don't blame a lot of these companies [32:28.920 --> 32:30.700] because you don't want to end up at DEF CON [32:30.700 --> 32:31.940] and end up in the news. [32:31.940 --> 32:36.480] But just remember, a lot of these vulns are super simple [32:36.940 --> 32:39.580] but yet have been found in the last three months [32:40.520 --> 32:42.560] and they're very, very low hanging fruit. [32:42.560 --> 32:45.640] And it's just to show if you have the right data, [32:45.640 --> 32:47.520] it doesn't even have to be to the extreme [32:47.520 --> 32:48.760] that we went with this talk. [32:48.760 --> 32:50.300] If you have the right data, [32:50.300 --> 32:52.560] you know how to process it and store it, [32:52.560 --> 32:55.140] then you can find a ton of good and easy bugs with it. [32:56.520 --> 32:58.400] So the first one I'm going to get out of the way [32:58.400 --> 32:59.660] is I have no screenshots. [32:59.660 --> 33:01.320] I couldn't get this approved, unfortunately, [33:01.320 --> 33:02.600] but it was really, really unique [33:02.600 --> 33:06.800] because I've gone the same exact XSS six times in a row, [33:06.800 --> 33:09.120] the same exact payload and exact endpoint [33:09.620 --> 33:11.800] on the same target over and over again [33:11.800 --> 33:13.460] for the past few months. [33:13.460 --> 33:14.840] So how does it look? [33:15.140 --> 33:16.540] So about a year ago, [33:16.540 --> 33:19.060] big shout out to actually Space Raccoon for this one. [33:19.060 --> 33:20.720] If you don't know Space Raccoon, Eugene, [33:20.720 --> 33:23.040] awesome hacker, go follow him on Twitter. [33:23.300 --> 33:25.880] We're collaborating on this private program on HackerOne. [33:26.460 --> 33:27.500] Casually send him a link [33:27.500 --> 33:29.620] and he casually send me back a vuln. [33:29.800 --> 33:31.620] Never thought about it ever again. [33:31.620 --> 33:34.200] Never spoke of it, never looked for it ever again. [33:34.220 --> 33:35.560] But me being me, [33:35.560 --> 33:38.660] I naturally added that endpoint to my word list. [33:38.660 --> 33:39.960] Hey, you never know what's going to happen. [33:39.960 --> 33:41.380] You might use it later on, right? [33:41.600 --> 33:44.100] Well, later on happens, I'm working with Tanner [33:44.700 --> 33:46.700] and we dump another set of data. [33:46.740 --> 33:51.880] And I rediscovered that this demo app.html thing is back up. [33:51.960 --> 33:54.620] And we know this thing, we've already seen it. [33:54.620 --> 33:57.980] So having access to our fingerprinting tool, [33:57.980 --> 34:00.200] I go back to our JSON thing. [34:00.200 --> 34:02.040] We write a fingerprint for this HTML thing. [34:02.040 --> 34:04.360] And we say, hey, if you hit this endpoint, [34:04.360 --> 34:05.900] it comes back as 200. [34:05.940 --> 34:08.960] Check and see if this JavaScript file is being called. [34:08.960 --> 34:11.720] And if it is, then we know there is an XSS in there [34:11.720 --> 34:14.020] because they're not patching the XSS. [34:14.020 --> 34:15.940] They're just removing it every time we find it. [34:16.100 --> 34:17.500] And we just keep monitoring it. [34:17.500 --> 34:19.520] So every time there's a new scan that goes up, [34:19.520 --> 34:21.760] you grab the data, you feed it to the fingerprinting tool [34:21.760 --> 34:25.540] and you look for this particular endpoint on that target. [34:25.700 --> 34:27.800] And if it comes back, you can get a bounty from it. [34:27.800 --> 34:29.360] And I've done this six times so far. [34:29.360 --> 34:31.760] Super easy, super low hanging fruit, [34:31.760 --> 34:34.940] but it just comes down to knowing how to monitor for it. [34:35.640 --> 34:41.280] The next one is, first of all, kudos to RhinoRater, [34:41.280 --> 34:44.680] Justin Garner, for getting the CVE number with LEET9, [34:44.680 --> 34:46.840] as he calls it, 13379. [34:47.500 --> 34:50.200] It's an on-auth SSRF in Grafana. [34:50.620 --> 34:53.400] I'm not talking about the POC at all during this talk. [34:53.400 --> 34:55.200] There is no talks around it at all. [34:55.200 --> 34:58.520] If you're interested in the technical aspects [34:58.520 --> 35:01.740] of this vulnerability, then I highly recommend going [35:01.740 --> 35:06.120] and watching his talk from ActivityCon last weekend. [35:06.120 --> 35:07.480] And he has a blog post out for it. [35:07.480 --> 35:09.620] So definitely check it out if you want to learn [35:09.620 --> 35:12.560] about this phone in particular. [35:13.980 --> 35:18.500] So, this is the fingerprint that we came up with. [35:18.500 --> 35:19.440] We talked about this already. [35:19.440 --> 35:21.660] If you hit root, it 302s to login. [35:21.660 --> 35:23.460] If it has the word Grafana in the response, [35:23.460 --> 35:24.840] then boom, you have it. [35:25.200 --> 35:26.600] But it's not always on 443. [35:26.600 --> 35:29.680] We've also seen it religiously come up on 3000. [35:29.680 --> 35:33.980] And I've also heard Justin say it comes up on 3001 as well. [35:34.160 --> 35:35.460] So you have some fingerprints. [35:36.220 --> 35:37.640] The 3000 thing is cool [35:37.640 --> 35:41.580] because it doesn't have the keyword Grafana in the, [35:41.580 --> 35:44.640] it may be a, you know, most people call it grafana.whatever, [35:44.640 --> 35:46.460] the permutation site.com. [35:46.460 --> 35:49.960] But in a lot of cases in 3000, it could be a wild card, [35:49.960 --> 35:51.720] but you have a higher chance of it being Grafana [35:51.720 --> 35:54.480] because it's on that port than you do on 443, right? [35:54.480 --> 35:56.840] Because tons of people are hosting stuff on 443. [35:58.360 --> 35:59.580] So how does that work? [35:59.580 --> 36:03.840] We pull everything that's on port 443 from Bounding Table. [36:03.840 --> 36:07.020] And again, Bounding Table is what Tan and I have put away [36:07.600 --> 36:10.000] with targets that are valuable to us. [36:10.360 --> 36:12.280] It was just a list of maybe 30 companies [36:12.280 --> 36:16.740] that had a wild card program and were useful to us. [36:16.920 --> 36:17.960] And we shoved them in there [36:17.960 --> 36:19.900] and we're just going through them every week [36:19.900 --> 36:21.640] or every other day almost. [36:22.180 --> 36:24.060] So we pulled everything that has Grafana in it, [36:24.060 --> 36:25.600] everything that's from port 3000. [36:25.680 --> 36:27.980] You hit login on all of them with Meg. [36:28.660 --> 36:31.820] And once you hit it with Meg, you do the same thing. [36:31.820 --> 36:32.920] You have it searched for 200 [36:33.300 --> 36:36.780] and you want to make sure the keyword Grafana comes back. [36:36.780 --> 36:39.240] So you know Grafana is actually on these things. [36:39.260 --> 36:41.680] And this returns all the possible instances. [36:42.160 --> 36:44.120] You can skip the login part. [36:44.120 --> 36:45.760] If you don't care to fingerprint for it, [36:45.760 --> 36:47.240] you can just directly hit the POC [36:47.240 --> 36:50.060] and tell it to fetch the latest endpoint [36:50.660 --> 36:52.240] on the AWS metadata. [36:52.240 --> 36:53.940] And instead of looking for Grafana, [36:53.940 --> 36:57.200] latest replies with user data, metadata, [36:57.200 --> 36:59.360] and I think another folder. [36:59.360 --> 37:00.760] So you can fingerprint to see, okay, [37:00.760 --> 37:05.340] if my work and the response of the POC [37:05.340 --> 37:07.660] have the word meta-data in it, [37:07.660 --> 37:10.720] and it's exploitable, flag it for me and give me the results. [37:11.900 --> 37:13.640] But we didn't need to really do this [37:13.640 --> 37:17.820] because we have already Grafana tagged in our bounded table. [37:17.820 --> 37:20.800] So all we have to do is go back to our database, [37:20.800 --> 37:23.940] type in our regular query and say, [37:23.940 --> 37:25.760] hey, I want you to give me every domain [37:25.760 --> 37:28.000] that was tagged as a potential Grafana. [37:29.080 --> 37:32.000] And we could have either written a workflow for it [37:32.000 --> 37:34.080] where it automatically exports it. [37:34.080 --> 37:34.980] I'm against doing those [37:34.980 --> 37:36.400] because I like to do that part manually [37:36.400 --> 37:38.060] to make sure nothing's going wrong. [37:38.140 --> 37:39.340] You never know if it's a typo, [37:39.340 --> 37:42.580] if there is something wrong in your POC. [37:42.580 --> 37:43.880] I like to do those manually. [37:43.960 --> 37:47.840] So we'd get all those potential vulnerable instances [37:47.840 --> 37:50.120] and do it manually and make sure they're vulnerable. [37:50.300 --> 37:51.960] But again, you can automate it with Meg [37:52.520 --> 37:54.220] or write your own workflow of, [37:54.220 --> 37:57.600] if we diff it, it comes up as Grafana, [37:57.600 --> 37:59.960] hit the POC, if the POC gives you metadata, [37:59.960 --> 38:01.080] cool, it's vulnerable, [38:01.080 --> 38:04.080] send a hook to Slack or Discord and let us know. [38:04.200 --> 38:05.100] But I skip all that. [38:05.100 --> 38:06.240] I like to do it manually. [38:06.420 --> 38:08.300] And that was really easy to do, right? [38:09.480 --> 38:10.620] Again, like I talked about it, [38:10.620 --> 38:12.820] we filter the DB, [38:12.820 --> 38:14.660] it shows all the assets tagged as Asana [38:14.660 --> 38:16.000] and we run it through Meg [38:16.000 --> 38:18.660] and it gave us some really good results. [38:18.760 --> 38:20.880] But what was cool was that we realized [38:20.880 --> 38:24.880] some of these targets weren't really doing this [38:25.540 --> 38:26.680] just in one instance. [38:26.680 --> 38:27.500] There was a lot of them. [38:27.500 --> 38:29.240] This is actually a report that Justin found [38:29.240 --> 38:32.300] and we realized there were, [38:32.300 --> 38:33.960] I want to say 12 other instances [38:33.960 --> 38:37.000] just because we weren't looking at the right domain [38:37.000 --> 38:41.240] and we weren't looking at the right internal domain, [38:41.240 --> 38:41.820] if that makes sense. [38:41.820 --> 38:43.140] I can't talk about the company, unfortunately, [38:43.140 --> 38:45.040] because of how private it is, [38:45.040 --> 38:47.460] but they were fascinated by the fact [38:47.460 --> 38:49.060] that we found so many different IP addresses [38:49.600 --> 38:51.380] that was vulnerable to this thing. [38:51.860 --> 38:53.820] And of course, that wasn't the only company [38:53.820 --> 38:54.960] that was vulnerable to it. [38:54.960 --> 38:56.620] There was a ton more, [38:56.620 --> 39:00.220] but these were just the most recent ones that we had found. [39:01.380 --> 39:03.960] And all of these were bounded at some point, I believe, [39:03.960 --> 39:05.780] something big or something small. [39:06.260 --> 39:08.760] In a lot of cases, smaller because this was a POC [39:08.760 --> 39:11.400] that was about 40, not even 30 days old. [39:11.700 --> 39:14.900] We were just reporting it without the expectation of bounty. [39:15.140 --> 39:16.880] So if they gave us a bounty, [39:16.880 --> 39:20.360] it was just an additional benefit of it. [39:20.500 --> 39:22.940] In a lot of cases, it was more than just one asset. [39:22.940 --> 39:25.560] So we're identifying a list of vulnerable [39:25.560 --> 39:28.460] in that company's infrastructure and sending it to them, [39:28.460 --> 39:31.820] which kind of made things more interesting. [39:32.820 --> 39:34.680] So key takeaways, again, [39:34.680 --> 39:37.300] companies may have the same happening [39:37.300 --> 39:39.620] in multiple instances on other IPs, [39:40.080 --> 39:41.680] but multiple instances doesn't mean [39:41.680 --> 39:43.200] that they're gonna give you multiple bounty. [39:43.200 --> 39:45.740] Believe me, I've dealt with that a number of times, [39:45.740 --> 39:48.600] but multiple instances, sometimes, [39:48.600 --> 39:49.920] or I wanna say in most cases, [39:49.920 --> 39:52.580] it means that you're gonna get a higher reward or bonus, [39:52.580 --> 39:55.260] but also give the teams an appropriate time to patch. [39:56.140 --> 39:58.840] You don't wanna report CV jobs that you wanna go about. [39:58.840 --> 39:59.580] You don't wanna be that person [39:59.580 --> 40:01.080] that reports at the same day. [40:01.080 --> 40:04.400] I get that, it's the security team's job [40:04.400 --> 40:06.900] to fix these things, but it takes time. [40:06.900 --> 40:08.080] It's not overnight. [40:08.560 --> 40:09.940] You gotta let them go through their cycles [40:10.720 --> 40:12.000] and let them patch it. [40:12.000 --> 40:14.260] So if you decide to report it too early and not get money, [40:14.260 --> 40:15.220] don't get upset. [40:15.220 --> 40:16.580] It's a part of the game. [40:16.700 --> 40:20.600] Give them enough time before you start mass paying for these. [40:21.760 --> 40:24.460] So we actually went and also sprayed admin [40:24.460 --> 40:26.320] across the entire bounty table, [40:26.960 --> 40:29.160] just because we wanted to see, hey, [40:29.160 --> 40:31.420] some of these IP addresses are coming back [40:31.420 --> 40:33.360] with core or internal within them, [40:33.360 --> 40:37.080] and they're not supposed to be accessible publicly, [40:37.080 --> 40:37.860] more than likely, right? [40:37.860 --> 40:39.120] Like the domain wouldn't load, [40:39.120 --> 40:42.160] but if we hit it by IP, then it loaded some stuff. [40:42.160 --> 40:43.280] So cool. [40:43.460 --> 40:45.740] Let's run admin and see what comes back. [40:46.400 --> 40:50.580] So again, we did meg, admin, ls of IPs. [40:50.580 --> 40:52.680] We'll search for anything that came back [40:52.680 --> 40:55.680] that had the keyword login in it and was 200. [40:56.040 --> 40:57.620] A lot of them came back, [40:57.620 --> 40:59.980] but we didn't have the time to go through all of them [40:59.980 --> 41:01.060] and brute force for them. [41:01.060 --> 41:02.440] But there was one that particularly [41:02.440 --> 41:04.760] was very, very interesting to us, [41:04.760 --> 41:07.660] which was this thing that redirected admin [41:07.660 --> 41:10.580] to mgmt some folder login. [41:10.760 --> 41:11.920] Cool. All right. [41:11.920 --> 41:14.760] Why are we going from admin to this thing? [41:14.760 --> 41:16.660] This has to be something interesting. [41:16.660 --> 41:17.880] Let's just look at it. [41:18.080 --> 41:19.540] Now, of course, when we go to mgmt, [41:19.540 --> 41:22.180] it has an admin login page, as you can see on the right. [41:23.100 --> 41:23.700] Okay. [41:24.040 --> 41:28.540] And the password for the admin username and password [41:28.540 --> 41:29.820] were admin, admin. [41:30.120 --> 41:31.840] And as you saw the reaction, [41:31.840 --> 41:34.820] it was anytime that I put admin, admin, and it works, [41:34.820 --> 41:37.500] this is probably the most accurate reaction. [41:38.420 --> 41:39.320] But that worked. [41:39.320 --> 41:41.680] It got us logged in, but that's not fun, really. [41:41.680 --> 41:43.940] There's nothing cool about saying, [41:43.940 --> 41:48.220] okay, I found an admin folder, admin, admin worked. [41:49.120 --> 41:51.360] It's cool. It's an easy bug. [41:51.360 --> 41:52.280] It's an easy bounty. [41:52.280 --> 41:54.560] But the bigger question is, [41:55.270 --> 41:57.760] are they doing this in multiple places? [41:57.760 --> 41:59.880] Is this being reused other places? [41:59.880 --> 42:03.220] Are they using this for other applications? [42:03.220 --> 42:04.560] How does this look? [42:04.560 --> 42:05.860] Is this just a single app? [42:05.860 --> 42:07.280] Is it... [42:07.280 --> 42:07.980] Let's look at it. [42:07.980 --> 42:10.880] So the app name is on the left side. [42:10.880 --> 42:13.120] We rename it to XYZ. [42:13.120 --> 42:15.820] The permutation here, it's not really a permutation. [42:16.460 --> 42:19.500] It's the platform where the game is hosted. [42:19.500 --> 42:23.800] So if it's iOS, if it's through Android, [42:23.800 --> 42:26.040] other platforms that you can play this game, [42:26.040 --> 42:27.280] I wish I could disclose this target [42:27.280 --> 42:29.780] is obviously the domain that we can't disclose. [42:29.780 --> 42:31.500] And then the core app is the thing [42:31.500 --> 42:34.760] that they internally call it when you're logged in. [42:34.760 --> 42:35.880] And it wasn't called core app. [42:35.880 --> 42:38.820] It was something very unique to this game [42:38.820 --> 42:40.060] that made you go, [42:40.060 --> 42:41.980] okay, so this endpoint isn't going to come up [42:41.980 --> 42:43.380] on other IP addresses. [42:43.460 --> 42:45.380] But if we find an IP address [42:45.380 --> 42:48.180] that doesn't have a hosting, for example, [42:48.180 --> 42:49.860] within their CIDR, [42:49.860 --> 42:51.560] but it comes back with this folder, [42:51.560 --> 42:53.140] it means it's owned by them [42:53.140 --> 42:54.900] and it's running the same code, right? [42:54.980 --> 42:55.980] Okay, cool. [42:56.240 --> 42:57.820] Now let's go back to our database. [42:57.820 --> 42:59.700] We're going to look for this app name, [42:59.700 --> 43:02.420] you know, the XYZ part right here. [43:02.520 --> 43:03.340] And we're going to say, [43:03.340 --> 43:06.320] put everything that has this XYZ portion. [43:06.700 --> 43:09.160] And I don't care what's before and after it. [43:09.160 --> 43:10.920] As long as that keyword is in the middle [43:11.480 --> 43:12.960] and it has a domain, [43:12.960 --> 43:15.040] I wish I could disclose.com in it. [43:15.100 --> 43:16.260] Give me the results. [43:16.260 --> 43:17.420] And I'm going to split it with Meg [43:18.120 --> 43:19.380] and see how many come back. [43:19.380 --> 43:21.440] So 15 of them came back to be exact. [43:21.640 --> 43:23.340] I think some of them were patched by the time [43:23.340 --> 43:25.400] we're fingerprinting for more of these, [43:25.400 --> 43:27.660] but 12 of them actually allowed us to log in [43:27.660 --> 43:28.820] with admin admin. [43:28.920 --> 43:31.880] And each of them had access to different user data [43:31.880 --> 43:34.120] and PII because we're on different platforms. [43:34.260 --> 43:36.300] But from what I heard from their internal team, [43:36.300 --> 43:38.520] it was roughly about 1 million users [43:38.520 --> 43:39.940] that were using this thing. [43:39.940 --> 43:42.260] And I'm 99% sure there was RCE by design [43:42.260 --> 43:46.000] in some of the links that were in the admin panel. [43:46.360 --> 43:48.400] So again, it was a cool bug, [43:48.400 --> 43:50.760] but you go from one bounty to like, [43:50.760 --> 43:51.740] hey, it's the same bug. [43:51.740 --> 43:53.420] I'm not saying give me multiple bounties, [43:53.420 --> 43:55.420] but there are multiple things that could be affected [43:55.420 --> 43:55.940] by this. [43:55.940 --> 43:57.480] The team investigates this more [43:57.480 --> 43:58.900] and they look into it more. [43:58.900 --> 44:00.760] And you'd usually turn out with a better bounty, [44:00.760 --> 44:01.620] to be honest. [44:04.000 --> 44:07.120] All right, this has to be one of the most insane [44:07.610 --> 44:10.620] and easiest vulns that I've seen in my life. [44:11.380 --> 44:14.820] This is on a megacorp that I know as a fact, [44:14.820 --> 44:16.840] everybody watching this presentation [44:16.840 --> 44:18.580] probably has heard about them. [44:19.120 --> 44:21.280] And you definitely don't know who they are. [44:21.400 --> 44:24.260] But unfortunately, because this just got patched [44:24.260 --> 44:27.220] and fixed just last week, [44:27.220 --> 44:29.240] we didn't have enough time to ask for permission. [44:29.460 --> 44:31.840] So there might be a blog post for this later on. [44:32.040 --> 44:33.600] But let's, before we talk about the bug, [44:33.600 --> 44:34.800] let's talk about a few fingerprints [44:34.800 --> 44:36.220] and things that are valuable. [44:36.220 --> 44:38.460] If you've ever looked at Spring Boot's documentation, [44:38.460 --> 44:40.340] there's a few things that are really interesting about it. [44:40.340 --> 44:43.940] Every endpoint that comes back within Spring Boot, [44:43.940 --> 44:44.740] it's really interesting. [44:44.740 --> 44:46.380] But two of them are really, really interesting [44:46.380 --> 44:48.720] because of the data they give you. [44:48.720 --> 44:50.620] One of them is being the HTTP trace. [44:50.620 --> 44:54.180] It's usually slash HTTP trace or slash trace. [44:54.240 --> 44:57.180] That gives you information about the HTTP request [44:57.180 --> 44:58.600] and the response exchange. [44:58.600 --> 45:00.180] So whatever response you send it [45:00.180 --> 45:02.820] or whatever request you send the server, [45:02.820 --> 45:06.740] it stores it in trace up to like 50 of them, for example. [45:06.780 --> 45:09.880] So if you're brute forcing, it also stores those in trace. [45:09.880 --> 45:11.740] And we'll talk about that in a little bit. [45:12.000 --> 45:13.680] And also the heap dump is obviously, [45:13.680 --> 45:16.160] it gives you a heap dump from the applications JVM. [45:17.420 --> 45:19.460] And according to documentation, [45:19.460 --> 45:24.240] if you hit a Spring Boot application, [45:24.240 --> 45:26.260] it comes back with content type as this. [45:26.260 --> 45:27.920] So if you hit slash trace, [45:27.920 --> 45:30.200] the response is going to have this and the header. [45:30.340 --> 45:32.360] And that's what the documentation tells us. [45:32.360 --> 45:34.400] Cool, let's use this, this fingerprint some stuff [45:34.400 --> 45:35.840] and go after an org. [45:37.200 --> 45:39.280] ZLZ and Zayed, Zayed's going to kill me [45:39.280 --> 45:41.440] for capitalizing the Z in his name, but that's fine. [45:41.440 --> 45:42.980] If you don't know him, follow him on Twitter. [45:43.140 --> 45:46.020] They really, really wanted to hack this megacorp. [45:46.520 --> 45:47.580] They were on a mission. [45:47.580 --> 45:49.060] We have to own this company. [45:49.260 --> 45:50.720] We have to be there internally. [45:50.720 --> 45:52.820] We want to see what this company looks like from the inside. [45:52.820 --> 45:53.440] Okay. [45:53.460 --> 45:55.600] So they dumped every single asset they could find [45:55.600 --> 46:01.200] from all of our resources, beyond our IP scans, [46:01.200 --> 46:03.580] whatever we have, historic data, old data, new data, [46:03.580 --> 46:06.940] whatever we have, we just dump it all into one text file. [46:06.940 --> 46:11.680] We split every single one of them with a slash HTTP trace. [46:11.760 --> 46:15.080] And we look for it and see which ones come back. [46:15.380 --> 46:16.840] So in one of our exchanges, [46:16.840 --> 46:20.820] we saw that we came across the following URL. [46:20.820 --> 46:22.840] Again, XYZ is the app name. [46:22.920 --> 46:24.600] It's just to protect the company. [46:24.620 --> 46:25.720] We don't want to disclose who they are. [46:25.720 --> 46:27.300] So the app name would be pretty obvious, [46:27.300 --> 46:30.740] but it's XYZ-internal-prod. [46:30.740 --> 46:34.220] And it was site.com-actuator-http-trace. [46:34.760 --> 46:37.920] Okay. Well, let's look at it. [46:37.940 --> 46:40.400] When we looked at it, this thing comes up. [46:40.480 --> 46:43.240] You know, this is the information that's being stored. [46:43.240 --> 46:44.780] It's pretty much a timestamp. [46:44.860 --> 46:47.900] What kind of requests it was, what was the URL? [46:47.900 --> 46:49.520] They made the request to all the headers, [46:49.520 --> 46:50.400] including the cookie. [46:50.820 --> 46:52.800] And also they had some other stuff right here, [46:52.800 --> 46:54.640] user agent, blah, blah, blah, right? [46:55.460 --> 46:58.920] But internal-prod-megacorp is what got us attention. [46:59.880 --> 47:02.840] But the cookies that we had in that previous screenshot, [47:02.840 --> 47:05.180] the first set of cookies that we found were not useful. [47:05.180 --> 47:07.540] We couldn't log into that app that we were hacking on, [47:07.540 --> 47:09.840] but we knew if we looked deeper, [47:09.840 --> 47:12.020] maybe because we had the heap dump, [47:12.020 --> 47:14.800] we could probably find better credentials or cookies. [47:14.880 --> 47:18.780] But the one thing that worked out was we understood that, [47:18.780 --> 47:21.660] okay, there's XYZ-internal-prod-site. [47:21.680 --> 47:24.680] Does that mean there's XYZ.site.com? [47:24.680 --> 47:26.480] Is there XYZ-internal? [47:26.480 --> 47:28.120] Is there XYZ-prod? [47:28.120 --> 47:31.120] And it turns out all of these different permutations exist, [47:31.120 --> 47:34.400] and every single one of them have the same exact mistake [47:34.820 --> 47:40.280] of having actuator HTTP trace available to hit. [47:40.460 --> 47:42.880] So naturally we went through one of them, [47:42.880 --> 47:46.720] and we found out that in one of the actual HTTP traces, [47:46.720 --> 47:48.800] there are requests being made to these different things. [47:48.800 --> 47:51.440] And again, these are all renamed, [47:51.440 --> 47:52.900] but there was this thing called core-app. [47:52.900 --> 47:55.860] This is the core-corp, it's the app that we're using. [47:55.860 --> 47:57.560] There's the application, there's viewer, [47:57.560 --> 47:59.720] and there's XYZ-services, where XYZ, again, [47:59.720 --> 48:02.060] is what was in the subdomain name. [48:02.360 --> 48:05.680] So there are four different apps running on this, [48:05.680 --> 48:08.540] and they each have an actuator, [48:08.540 --> 48:12.280] and they each have their own HTTP dump and HTTP trace. [48:12.420 --> 48:13.920] So we dumped them all. [48:14.500 --> 48:16.780] We saved all the results from all of them. [48:16.820 --> 48:18.780] We also saved all the heap dumps, [48:18.780 --> 48:21.200] and we went through every single one of them, [48:21.200 --> 48:22.020] gripping for cookies. [48:22.020 --> 48:25.000] And eventually we found a working session [48:25.000 --> 48:27.580] that actually logged us into the website, [48:27.580 --> 48:30.920] and we loaded them into Burp via match and replace. [48:30.920 --> 48:34.960] And we eventually got access to a lot of internal sites [48:34.960 --> 48:36.820] that we shouldn't have access to. [48:36.960 --> 48:41.120] So, and again, just to explain the whole thing to wrap it up [48:41.120 --> 48:43.220] is we found cookies that didn't work. [48:43.220 --> 48:45.460] We found more instances of this thing being vulnerable [48:45.460 --> 48:48.020] in other places within their network. [48:48.020 --> 48:51.160] One of them actually had working employee credentials. [48:51.160 --> 48:54.920] We plugged them into Burp Authenticator's internal app. [48:55.200 --> 48:57.440] And on accident, when we navigated to other websites, [48:57.440 --> 48:59.720] we realized, you know, it's automatically logging us in [48:59.720 --> 49:01.560] because we had a match and replace set up [49:01.560 --> 49:03.240] that we completely forgot about. [49:03.240 --> 49:05.520] It was to the point that none of us knew how we were logged in [49:05.520 --> 49:08.720] and then we realized ZLZ had a match and replace [49:08.720 --> 49:10.280] that you forgot to take off. [49:10.420 --> 49:12.660] But they gave us access to some really cool stuff. [49:12.660 --> 49:14.840] There was 3,652 people. [49:14.840 --> 49:16.640] I think these are all employees of this company. [49:16.640 --> 49:18.480] We had access to their accounts on this thing. [49:19.320 --> 49:21.200] This had a little bit of a trick [49:21.200 --> 49:24.600] with the path normalization stuff, [49:24.600 --> 49:26.760] but it still gave us access because we had cookies. [49:27.560 --> 49:29.060] This is called my cells comp. [49:29.060 --> 49:29.860] I don't know what it is, [49:29.860 --> 49:32.900] but gave us access to some cell stuff that they did. [49:33.800 --> 49:38.940] This one was redacted, but you can see it says welcome [49:38.940 --> 49:40.800] with the name right here in the top right corner. [49:40.800 --> 49:43.340] I think this thing had some weird functions [49:43.340 --> 49:48.460] when it let us impersonate other users. [49:48.460 --> 49:50.420] We never explored what those users were [49:50.420 --> 49:54.300] because we were already too deep in this company's assets [49:54.300 --> 49:56.900] that we just deleted the cookies, send an email, [49:56.900 --> 49:59.060] apologize for doing this, but we want to show impact [49:59.060 --> 50:00.940] and let them know this is very, very serious [50:00.940 --> 50:02.140] and it should be fixed. [50:03.600 --> 50:05.500] And we learned some lessons from it. [50:05.500 --> 50:08.100] First of all, dig deep. [50:08.100 --> 50:09.680] There's not just cookies, there's credentials [50:09.680 --> 50:10.460] that could be in there. [50:10.460 --> 50:11.420] It could be basics to four. [50:11.420 --> 50:12.380] It could be keys. [50:12.380 --> 50:14.020] It could be authorization headers. [50:14.740 --> 50:16.160] There could be a lot more information there [50:16.160 --> 50:18.280] than what I just explained. [50:18.460 --> 50:21.300] The biggest lesson learned from me is to stop brute forcing [50:22.100 --> 50:24.720] when you have HTTP trace available. [50:25.080 --> 50:27.420] And that's because if you're doing HTTP trace [50:27.420 --> 50:28.680] and you're monitoring it for cookies [50:28.680 --> 50:31.000] and somebody else like me is just sending [50:31.000 --> 50:33.200] like 200,000 requests to find another folder [50:33.200 --> 50:35.900] that's on there, it's gonna mess up someone else's work [50:35.900 --> 50:37.660] while they're monitoring for cookies. [50:38.000 --> 50:40.160] And the Megacorp that we mentioned in here [50:40.160 --> 50:42.260] wasn't the only company that was vulnerable. [50:42.260 --> 50:45.000] So we actually went after the entire bounty table [50:45.000 --> 50:47.540] that we had and we did the same exact thing. [50:48.960 --> 50:50.620] But before I show those examples, [50:50.620 --> 50:52.680] please, please understand like understanding your targets [50:52.680 --> 50:53.900] is very, very important. [50:53.900 --> 50:57.300] If you see one mistake being made on one app, [50:57.300 --> 50:59.140] you get a bit that it's gonna happen again [50:59.140 --> 51:01.300] and again and again within the infrastructure. [51:02.140 --> 51:05.280] So this is a few examples of it. [51:06.120 --> 51:09.080] It was just us throwing a bunch of these IP addresses [51:09.080 --> 51:11.520] and pretty much fingerprinting for it. [51:11.840 --> 51:12.940] Now the good stuff. [51:12.940 --> 51:16.540] I'll let Tanner explain what we're doing next [51:16.540 --> 51:18.320] with all these things that we've talked about. [51:20.820 --> 51:21.900] Awesome, thanks, Ben. [51:21.900 --> 51:25.160] Yeah, it's been a real exciting, to say the least. [51:25.160 --> 51:27.220] It's been an exciting couple of months for sure, [51:27.220 --> 51:29.040] really crawling through this data. [51:29.100 --> 51:30.460] Next slide, please. [51:31.620 --> 51:34.000] Yeah, so these are the two tools [51:34.610 --> 51:36.000] that I mentioned kind of at the start [51:36.000 --> 51:38.860] is GoFingerprint and VhostScan. [51:38.860 --> 51:43.340] So GoFingerprint takes a list of URLs [51:43.900 --> 51:45.280] and the fingerprints. [51:45.280 --> 51:48.320] Jason, there's an example one in the repo. [51:48.320 --> 51:49.880] You can obviously add to it [51:50.880 --> 51:52.960] or take away the ones you think are dumb, [51:52.960 --> 51:54.840] however it kind of suits you. [51:54.880 --> 51:56.060] And up there in the top right [51:56.580 --> 51:58.620] is kind of what the output you'll get back, right? [51:58.620 --> 52:02.800] You'll get the domain that it was on [52:02.800 --> 52:05.060] or the IP, whichever one you're kind of feeding into it, [52:05.060 --> 52:07.860] and then a colon and then whatever it was tagged. [52:07.860 --> 52:11.480] So you'll get back all the positive ID services. [52:12.480 --> 52:14.780] The last one is VhostScan. [52:14.780 --> 52:16.100] So again, like I mentioned before, [52:16.100 --> 52:20.120] so you give it a CSV file with a host name, IP and port. [52:21.500 --> 52:24.500] And right now it doesn't return a JSON file. [52:24.580 --> 52:25.640] It's still kind of a new tool. [52:25.640 --> 52:26.920] I'll be pushing some updates to it, [52:26.920 --> 52:30.000] but right now it just kind of dumps those JSON [52:34.100 --> 52:36.020] paths, basically just JSON objects. [52:36.020 --> 52:37.700] They're just like printed out to the terminal [52:37.700 --> 52:40.500] and you've got the domain, the IP and the port [52:40.500 --> 52:41.460] from what you gave it. [52:41.460 --> 52:44.860] And then it has the status code from hitting it by IP, [52:44.860 --> 52:49.220] the response link by IP, the status code and response [52:49.220 --> 52:51.680] by hitting it with a host header of the domain, [52:51.680 --> 52:53.600] and then the status code and response [52:54.220 --> 52:55.700] of hitting it by local host. [52:55.700 --> 52:58.240] And then a final one called domain accessible, [52:58.240 --> 53:01.220] which will tell you whether or not you can hit this [53:01.220 --> 53:04.340] by its domain, the DNS record. [53:04.420 --> 53:06.940] The point of that was we noticed in the data, [53:06.940 --> 53:09.040] it was kind of a pretty consistent identifier [53:09.040 --> 53:12.260] that if you had a target where you couldn't, [53:12.260 --> 53:14.420] if you try to pull it up by domain, [53:14.420 --> 53:16.620] even though there was a domain name or a C name [53:16.620 --> 53:18.440] in the certificate for the IP, [53:19.260 --> 53:21.920] you couldn't hit it by domain. [53:21.920 --> 53:23.120] You could only hit it by IP. [53:23.120 --> 53:24.780] And typically that ended up netting us [53:24.780 --> 53:26.440] some more interesting targets. [53:26.440 --> 53:28.320] So we put that in there as well as kind of a way [53:28.320 --> 53:33.560] to differentiate them extra wise. [53:34.140 --> 53:35.340] Next please. [53:35.340 --> 53:38.760] This is the goldmine that I think. [53:38.780 --> 53:40.740] We've been excited to share this last slide [53:40.740 --> 53:42.160] for a very long time, [53:42.160 --> 53:45.260] and I'm very excited for Tanner to release this right now. [53:45.580 --> 53:50.080] Yeah, so this is gonna be real fun to watch. [53:50.700 --> 53:52.880] I really hope it stays alive. [53:52.880 --> 53:55.280] I have a hunch that the little micro instance [53:55.280 --> 53:57.520] it's running on is probably gonna die. [53:59.020 --> 54:01.820] Regardless, if you go to api.recon.dev, [54:01.820 --> 54:03.260] search and then domain, [54:04.940 --> 54:08.040] right now it's just a simple, really dumb API. [54:08.040 --> 54:10.060] Just give it a domain you're interested in. [54:10.060 --> 54:11.560] You don't need a period at the end of it, [54:11.560 --> 54:13.860] just the kind of the root domain you're after. [54:14.800 --> 54:16.240] Or really, I mean, you can do multiple, right? [54:16.240 --> 54:17.960] You can do like foo.bar.com. [54:17.960 --> 54:19.580] You just don't need that first period. [54:19.920 --> 54:24.660] And you'll get a JSON array returning the domain, [54:24.660 --> 54:27.000] the raw domain, the raw IP of the target, [54:27.000 --> 54:28.980] and then those two things with their port [54:28.980 --> 54:31.100] they were found on as a full URL. [54:32.080 --> 54:33.660] So it's really dirty. [54:34.700 --> 54:37.620] It's obviously very raw data, but it's super fun. [54:37.620 --> 54:39.180] I think, Ben, you've got it pulled up, right? [54:39.180 --> 54:39.980] We can give like a... [54:40.620 --> 54:42.400] Yeah, I can actually do a demo of it [54:42.400 --> 54:44.760] if I think it's already struggling [54:44.760 --> 54:46.320] with how many people are hitting it. [54:46.420 --> 54:47.300] Oh, probably. [54:47.380 --> 54:50.480] I mean, it's, yeah, I mean, obviously it's... [54:50.480 --> 54:51.880] So I'll show that quickly. [54:51.880 --> 54:54.000] A lot of you know how much I love cert.sh [54:54.000 --> 54:56.480] and I didn't like what they did with it recently. [54:56.480 --> 54:58.400] So we thought we'd do it on our own. [54:58.540 --> 54:59.680] Kind of looks the same almost. [54:59.680 --> 55:01.540] You just have to get the domain out of it. [55:01.540 --> 55:02.480] And then you can use it for OAuth.cloud [55:02.480 --> 55:05.660] because if you hack Verizon Media, you know what's up. [55:06.140 --> 55:08.040] So this is what it looks like [55:08.040 --> 55:10.020] when you would get the data from it. [55:10.780 --> 55:12.240] Yeah, so if you try to hit that [55:12.240 --> 55:15.180] and it takes like four hours to come back, [55:15.180 --> 55:16.000] that's not us. [55:16.000 --> 55:17.680] That's all your other fellow hackers [55:17.680 --> 55:20.420] that are keeping you away from really juicy P1s. [55:20.420 --> 55:24.320] So, you know, if you want the API to stay alive, [55:24.320 --> 55:25.840] you know, coffee goes a long way [55:25.840 --> 55:28.440] to keeping these things running. [55:28.440 --> 55:31.320] And again, we released, we worked on this last night. [55:31.320 --> 55:32.680] So we're going to work on this a little bit more [55:32.680 --> 55:35.060] and make it better as we have more time now. [55:35.060 --> 55:37.360] But we just want to make sure there is something here [55:37.360 --> 55:38.400] for everybody to look at. [55:38.400 --> 55:41.280] And yeah, once this talk is over, [55:41.280 --> 55:43.100] we'll look through it and see where it goes. [55:43.620 --> 55:45.460] But let's quickly, we're almost out of time. [55:45.460 --> 55:46.320] Let's do a conclusion. [55:46.860 --> 55:49.040] First of all, understand your targets as always. [55:49.040 --> 55:50.320] Where do they deploy their new apps? [55:50.320 --> 55:51.420] How do they do it? [55:51.900 --> 55:53.900] Knowing things that, mistakes they make [55:54.280 --> 55:55.720] is very, very important. [55:56.220 --> 55:57.280] Again, familiarize yourself [55:57.280 --> 55:58.820] with things that you see frequently. [55:58.920 --> 56:01.040] If you don't, if you understand how these things work, [56:01.040 --> 56:02.480] it's easier to exploit them. [56:03.260 --> 56:04.360] Fingerprinting becomes easier. [56:04.360 --> 56:05.600] Make sure you have a solid understanding [56:05.600 --> 56:07.580] of the apps and the backends. [56:08.000 --> 56:11.520] And also get a good database of assets you care about [56:11.520 --> 56:12.820] and make sure you keep them updated [56:12.820 --> 56:14.980] and you keep historic data. [56:14.980 --> 56:15.640] And you definitely, again, [56:15.640 --> 56:17.460] you don't have to go to the extreme that we did. [56:17.460 --> 56:20.720] A lot of this data is available on Census and Shodan. [56:21.600 --> 56:22.960] You just have to know how to work them. [56:22.960 --> 56:25.380] We just have the luxury of being able to do this. [56:25.380 --> 56:28.340] And we really want to do some cool research around it. [56:28.340 --> 56:30.880] And that's why we kind of reinvented the whole wheel again. [56:32.160 --> 56:33.960] And again, most of these old tricks, [56:33.960 --> 56:35.120] most of these are old tricks. [56:35.120 --> 56:37.000] Nothing is new that I've talked about, [56:37.000 --> 56:39.420] but it just shows that it still works [56:39.420 --> 56:42.060] against huge megacorps. [56:42.060 --> 56:44.320] You know, an example of the heap dump thing [56:44.320 --> 56:47.780] that I showed you, someone with malicious intent, [56:47.780 --> 56:49.120] that's a goldmine for them, right? [56:49.120 --> 56:50.020] It's easy to pivot. [56:50.020 --> 56:51.320] You already have credentials. [56:51.640 --> 56:52.080] Who knows? [56:52.080 --> 56:53.700] We didn't go and test any of these apps [56:53.700 --> 56:54.640] that we had access to, [56:54.640 --> 56:56.920] but I imagine one or two of them had SSRF [56:56.920 --> 56:58.760] or, you know, RC or something on them [56:59.220 --> 57:01.020] that could have elevator access. [57:01.520 --> 57:03.060] Also, don't just collect assets [57:03.060 --> 57:06.340] and spray random word lists at them. [57:06.340 --> 57:09.460] I mean, there's nothing wrong with doing that, [57:09.460 --> 57:11.500] but the chance of you getting good results [57:11.980 --> 57:14.880] is a lot less with a target that you don't understand [57:14.880 --> 57:17.300] versus a company that you know what folders [57:17.300 --> 57:18.260] and files to look for, [57:18.260 --> 57:20.460] what the naming conventions are, and so on. [57:20.800 --> 57:23.480] And also, again, the wider you go, [57:23.480 --> 57:25.920] the more targets you have to play with. [57:26.000 --> 57:29.060] But again, it all comes down to how you process your data. [57:30.820 --> 57:34.000] And I see a lot of talks about bug bounties on Twitter, [57:34.000 --> 57:36.380] especially every year with DEF CON coming up. [57:36.860 --> 57:39.180] I wanna say that most of these bugs that I've talked about [57:39.180 --> 57:41.300] are found within the last few months, [57:41.300 --> 57:44.720] and there's a good $50,000 worth of bugs in here. [57:44.960 --> 57:46.640] So bug bounties, do they pay? [57:46.640 --> 57:47.520] Absolutely they pay, [57:47.520 --> 57:49.180] but you have to spend extra time [57:49.180 --> 57:51.160] to learn about your target's behaviors, [57:51.160 --> 57:52.920] how do they operate, what do they do? [57:52.920 --> 57:54.920] And you have to find impactful bugs. [57:55.540 --> 57:59.440] To keep that in mind, again, [57:59.440 --> 58:01.880] bug bounties are about impact, not finding vulnerabilities. [58:01.880 --> 58:03.800] So the higher impact you have, the better. [58:03.800 --> 58:07.140] And this was a good case for it. [58:07.520 --> 58:09.820] I don't have a reason why I put this on here. [58:10.120 --> 58:14.020] Obviously the semicolon trick always works. [58:14.080 --> 58:15.240] One of the slides that I showed, [58:15.240 --> 58:17.400] I said the semicolon path normalization stuff, [58:17.400 --> 58:18.480] this is how we did it. [58:18.700 --> 58:20.700] But I also wanted to show how important it is [58:20.700 --> 58:23.380] to incorporate this in your recon. [58:24.560 --> 58:25.860] You can see it from Nafi, [58:25.860 --> 58:27.700] there was a CV that came out not too long ago [58:27.700 --> 58:30.580] on one of the VPN service providers, [58:30.580 --> 58:33.380] and then you can see they're all connected. [58:33.380 --> 58:36.300] Now, of course, if you're not doing this right now in 2020, [58:36.300 --> 58:37.720] you're probably two years behind. [58:38.480 --> 58:40.540] And last but not least, thank you for watching. [58:40.540 --> 58:43.160] Thank you for the Red Team Village for having us. [58:43.280 --> 58:46.640] And of course, thank you to Ziad, ZLZ, Donut, [58:46.640 --> 58:48.920] Tom Nom Nom, Urbysam, and RhinoRider. [58:48.920 --> 58:51.020] And if I forget anybody that helped us [58:51.020 --> 58:52.600] throughout this research, I apologize, [58:52.600 --> 58:54.960] but thank you everybody and thanks for having us. [58:55.400 --> 58:56.920] Thanks guys, it's been great. [58:57.220 --> 59:00.360] Awesome, thank you so much guys, amazing presentation. [59:00.700 --> 59:02.800] Thank you so much for supporting not only DEF CON, [59:02.800 --> 59:04.080] but the Red Team Village as well. [59:04.080 --> 59:04.960] And as a reminder for...