WEBVTT

00:00.000 --> 00:00.700
Hello.

00:01.300 --> 00:07.160
Well, hello and welcome to what is a day, one of Red Team Village at DEF CON.

00:07.560 --> 00:12.180
I'm Ben Sadegopour and I have Tanner Barnes, 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:25.700
And we did some really cool research, but before we jump into it, we're going to do some agenda, intro on who we are, and kind of give you a background 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:32.260
Cool.

00:32.260 --> 00:34.140
I'm trying to see where my notes went.

00:34.220 --> 00:36.600
There we go.

00:36.980 --> 00:51.060
So for agenda for today, we talk about who we are, why we focus so much on the cloud and our solution, and talk about how we mass exploited or look for vulnerabilities and mistakes in mass.

00:51.060 --> 00:59.360
And then we'll also have some really cool examples of things that we accomplished and got some boundaries with in the past few months.

00:59.720 --> 01:02.500
So originally when we, before we get into it, 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:12.320
So this was supposed to be for next DEF CON, but unfortunately things happened 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:19.800
So we're doing a smaller version of this today as a part of DEF CON.

01:19.800 --> 01:24.400
And hopefully next year we can come back with more examples and more in-depth research.

01:24.940 --> 01:28.580
So a quick about me, I'll also let Tanner introduce himself afterwards.

01:28.580 --> 01:31.220
Again, I'm Ben Sadigapour, 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:47.500
And again, you can follow me on all social medias under the name Naham Sec.

01:50.140 --> 01:50.860
Awesome.

01:50.860 --> 01:51.160
Yeah.

01:51.160 --> 01:55.500
So like you said, my name is Tanner Barnes, 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:22.020
And then I've been doing pin testing for Aon Cyber Solutions for like the last year and a half now and I'm an occasional bug hunter, but I help a lot more with some other bug hunters like Ben and some other people I know, 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:31.660
And then I also have just recently started doing some live coding on Twitch as a handler.

02:33.260 --> 02:41.120
Tanner, before we jump into this, I know that DEF CON has this tradition where when you speak at DEF CON, you have to take a shot.

02:41.540 --> 02:45.460
I don't know if you have one ready, 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:57.260
Sorry, I did not, I could have ran downstairs, 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:13.170
Like what's the meaning behind, why did we get into doing all this?

03:13.950 --> 03:18.870
So there's not currently a ton of great solutions for looking at cloud assets, right?

03:18.870 --> 03:22.510
So you've got things like Census and Shodan, 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:29.930
Shodan licenses for their APIs aren't necessarily the cheapest.

03:30.810 --> 03:34.630
And it's definitely worth looking into, right?

03:34.630 --> 03:40.030
And so we wanted to kind of see like, 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:46.150
And the other part is just kind of, who isn't in the cloud these days, right?

03:46.150 --> 03:55.250
Like, I think you're probably hard-pressed to find a large Fortune 500, Fortune 50 company that's not running some part of their infrastructure out in the cloud.

03:55.250 --> 03:57.970
So it's a huge target-rich environment, right?

03:57.970 --> 04:06.110
If you look at just Azure, AWS, GCP, you're looking at something like 88 million IP addresses.

04:06.510 --> 04:13.150
And that's just in their, what I guess I would call like their EC2 space or their compute space, right?

04:13.150 --> 04:23.410
We're not talking about like stuff for Lambda functions, right, that have like pooled up IP addresses, but 88 million IP addresses that could actually be spun up for somebody's instance.

04:24.450 --> 04:33.050
And this is also a big part of where organizations, large ones use to spin up their kind of quick 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:48.410
So if we can get really good coverage and insight into what's happening on the cloud, we can really find some really cool targets and get some really useful data out of it.

04:48.910 --> 04:50.110
Next slide, please.

04:50.790 --> 05:00.030
Yeah, so I mean, this is kind of an example, right, of just some real quick, like dirty, just some quick data that we grab from our database real quick.

05:00.030 --> 05:16.630
So when you're looking at like 1,000 corp domains, 13,000 internal domains, we found that actually very fascinating about how a lot of these domains in the cloud, a lot of their DNS names have stuff like internal corp dev, and it's odd, you would, I guess,

05:16.630 --> 05:19.570
initially I would have thought that you wouldn't see a lot of that.

05:19.570 --> 05:28.590
But yeah, so I think that's cool is that that kind of tells you the type of things companies are putting out there on the cloud and on the edge, right?

05:29.130 --> 05:33.030
And then things like API, a lot of cloud APIs are obvious.

05:33.030 --> 05:43.850
And then if you look at like some specific target options, right, like anything on Yahoo or OAuth, right, you're looking at 100,000, 4,000 targets, right, all out there in the cloud.

05:46.840 --> 05:49.340
Right, so this is my favorite part.

05:49.380 --> 05:57.360
This is when Ben kind of brought this idea to me, I was immediately hooked and I thought it was gonna be a real fun challenge.

05:58.620 --> 06:01.900
So yeah, so we're getting to kind of how it works and what we did.

06:02.220 --> 06:19.480
So it's built in Go, I've been on a huge Go kick, if anybody knows me, or if you look at my GitHub, it's kind of funny, it started out when I really started doing GitHub work, a lot of Java, a lot of, I call last year the year of Java for me, it was a lot of like perf extensions and things like that.

06:19.660 --> 06:25.380
And then I got into writing Golang code and I just got hooked.

06:25.380 --> 06:29.860
So pretty much everything I've built since then has been in Go, it's super great.

06:30.000 --> 06:38.140
Go routines make work like this especially easy, it's incredibly concurrent and it's a language built for concurrency.

06:38.740 --> 06:58.820
So if you look at like, what is the tool that we built do as kind of a core thing, so what we're doing is we're taking IP addresses and we are hitting them on a certain port over TLS and then we're pulling the CNAME and DNS name records out of the certificate it returns and storing that tied to the IP address.

06:58.820 --> 07:05.780
So we're building a huge database of domain names to IP addresses in the cloud.

07:05.780 --> 07:14.360
So kind of unmasking who owns these 88 million IP addresses out in the cloud and to try to differentiate targets from them.

07:14.680 --> 07:20.000
As far as the actual code goes, not really incredibly, there's not a lot of magic there.

07:21.260 --> 07:25.780
Mainly, it was just kind of starting ground 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:34.860
So again, 88 million IP addresses, you're not really gonna be able to hit that 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 --> 08:04.580
So we were looking at about 535,000 slash 24-siders across large Barn Bunny targets and cloud infrastructure, and then across 11 main ports.

08:04.580 --> 08:10.720
So you're looking at about 1.4 billion unique scan targets that we were looking at.

08:11.040 --> 08:18.720
And I just recently, we just created version two of the API and I was able to get it down to a full scan of that space in 15 minutes.

08:18.720 --> 08:29.400
So that comes out to a rate of about 1.6 million unique scan targets a second with 28 to 29 million identified targets across those 11 ports.

08:29.400 --> 08:37.500
And then my favorite thing is that all of that costs 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:50.020
One thing I learned off the bat is do not try this with Lambda.

08:50.020 --> 08:52.820
Lambda seems like a really simple solution to do this.

08:52.860 --> 08:59.580
Turns out they will not let you spin up 535,000 Lambda 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:16.980
So there's definitely been some heavy hitting AWS bills along the way working through this, getting to that mythical $25 bill of scan.

09:17.180 --> 09:25.340
As far as the code goes, when you get to things like this at scale, the quicker you can make the underlying code is obviously super important.

09:25.340 --> 09:42.240
So I had a lot of fun building a really simple solution and then going through with profiling tools that are built into Go to really carve out every wasted piece of memory and wasted CPU cycle to just make it as fast as humanly possible, or I guess as computer possible.

09:42.240 --> 09:48.500
So when I did put it on the scaling solution, it would run quicker on the scaling solution and thus cost us less money.

09:49.540 --> 09:59.600
One part of the funniest lesson we learned from all this is definitely be careful like who you're scanning and what you do with the data you get from the scan.

09:59.600 --> 10:10.440
The cooling about this scanner is it actually is very light on the network of targets because we're actually not making a full TLS HTTPS connection.

10:12.340 --> 10:19.960
It's rare you would actually probably see this on your ingress logs to your server because we're not actually making a full handshake.

10:21.060 --> 10:31.500
What we mistakenly did once was when we had the data, we decided, and we'll get to in a bit, we had a really cool fingerprinting tool that we built and we decided we'd try to go fingerprint our entire database.

10:31.900 --> 10:42.640
We got some very hilarious LinkedIn messages and Twitter DMs from some very worried CISOs who thought we were trying to take over or attack their entire network.

10:42.640 --> 10:48.840
So definitely important with great power comes great responsibility, 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 --> 11:00.500
You can get some really cool insight into what's out there in the cloud, but it's just a start, right?

11:00.500 --> 11:04.220
So we have all this data, but what are we going to do with it, right?

11:04.220 --> 11:09.580
And we kind of hinged and found some really core things that we do with the data, right?

11:09.580 --> 11:24.460
So we have these 28 million hosts that we found across 11 ports, but obviously, XYZ Laundromat's website isn't going to pay us for that sick IDOR 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:46.520
I'm blanking on the guy's name, but it's basically a bug bounty targets, like aggregation list that keeps a wildcard list of wildcard scopes on bug bounty programs.

11:46.520 --> 11:56.420
So we use that as kind of a seed and then some kind of custom ones that we put in there as well to run concurrently with the scan and filter them off into their own database.

11:56.420 --> 12:03.440
So while we have a list of every domain that we found, we have a specific database just for bug bounty targets.

12:03.620 --> 12:09.080
And that helps us kind of filter the data down to then point into some of these other tools.

12:09.560 --> 12:14.120
Another really cool thing that we'll get to is we started diffing scans, right?

12:14.120 --> 12:29.280
So initially we started out just running kind of one a week or one every other week, and we realized we could actually get a lot of coverage and find some even cooler vulnerabilities if we started doing this twice a week and looking at what had changed in between those two days.

12:29.280 --> 12:37.020
So obviously a lot of overlap, but then those really new ones, we realized we were catching those only, but they'd only been in existence a day or two.

12:37.120 --> 12:41.540
And that was really helpful to kind of focus on what we needed to look at first.

12:42.080 --> 12:48.500
Another really cool one is vhost discrepancies or virtual host discrepancies with the host header, right?

12:48.500 --> 12:53.760
So we have all these targets, but again, you're looking at millions of them.

12:53.760 --> 12:56.760
What is kind of a key differentiator 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:05.520
So, and I'll get to that, and we'll come to that later in the slides, but you'll find some hosts in this data.

13:05.520 --> 13:09.780
We found some where you can hit it by IP 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:20.360
And if you hit it by a local host header, or a local host host header, you will get sometimes access to stuff you wouldn't have normally.

13:21.700 --> 13:24.160
And then the final thing was that fingerprinting, right?

13:24.160 --> 13:41.820
So being able to pull like titles, response links, status codes, and take that data and use it to fingerprint specific services would let us key in on large technologies that we knew we wanted to go after, like the Grafana bug that Ben's gonna talk about 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 --> 14:02.790
I'd recommend everybody, if you're starting out with a recon set and you wanna look at like where to start doing recon on, that repo right there is a great guide for sure to get started.

14:02.790 --> 14:06.610
Like I said, you got 1.4 billion targets that creates a lot of noise.

14:06.610 --> 14:17.310
Obviously not all 1.4 billion come back, but out of that 28 million, we really need to kind of filter it down pretty quickly 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:27.630
So being able to filter like that 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:44.000
So like I said, the scan diffing, obviously multiple scans, like I said, they have some overlap, but the kind of the big usefulness there 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:54.600
And those new hosts from Tuesday to Thursday are gonna be really interesting 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:21.580
The way we've kind of been doing it in the past was basically we would run on Tuesday and then on Thursday, on Thursday's scan, we would push Tuesday's off into cold storage, just in a CSV file, flat file, and then we would move Thursday's scan, or we kept two scans of targets,

15:21.580 --> 15:21.740
right?

15:21.740 --> 15:25.120
So Tuesday's would go into, that's what I'm sorry, that's what I was trying to say.

15:25.120 --> 15:33.960
Tuesday's would go into a historical database, and then the previous Thursday would go into cold storage, and then Thursday would be the newest data, and then it would continually shift, right?

15:34.180 --> 15:47.780
So we can always go back if we want to kind of do long-run sentiment analysis of like, not sentiment analysis, we want to do a long-run months analysis of how Verizon spins up domains in the cloud.

15:47.780 --> 15:57.840
We can look at all that historical data and see like, oh, this is how they name their hosts when they're deploying things to the cloud, which can help us in further scans.

16:02.430 --> 16:06.870
So yeah, so like I said, the virtual host discrepancies is a lot of fun.

16:06.870 --> 16:08.430
We found some really cool,

16:11.790 --> 16:24.450
some really cool targets that I guess you wouldn't have found or you wouldn't have known were immediately interesting just from looking at, if all you had was just here's the domain and here's the IP, you know, 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:30.550
But if you take, like, this is one is just one I grabbed out of the database last night, kind of looking through the database.

16:32.310 --> 16:42.250
You couldn't hit this host by going to the domain and a local host header wouldn't work, but if you hit it just by IP, you could get access to there.

16:42.250 --> 16:49.830
It was an AEM instance that was like definitely meant to be temporary and had a lot of things exposed on it.

16:50.130 --> 16:55.230
And stuff like doing this vhost checking lets us see those really quickly at a glance.

16:55.230 --> 17:08.910
So this is a tool we're actually dropping at the end of the talk, but it basically, we give it a target with an IP address, a domain, and a port, and it will run these three checks.

17:08.910 --> 17:13.590
So it will test visiting the IP with the host header as the IP.

17:13.590 --> 17:18.270
We'll do the IP address with the domain as the host name and then local host as the host header.

17:18.490 --> 17:25.550
And you can see all those side-by-side and really quickly at a glance, see what might be different in the outputs there.

17:29.040 --> 17:33.340
Yeah, and I'll let Ben take it away for some of the cool things we found in the data.

17:34.320 --> 17:38.660
Yeah, so again, there is millions and millions of IP addresses, right?

17:38.680 --> 17:43.740
There's so much of this that one person or two people can't go through.

17:43.740 --> 17:55.440
So we wanted to be as fast as we could with exploitation because from the time we decided to do this talk to today, 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:15.660
And that's kind of why we went after all these automation things, getting the response headers and the response code, looking at them based on the V host and the host header and kind of seeing all these things that could be weird, that could lead us into getting a vulnerability,

18:15.660 --> 18:16.300
right?

18:17.020 --> 18:20.140
So we need to do a few things first.

18:20.680 --> 18:34.560
We need to decide if we're going to just go after targets that are huge, like for example, Verizon Media, or do we want to go after targets that are vulnerable, 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:39.740
So the first thing is, you want to go after a single target, right?

18:39.800 --> 18:40.320
Cool.

18:40.320 --> 18:41.900
What do we know about these targets?

18:41.900 --> 18:46.060
If you watch any of my Sunday streams, I do a lot of hacking on Yahoo.

18:46.400 --> 19:00.340
I know how they deploy things, what mistakes they make, where do they make those mistakes, where their APIs are, where do they document, where are they storing the documentation, and also like, where are these internal and corporate hosts?

19:00.340 --> 19:04.980
If you hack on Verizon Media, you know that corporate.yahoo.com isn't just the only thing, right?

19:04.980 --> 19:06.340
There's other stuff.

19:06.440 --> 19:14.200
So again, I talked about Verizon Media, application.waddle and Swagger UI, they're notorious for it.

19:14.200 --> 19:17.020
There's other variation of Swagger that you can find on there.

19:19.160 --> 19:33.360
Port 4443 is very interesting because from what I've read on blog posts and from what I've seen on that port, it looks like a lot of times it's meant to be internal or accessible by another app and not directly visited by the user in the browser.

19:33.360 --> 19:43.820
So you want to really understand your target and understand what are some of the weird things about this target that's important and make sure you fingerprint for those 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:53.820
You spray whatever vulnerability that you want across the entire boundary table that we have.

19:53.920 --> 20:00.140
We've set up, when our boundary table went up, we had a set of targets, including private programs 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:18.200
There's a ton of good CVEs that got dropped in the past three months.

20:18.980 --> 20:25.200
There was a lot of stuff about heap dumps and memory leaks and stuff that comes with Spring Boot or Jolokia.

20:25.200 --> 20:30.700
You also want to go after API documentation because if you have API documentation, 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:37.680
So it gives you a little bit of a boost in your work when it comes up to fuzzing an API.

20:38.140 --> 20:49.480
And of course, you want to also look for sensitive or internal tooling or applications that are not meant to be really publicly accessible like Jenkins, GitLab, GitHub, Jira, Grafana, you name it.

20:49.480 --> 20:54.840
So you want to make sure you understand what those sensitive apps or internal toolings are 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:03.240
But again, like I've been mentioning this whole time, fingerprinting is very, very important.

21:03.480 --> 21:07.360
You have to make sure you know how to identify these things properly.

21:07.880 --> 21:12.580
So the first thing you want to do is, first of all, understand what you want to go after.

21:12.580 --> 21:20.200
So for our case, we really heavily focused on API docs because again, APIs could be huge.

21:20.200 --> 21:21.800
You know, it could be 50 endpoints.

21:21.920 --> 21:24.740
If you know how to use them 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:34.160
If they've left it behind as a heap dump, you drop the heap dump, 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:41.500
Is it something in the response body 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:54.140
Is it whatever you hit that endpoint, does it come back with a keyword that explains 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 --> 22:07.980
So Swagger, for example, if you're looking for a Swagger doc, like here, if you hit Swagger resources, 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:17.220
You don't have to brute force for it, but you can fingerprint for Swagger version because no matter what the version is, it's going to have this keyword in there, right?

22:17.580 --> 22:25.100
So you want to use it as a part of your fingerprint and the response body, if it has Swagger version on their Swagger resources, then that's a hit.

22:25.100 --> 22:26.140
That's our fingerprint.

22:27.380 --> 22:42.200
If you find a Swagger slash API docs, and it's a JSON format, and it doesn't tell you where you got it, just brute force for it, but you're brute forcing for it in mass, you want to look for base path because every single Swagger documentation that is in JSON that I've seen so far,

22:42.200 --> 22:47.360
they all have the base path in there because you have to tell the user where the API base path is, right?

22:47.360 --> 22:53.620
That's our main way to fingerprint for the JSON formatted API docs from Swagger.

22:53.780 --> 23:02.660
And obviously, before people start reporting Swagger vulnerability about running programs, Swagger by itself is not a vulnerability unless it's some internal tool and the company wants to pay for it.

23:02.660 --> 23:13.720
I never report them by themselves, but it's really helpful when you're not playing hide and seek with the API, where you don't have to brute force for these API routes, then you don't have to brute force for the parameters, you don't have to brute force if it's a put,

23:13.720 --> 23:15.140
post, or get request.

23:15.260 --> 23:16.620
So all these things add up, right?

23:17.160 --> 23:20.660
So as long as you have this information, 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:31.960
What we did here was, if you curl to GraphQL, you host and you hit the GraphQL, response is gonna come back as 400 bad requests.

23:32.060 --> 23:35.240
And it's going to tell you, hey, look, the get query is missing.

23:35.240 --> 23:39.380
Again, this is not the only way to do this, but it was the easiest and the fastest one.

23:39.480 --> 23:51.480
So as long as the response code is coming back as 400, and it has the words query missing within the body, then we knew 100%, there's at least some sort of GraphQL on there, which you look for a little bit further.

23:53.280 --> 23:57.920
And of course, if you're going after stuff like Jenkins, Grafana, Jira, easy to enumerate for them.

23:57.920 --> 24:10.540
There's always an endpoint, there's always a logo, there's always an API endpoint, or even better in the headers or in the text response itself, in the HTTP response, 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:30.800
As long as it's Grafana coming back, it's not case sensitive, whether if it's, you know, capital G or not capital G down here, as long as Grafana is somewhere in there, in the root directory is redirecting us to log in, then we know that's also a Grafana instance,

24:30.800 --> 24:31.440
right?

24:31.680 --> 24:41.900
Those are things that we, those are examples of things that we've came up with as a part of our fingerprints to make sure we're avoiding as many false positives as possible.

24:42.620 --> 24:47.540
But again, just because you have these fingerprints 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:55.120
So eventually we ended up releasing a tool, which we're gonna talk about later on.

24:55.260 --> 24:58.240
But before all of that, you know, in the beginning, 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:28.260
You can either give it one single endpoint and tell it to hit a number of hosts, 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:41.420
And the good thing about it is it saves the entire, 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:59.800
But on top of that, as I also showed in the last screen, it saves the entire response, the HTTP response within a folder.

25:59.800 --> 26:05.200
So if you go and do a base on IP, it would save them in the IP address.

26:05.200 --> 26:12.140
If you do it based on the domain, they would have a domain in the folder with everything that came back as a response.

26:12.140 --> 26:17.760
This is very, very useful because we can use this data to see if our fingerprinting is working.

26:19.480 --> 26:28.380
So before I jump into this, there is 100% a better way to do this than doing a crappy one-liner in Bash.

26:28.380 --> 26:34.520
But again, the whole thing is to show you don't have to be a wizard or a monstrous developer.

26:34.520 --> 26:36.180
You don't have to have a huge developer background to do this.

26:36.180 --> 26:42.080
As long as you know what you're looking for and you're not going after millions of targets, 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:50.100
So the first thing in that code that I showed is we grep for the response code from out index.

26:50.100 --> 26:57.700
Remember, out index is where it saves the request that you sent out and it tells you if it came back as 200 or if it's not there, right?

26:57.820 --> 27:04.100
So right now I'm greping for anything that came back 200 in out index, a lot of metrics, right?

27:04.620 --> 27:05.700
In that portion.

27:05.700 --> 27:13.380
Then we feed this to cut and we say, hey, I want you to cut out everything after this space right here 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:20.360
It's just a bad habit of mine that I always have to make sure I don't have any duplicates.

27:20.700 --> 27:30.060
So now we have the location of every single HTTP response that came back and make a save for us that was also 200 for this thing that we were looking for.

27:30.280 --> 27:30.880
Cool.

27:31.120 --> 27:37.720
Now I want to loop through all of these and we want to read every single one of these files and check it against our fingerprint.

27:37.820 --> 27:39.680
So we do a quick XARG.

27:39.740 --> 27:47.500
We say for every single one of them, we want to feed it to grep and we're using the dash H so it shows a file name for where the fingerprint matches.

27:47.980 --> 27:51.740
And we're doing the dash I because that's where it ignores case.

27:51.740 --> 27:57.360
So if it's, you know, capital and we didn't give it a capitalized letter, 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:10.680
So example, if we're looking for swagger within the fingerprint, we'll put swagger resources or sorry, we'll put swagger version and it will loop through all of those files and say, 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:20.120
And then you cut it again because you want to get the path of the ones that match.

28:20.120 --> 28:26.920
Because again, if we do grep dash H, it's going to give you the location of the file and it's going to tell you what line.

28:26.920 --> 28:31.520
So you want to cut that out 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:42.300
So when I type in search, I give it a response code and I tell it the fingerprint and it does the whole thing.

28:42.300 --> 28:47.820
So let's look at some examples of how we use Meg to eliminate false positives.

28:48.460 --> 28:56.020
So as you remember on this slide right here, I was talking about how if you hit swagger resources, it will give you swagger version.

28:56.020 --> 28:57.240
That's our fingerprint.

28:57.240 --> 29:00.200
And it's going to come back as 200 obviously because it exists.

29:00.420 --> 29:01.040
Cool.

29:01.040 --> 29:10.980
We have a list of hosts from Netflix and we're going to hit swagger resources from every single, onto every single host that we have found through our resources.

29:10.980 --> 29:14.560
In this case is the database that we had before we started fingerprinting things.

29:15.000 --> 29:18.600
And that immediately came back with a ton of IP addresses that matched that fingerprint.

29:18.600 --> 29:24.400
So that every IP address that's on here has come back as 200 right here.

29:24.400 --> 29:29.380
And it has the word swagger version and it probably has the location of the API docs in it.

29:29.760 --> 29:36.040
Very useful stuff that just extends the attack service 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:48.040
I want it to come back, whatever it has 400 and tell me if it has the word missing inside of the response.

29:48.240 --> 29:51.260
And I cut it again just because I want to just get the IP addresses.

29:51.260 --> 29:55.300
So I'm just telling it, hey, I don't care about the response that you stored it with Meg.

29:55.620 --> 30:00.940
Just give me the IP addresses because I'm going to automate some stuff on top of it 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:10.680
And I'll let Tanner talk about the fingerprinting tool 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:31.340
Where we have all this data and it is, it's like the command line tools are obviously bash one-liners work, but not when you're feeding it some giant couple hundred thousand line file of targets.

30:31.340 --> 30:47.620
So the cool thing we were able to do with this pipeline that we built and this kind of framework is that we're able to take the data from the scans and kind of pipe it directly to these tools to run through, right?

30:47.620 --> 31:10.280
So the GoFingerprint kind of wraps up that whole bash one-liner of like, I want to take a bunch of targets, get results from their web requests and look through them for the things I'm interested in, 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:27.180
We kind of have it set up internally for us that when new scans come in, this is triggered automatically and kind of enriches that data, like I said, and all of our records that we keep 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:42.060
I have an entire like fingerprints, JSON file that you can add to or create your own, right, for finding your own kind of targets 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:51.420
You want to make sure you keep these fingerprints 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 --> 32:03.040
It's very important to do your fingerprinting quickly so you can go to your data and make sure you identify these things 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:14.560
Cool, so again, please remember that a lot of these 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:21.980
I'm hoping my redactions have done properly before I start doing all of these.

32:21.980 --> 32:27.620
And we changed a lot of them and it's really hard to use real life examples.

32:27.620 --> 32:31.940
I don't blame a lot of these companies because you don't want to end up at DEF CON and end up in the news.

32:31.940 --> 32:42.560
But just remember, a lot of these vulns are super simple but yet have been found in the last three months and they're very, very low hanging fruit.

32:42.560 --> 32:48.760
And it's just to show if you have the right data, it doesn't even have to be to the extreme that we went with this talk.

32:48.760 --> 32:55.140
If you have the right data, you know how to process it and store it, then you can find a ton of good and easy bugs with it.

32:56.520 --> 32:59.660
So the first one I'm going to get out of the way is I have no screenshots.

32:59.660 --> 33:13.460
I couldn't get this approved, unfortunately, but it was really, really unique because I've gone the same exact XSS six times in a row, the same exact payload and exact endpoint on the same target over and over again for the past few months.

33:13.460 --> 33:14.840
So how does it look?

33:15.140 --> 33:19.060
So about a year ago, big shout out to actually Space Raccoon for this one.

33:19.060 --> 33:23.040
If you don't know Space Raccoon, Eugene, 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:29.620
Casually send him a link 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:38.660
But me being me, 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:46.700
Well, later on happens, I'm working with Tanner 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 --> 34:00.200
So having access to our fingerprinting tool, 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:05.900
And we say, hey, if you hit this endpoint, 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:14.020
And if it is, then we know there is an XSS in there 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:25.540
So every time there's a new scan that goes up, you grab the data, you feed it to the fingerprinting tool 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:34.940
Super easy, super low hanging fruit, but it just comes down to knowing how to monitor for it.

34:35.640 --> 34:46.840
The next one is, first of all, kudos to RhinoRater, Justin Garner, for getting the CVE number with LEET9, 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 --> 35:06.120
If you're interested in the technical aspects of this vulnerability, then I highly recommend going 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:12.560
So definitely check it out if you want to learn 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:24.840
If it has the word Grafana in the response, 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:46.460
The 3000 thing is cool because it doesn't have the keyword Grafana in the, it may be a, you know, most people call it grafana.whatever, the permutation site.com.

35:46.460 --> 35:54.480
But in a lot of cases in 3000, it could be a wild card, but you have a higher chance of it being Grafana 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:10.000
And again, Bounding Table is what Tan and I have put away with targets that are valuable to us.

36:10.360 --> 36:16.740
It was just a list of maybe 30 companies that had a wild card program and were useful to us.

36:16.920 --> 36:21.640
And we shoved them in there and we're just going through them every week or every other day almost.

36:22.180 --> 36:25.600
So we pulled everything that has Grafana in it, 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:36.780
You have it searched for 200 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:52.240
If you don't care to fingerprint for it, you can just directly hit the POC and tell it to fetch the latest endpoint on the AWS metadata.

36:52.240 --> 36:59.360
And instead of looking for Grafana, latest replies with user data, metadata, and I think another folder.

36:59.360 --> 37:10.720
So you can fingerprint to see, okay, if my work and the response of the POC have the word meta-data in it, and it's exploitable, flag it for me and give me the results.

37:11.900 --> 37:17.820
But we didn't need to really do this because we have already Grafana tagged in our bounded table.

37:17.820 --> 37:28.000
So all we have to do is go back to our database, type in our regular query and say, hey, I want you to give me every domain that was tagged as a potential Grafana.

37:29.080 --> 37:34.080
And we could have either written a workflow for it where it automatically exports it.

37:34.080 --> 37:38.060
I'm against doing those because I like to do that part manually to make sure nothing's going wrong.

37:38.140 --> 37:42.580
You never know if it's a typo, if there is something wrong in your POC.

37:42.580 --> 37:43.880
I like to do those manually.

37:43.960 --> 37:50.120
So we'd get all those potential vulnerable instances and do it manually and make sure they're vulnerable.

37:50.300 --> 38:04.080
But again, you can automate it with Meg or write your own workflow of, if we diff it, it comes up as Grafana, hit the POC, if the POC gives you metadata, cool, it's vulnerable, 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:18.660
Again, like I talked about it, we filter the DB, it shows all the assets tagged as Asana and we run it through Meg and it gave us some really good results.

38:18.760 --> 38:26.680
But what was cool was that we realized some of these targets weren't really doing this just in one instance.

38:26.680 --> 38:27.500
There was a lot of them.

38:27.500 --> 38:41.820
This is actually a report that Justin found and we realized there were, I want to say 12 other instances just because we weren't looking at the right domain and we weren't looking at the right internal domain, if that makes sense.

38:41.820 --> 38:51.380
I can't talk about the company, unfortunately, because of how private it is, but they were fascinated by the fact that we found so many different IP addresses that was vulnerable to this thing.

38:51.860 --> 38:54.960
And of course, that wasn't the only company that was vulnerable to it.

38:54.960 --> 39:00.220
There was a ton more, but these were just the most recent ones that we had found.

39:01.380 --> 39:05.780
And all of these were bounded at some point, I believe, something big or something small.

39:06.260 --> 39:11.400
In a lot of cases, smaller because this was a POC 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:20.360
So if they gave us a bounty, 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:31.820
So we're identifying a list of vulnerable in that company's infrastructure and sending it to them, which kind of made things more interesting.

39:32.820 --> 39:43.200
So key takeaways, again, companies may have the same happening in multiple instances on other IPs, but multiple instances doesn't mean that they're gonna give you multiple bounty.

39:43.200 --> 39:55.260
Believe me, I've dealt with that a number of times, but multiple instances, sometimes, or I wanna say in most cases, it means that you're gonna get a higher reward or bonus, 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 --> 40:01.080
You don't wanna be that person that reports at the same day.

40:01.080 --> 40:06.900
I get that, it's the security team's job to fix these things, but it takes time.

40:06.900 --> 40:08.080
It's not overnight.

40:08.560 --> 40:12.000
You gotta let them go through their cycles and let them patch it.

40:12.000 --> 40:15.220
So if you decide to report it too early and not get money, 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:37.640
So we actually went and also sprayed admin across the entire bounty table, just because we wanted to see, hey, some of these IP addresses are coming back with core or internal within them, and they're not supposed to be accessible publicly, more than likely,

40:37.640 --> 40:37.860
right?

40:37.860 --> 40:42.160
Like the domain wouldn't load, 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:55.680
We'll search for anything that came back that had the keyword login in it and was 200.

40:56.040 --> 41:01.060
A lot of them came back, but we didn't have the time to go through all of them and brute force for them.

41:01.060 --> 41:10.580
But there was one that particularly was very, very interesting to us, which was this thing that redirected admin to mgmt some folder login.

41:10.760 --> 41:11.400
Cool.

41:11.400 --> 41:11.920
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:22.180
Now, of course, when we go to mgmt, it has an admin login page, as you can see on the right.

41:23.100 --> 41:23.700
Okay.

41:24.040 --> 41:29.820
And the password for the admin username and password were admin, admin.

41:30.120 --> 41:37.500
And as you saw the reaction, it was anytime that I put admin, admin, and it works, 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:48.220
There's nothing cool about saying, okay, I found an admin folder, admin, admin worked.

41:49.120 --> 41:50.160
It's cool.

41:50.160 --> 41:51.360
It's an easy bug.

41:51.360 --> 41:52.280
It's an easy bounty.

41:52.280 --> 41:57.760
But the bigger question is, 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:29.780
So if it's iOS, if it's through Android, other platforms that you can play this game, I wish I could disclose this target is obviously the domain that we can't disclose.

42:29.780 --> 42:34.760
And then the core app is the thing 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:43.380
It was something very unique to this game that made you go, okay, so this endpoint isn't going to come up on other IP addresses.

42:43.460 --> 42:54.900
But if we find an IP address that doesn't have a hosting, for example, within their CIDR, but it comes back with this folder, it means it's owned by them 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 --> 43:02.420
We're going to look for this app name, you know, the XYZ part right here.

43:02.520 --> 43:06.320
And we're going to say, 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:15.040
As long as that keyword is in the middle and it has a domain, I wish I could disclose.com in it.

43:15.100 --> 43:16.260
Give me the results.

43:16.260 --> 43:19.380
And I'm going to split it with Meg 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:28.820
I think some of them were patched by the time we're fingerprinting for more of these, but 12 of them actually allowed us to log in with admin admin.

43:28.920 --> 43:34.120
And each of them had access to different user data and PII because we're on different platforms.

43:34.260 --> 43:39.940
But from what I heard from their internal team, it was roughly about 1 million users that were using this thing.

43:39.940 --> 43:46.000
And I'm 99% sure there was RCE by design in some of the links that were in the admin panel.

43:46.360 --> 43:51.740
So again, it was a cool bug, but you go from one bounty to like, hey, it's the same bug.

43:51.740 --> 43:55.940
I'm not saying give me multiple bounties, but there are multiple things that could be affected by this.

43:55.940 --> 43:58.900
The team investigates this more and they look into it more.

43:58.900 --> 44:01.620
And you'd usually turn out with a better bounty, to be honest.

44:04.000 --> 44:10.620
All right, this has to be one of the most insane and easiest vulns that I've seen in my life.

44:11.380 --> 44:18.580
This is on a megacorp that I know as a fact, everybody watching this presentation probably has heard about them.

44:19.120 --> 44:21.280
And you definitely don't know who they are.

44:21.400 --> 44:29.240
But unfortunately, because this just got patched and fixed just last week, 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:36.220
But let's, before we talk about the bug, let's talk about a few fingerprints and things that are valuable.

44:36.220 --> 44:40.340
If you've ever looked at Spring Boot's documentation, there's a few things that are really interesting about it.

44:40.340 --> 44:44.740
Every endpoint that comes back within Spring Boot, it's really interesting.

44:44.740 --> 44:48.720
But two of them are really, really interesting 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:58.600
That gives you information about the HTTP request and the response exchange.

44:58.600 --> 45:06.740
So whatever response you send it or whatever request you send the server, 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:16.160
And also the heap dump is obviously, it gives you a heap dump from the applications JVM.

45:17.420 --> 45:26.260
And according to documentation, if you hit a Spring Boot application, it comes back with content type as this.

45:26.260 --> 45:30.200
So if you hit slash trace, 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:35.840
Cool, let's use this, this fingerprint some stuff and go after an org.

45:37.200 --> 45:41.440
ZLZ and Zayed, Zayed's going to kill me 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 --> 46:06.940
So they dumped every single asset they could find from all of our resources, beyond our IP scans, whatever we have, historic data, old data, new data, 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:20.820
So in one of our exchanges, 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:30.740
So the app name would be pretty obvious, but it's XYZ-internal-prod.

46:30.740 --> 46:34.220
And it was site.com-actuator-http-trace.

46:34.760 --> 46:35.420
Okay.

46:35.520 --> 46:37.920
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:50.400
They made the request to all the headers, including the cookie.

46:50.820 --> 46:54.640
And also they had some other stuff right here, 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:05.180
But the cookies that we had in that previous screenshot, the first set of cookies that we found were not useful.

47:05.180 --> 47:14.800
We couldn't log into that app that we were hacking on, but we knew if we looked deeper, maybe because we had the heap dump, we could probably find better credentials or cookies.

47:14.880 --> 47:21.660
But the one thing that worked out was we understood that, 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:40.280
And it turns out all of these different permutations exist, and every single one of them have the same exact mistake of having actuator HTTP trace available to hit.

47:40.460 --> 47:48.800
So naturally we went through one of them, and we found out that in one of the actual HTTP traces, there are requests being made to these different things.

47:48.800 --> 47:52.900
And again, these are all renamed, 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 --> 48:02.060
There's the application, there's viewer, and there's XYZ-services, where XYZ, again, is what was in the subdomain name.

48:02.360 --> 48:12.280
So there are four different apps running on this, and they each have an actuator, 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:22.020
We also saved all the heap dumps, and we went through every single one of them, gripping for cookies.

48:22.020 --> 48:30.920
And eventually we found a working session that actually logged us into the website, and we loaded them into Burp via match and replace.

48:30.920 --> 48:36.820
And we eventually got access to a lot of internal sites that we shouldn't have access to.

48:36.960 --> 48:43.220
So, and again, just to explain the whole thing to wrap it up is we found cookies that didn't work.

48:43.220 --> 48:48.020
We found more instances of this thing being vulnerable 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 --> 49:03.240
And on accident, when we navigated to other websites, we realized, you know, it's automatically logging us in because we had a match and replace set up that we completely forgot about.

49:03.240 --> 49:10.280
It was to the point that none of us knew how we were logged in and then we realized ZLZ had a match and replace 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:26.760
This had a little bit of a trick with the path normalization stuff, 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:32.900
I don't know what it is, but gave us access to some cell stuff that they did.

49:33.800 --> 49:40.800
This one was redacted, but you can see it says welcome with the name right here in the top right corner.

49:40.800 --> 49:48.460
I think this thing had some weird functions when it let us impersonate other users.

49:48.460 --> 50:02.140
We never explored what those users were because we were already too deep in this company's assets that we just deleted the cookies, send an email, apologize for doing this, but we want to show impact and let them know this is very, very serious 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:10.460
There's not just cookies, there's credentials 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:18.280
There could be a lot more information there than what I just explained.

50:18.460 --> 50:24.720
The biggest lesson learned from me is to stop brute forcing when you have HTTP trace available.

50:25.080 --> 50:37.660
And that's because if you're doing HTTP trace and you're monitoring it for cookies and somebody else like me is just sending like 200,000 requests to find another folder that's on there, it's gonna mess up someone else's work while they're monitoring for cookies.

50:38.000 --> 50:42.260
And the Megacorp that we mentioned in here wasn't the only company that was vulnerable.

50:42.260 --> 50:47.540
So we actually went after the entire bounty table that we had and we did the same exact thing.

50:48.960 --> 50:53.900
But before I show those examples, please, please understand like understanding your targets is very, very important.

50:53.900 --> 51:01.300
If you see one mistake being made on one app, you get a bit that it's gonna happen again 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:11.520
It was just us throwing a bunch of these IP addresses and pretty much fingerprinting for it.

51:11.840 --> 51:12.940
Now the good stuff.

51:12.940 --> 51:18.320
I'll let Tanner explain what we're doing next 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:29.040
It's been an exciting couple of months for sure, really crawling through this data.

51:29.100 --> 51:30.460
Next slide, please.

51:31.620 --> 51:38.860
Yeah, so these are the two tools that I mentioned kind of at the start is GoFingerprint and VhostScan.

51:38.860 --> 51:45.280
So GoFingerprint takes a list of URLs and the fingerprints.

51:45.280 --> 51:48.320
Jason, there's an example one in the repo.

51:48.320 --> 51:54.840
You can obviously add to it or take away the ones you think are dumb, however it kind of suits you.

51:54.880 --> 51:58.620
And up there in the top right is kind of what the output you'll get back, right?

51:58.620 --> 52:07.860
You'll get the domain that it was on or the IP, whichever one you're kind of feeding into it, 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:20.120
So again, like I mentioned before, 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:30.000
I'll be pushing some updates to it, 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:41.460
They're just like printed out to the terminal and you've got the domain, the IP and the port from what you gave it.

52:41.460 --> 52:55.700
And then it has the status code from hitting it by IP, the response link by IP, the status code and response by hitting it with a host header of the domain, and then the status code and response of hitting it by local host.

52:55.700 --> 53:04.340
And then a final one called domain accessible, which will tell you whether or not you can hit this by its domain, the DNS record.

53:04.420 --> 53:18.440
The point of that was we noticed in the data, it was kind of a pretty consistent identifier that if you had a target where you couldn't, if you try to pull it up by domain, even though there was a domain name or a C name 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:26.440
And typically that ended up netting us some more interesting targets.

53:26.440 --> 53:33.560
So we put that in there as well as kind of a way 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:45.260
We've been excited to share this last slide for a very long time, 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:57.520
I have a hunch that the little micro instance it's running on is probably gonna die.

53:59.020 --> 54:08.040
Regardless, if you go to api.recon.dev, search and then domain, 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:13.860
You don't need a period at the end of it, 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:31.100
And you'll get a JSON array returning the domain, the raw domain, the raw IP of the target, and then those two things with their port 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:46.320
Yeah, I can actually do a demo of it if I think it's already struggling 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:56.480
A lot of you know how much I love cert.sh 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:05.660
And then you can use it for OAuth.cloud because if you hack Verizon Media, you know what's up.

55:06.140 --> 55:10.020
So this is what it looks like when you would get the data from it.

55:10.780 --> 55:16.000
Yeah, so if you try to hit that and it takes like four hours to come back, that's not us.

55:16.000 --> 55:20.420
That's all your other fellow hackers that are keeping you away from really juicy P1s.

55:20.420 --> 55:28.440
So, you know, if you want the API to stay alive, you know, coffee goes a long way 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:35.060
So we're going to work on this a little bit more and make it better as we have more time now.

55:35.060 --> 55:38.400
But we just want to make sure there is something here for everybody to look at.

55:38.400 --> 55:43.100
And yeah, once this talk is over, 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:55.720
Knowing things that, mistakes they make is very, very important.

55:56.220 --> 55:58.820
Again, familiarize yourself with things that you see frequently.

55:58.920 --> 56:02.480
If you don't, if you understand how these things work, it's easier to exploit them.

56:03.260 --> 56:04.360
Fingerprinting becomes easier.

56:04.360 --> 56:07.580
Make sure you have a solid understanding of the apps and the backends.

56:08.000 --> 56:14.980
And also get a good database of assets you care about and make sure you keep them updated and you keep historic data.

56:14.980 --> 56:17.460
And you definitely, again, 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:35.120
And again, most of these old tricks, most of these are old tricks.

56:35.120 --> 56:42.060
Nothing is new that I've talked about, but it just shows that it still works against huge megacorps.

56:42.060 --> 56:49.120
You know, an example of the heap dump thing that I showed you, someone with malicious intent, 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 --> 57:01.020
We didn't go and test any of these apps that we had access to, but I imagine one or two of them had SSRF or, you know, RC or something on them that could have elevator access.

57:01.520 --> 57:06.340
Also, don't just collect assets and spray random word lists at them.

57:06.340 --> 57:20.460
I mean, there's nothing wrong with doing that, but the chance of you getting good results is a lot less with a target that you don't understand versus a company that you know what folders and files to look for, what the naming conventions are, and so on.

57:20.800 --> 57:25.920
And also, again, the wider you go, 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:36.380
And I see a lot of talks about bug bounties on Twitter, especially every year with DEF CON coming up.

57:36.860 --> 57:44.720
I wanna say that most of these bugs that I've talked about are found within the last few months, 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:52.920
Absolutely they pay, but you have to spend extra time to learn about your target's behaviors, how do they operate, what do they do?

57:52.920 --> 57:54.920
And you have to find impactful bugs.

57:55.540 --> 58:01.880
To keep that in mind, again, 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:18.480
One of the slides that I showed, I said the semicolon path normalization stuff, this is how we did it.

58:18.700 --> 58:23.380
But I also wanted to show how important it is to incorporate this in your recon.

58:24.560 --> 58:33.380
You can see it from Nafi, there was a CV that came out not too long ago on one of the VPN service providers, and then you can see they're all connected.

58:33.380 --> 58:37.720
Now, of course, if you're not doing this right now in 2020, 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:48.920
And of course, thank you to Ziad, ZLZ, Donut, Tom Nom Nom, Urbysam, and RhinoRider.

58:48.920 --> 58:54.960
And if I forget anybody that helped us throughout this research, I apologize, 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:04.080
Thank you so much for supporting not only DEF CON, but the Red Team Village as well.

59:04.080 --> 59:04.960
And as a reminder for...

