← All talks

Tim Tomes - Web Application Authorization: Taming the Perfect Storm

BSides Augusta · 202558:18154 viewsPublished 2025-10Watch on YouTube ↗
Speakers
Tags
About this talk
My last 40 web application security assessments have resulted in 41 findings that relate to access control vulnerabilities. That means, on average, every application I test has at least one access control vulnerability. It's no surprise then that Broken Access Control is #1 on OWASP's list of top 10 web application security risks. But what makes access control systems so problematic? To put it plainly, access control systems are hard; hard to design, hard to implement, hard to maintain, and hard to test. This combination creates a perfect storm for privilege escalation in web applications. But only those that understand these systems and how to evaluate them can use the storm to their advantage. In this talk, I aim to equip you with the ability to tame the perfect storm. I'll start by addressing the pitfalls around access control systems in web applications of varying design architectures. I'll then demonstrate the tools and techniques that I use to uncover issues in these systems. Finally, I'll provide some insight into remediating access control issues, and how development teams can automate access control testing as part of a CI/CD pipeline... something that is largely considered to be impossible.
Show transcript [en]

Good afternoon everyone. >> Good afternoon. >> How are you? All right. Uh welcome again for the probably like the sixth or seventh time to Besides Augusta. Um this is one of my favorite places to go. Not just the conference but uh the area. Uh, I think I started I didn't start my cyber security career here, but it took a fairly large jump here when I was at Fort Gordon. I did a lot of stuff at Fort Gordon. I'm at the end of my military career. Um, so this is like a third home for me. It's like my home is in Spartanber, South Carolina. My second home is probably in Northwest Ohio, and this is my my third

home here. So, I enjoy anytime I get a chance to come to Augusta and share some stuff with you. So today we're going to be talking about web application authorization, the perfect storm that it is and how to tame it. Okay. Um this stuff up here, I have a lot to talk about, so I'm not going to spend much time talking about this, but I will say this. I do all of these things for three things. As God glory, God's glory, my joy, and the world's good. All right? So if you want to know anything about that or any of this stuff here, I'm going to hang out. I'll be at the conference the rest of

the day, obviously. Catch me and I can catch you up on any of this stuff here. If you'll notice, I'm not working for myself anymore. I am working for someone else. That's been a big transition for me and it's pretty fun. But any questions about any of that stuff, please catch me for the remain of the conference. I'd be happy to chat with you about it. But today, we're here to talk about these things here. Number one, defining what this perfect storm is. Why do I call it a perfect storm? Okay? And then we'll talk about how to tame it. That's where the majority of this talk is going to take place because that's where we get our hands on the

target and start doing some stuff with it. And then at the end, we'll talk about how to prevent the perfect storm. obviously remediation, prevention, that sort of stuff once we've defined and learned how to attack it. Okay, so the gist of this the the basis for this entire presentation comes from this slide right here. So in the OOS top 10, the top vulnerability in the OAPs top 10 from 2021 and my sources inside of OOPs tell me when the when the 2020 2025 list gets released here in the next two weeks, I think it's happening in the first week of November, broken access controls is probably going to be number one on the list then as well. All right.

I don't I'm not privy to any advanced knowledge, but I just got like the wink wink nod nod sort of thing. And so it's number one on the list and it's for a reason because access controls are the most easily or or missing access controls are the most easily missed vulnerability yet essential to find vulnerabilities. And we'll talk a little bit about why that is, okay? But it's essential to find because quite often when you have a broken access control or a missing access control, that's going to lead to some sort of high severity issue. Not always, but in most cases it is, and then they're easily missed because people and tooling aren't necessarily good at finding them. We're

going to resolve resolve half of that problem here today. But there's going to be nothing we can do about resolving the fact that tools aren't good at finding these things. They lack context. They don't understand the difference between something that belongs to me and something that belongs to you. At least not yet. Maybe with some advancements in AI, we can get to that point, but we aren't there right now. And so I before I joined the on defend my in my new job I went back and I looked at the last 40 assessments that I conducted at practice right the ones that I did personally and across those 40 assessments I reported 41 total access control related

vulnerabilities now I'm not a math genius or anything like that but I think that averages out to about one per assessment. Okay. So, I will tell you this. If you're not finding access control issues during assessments, it's not because they're not there. It's probably because you're missing them. And that's the problem that we're going to try to solve today. So, why are broken broken access controls such a major issue? Why are they so common? Well, the reality is is that access control systems are just hard. Every part of the process is hard. The top three pieces right here, them being hard to de hard to design, hard to implement, and hard to maintain. Has anybody here

ever written an application where they had to design an access control system before? If you have, you know how difficult it can be. Okay, so they're hard to design, hard to implement, hard to maintain, and then for us, they're difficult to test both on the automated tooling side and on the manual analysis side. I've already talked about some reasons why the tools are bad at it, right? They don't know if they if they're accessing a document that belongs to Tim or one that belongs to somebody else. They don't know if they're actually hitting an administrative level um privilege or whether they're accessing something that anybody should be able to get to. They may do that. I have seen scanners

absolutely go places that they weren't supposed to go with the session that I gave it, but it had no idea that it wasn't supposed to be there. So, it didn't know to report it. Okay, it's that human context, that understanding of the business purpose behind the application that's missing. Um, and so tools don't do it well. And then I I have found that general manual testers or just penetration testers in general don't have really good methodologies around that either. And that is what we're going to solve today. So the majority of the talk's going to be right here spent talking about how we tame this storm. Now if you'll notice here at the top part of this little diagram here

are three different phases of the web app testing methodology. These are highle phases, right? mapping is one of those early on phases and you have content discovery and vulnerability discovery which fall in there as well. That's when I would do these individual steps that we're going to talk about but there's basically three steps I go through to find uh access control issues and they incur in these different steps of the methodology. So I'm not going to sit there and do all these in order. We're going to do them in order here in class because we're kind of extracting that process out of a larger process. Okay? But just know that when you're going through and you're exercising the

methodology, this is when these different parts of the methodology is when you would execute these steps. And so there's three main steps here. The first one's going to be identifying the architectural design pattern. The second is going to be discovering all available routes fully resolving the attack surface. And the third one's going to be applying the appropriate technique based on the answers to the first two questions. Okay? Or the or the first two uh steps. So that's the over overarching uh thing that we're going to go through. Let's start off by identifying the architectural design pattern. And this is really important because the architectural design pattern is going to tell you if we if we determine which

design patterns the developer used to create the application, it will point us to where we can go or should go look for authorization issues and give us some ideas about the techniques that we should leverage in order to do so. So that's super important. architectural design pattern tells you a lot about an application in terms of vulnerabilities that can show up there, but authorization is particularly uh is one that it does particularly well. Now, there's a lot of different design patterns that we've seen over the years. We're going to focus in on the most common one that you'll see nowadays, which are which are versions of what we call model view controller, the model view controller design pattern. We're

going to talk about two specific ways that this is applied. And if you go and you do some Google search and you're going to see a lot of stuff about design patterns and you're going to see a lot of different uh versions of this particular here, but this is meant to be a highlevel general explanation of what MVC is and how access controls are affected by this particular design pattern. Okay. So this is the most popular pattern in application development today probably has been for the last 10 to 20 years and it's popular because it separates the application into three different components. Okay, which allows different developers to work on different parts of the app at

the same time without conflicting with one another. And those three different components are the model, the view and the controller MVC, right? The model is the internal representation of the data. So it's how the data is modeled. Okay? The view is the user interface, how people interact with that particular application. And then the controller is where all the business logic is handled. It's where the request gets routed and sent out to where it actually the actual business logic gets executed based on what that particular request is trying to do. So you have your model and your view and your controller. And some of the some of the older patterns, right, they just do all of this in a single

file. But this is where it's all done separately. So you can have developers specializing in in maybe model development, developers specializing in view development. You've heard called front-end developers, right? And then back-end developers that mostly focus on the controller level stuff. And so you have you can specialize in different skills and that has impacts on developer turnover and just a whole there's a whole lot of advantages that go along with that. That's one of the slides I had to cut out of here for time is all the advantages and disadvantages. But this is the way that things are being done now. Okay. And there's two different versions of this that I want to go into. And the first one is going

to be server side rendered MVC. Okay. So let's talk about through this process first. What's happening here? The client, the browser, okay, is making a request to the application on the back end. You can see that dotted line right there would be where our interception proxy is sitting. That would be the the threshold between the client side and the server side. And so there's typically this thing called a router which basically takes the URL and figures out which function it's that's supposed to process the request that was just made by the client. Okay, that's what the router does. It's basically just a mapping of oh I see a URL. It says that this function is supposed to

process it. Let me call the function and pass it the request. It's fairly simple there. So that's the first thing that it does. And then you see the three components that we talked about. So the controller is going to be the function that that does what the request asks it to do. Now while the controller is executing, it may or may not interact with the model layer. Okay, if it needs to get access from the database, it's probably going to interact with that model part of MVC. Once all that business log logic is executed at some point in time, it's going to be like, okay, I'm done doing the thing I need to do. I'm ready to present the next user

interface back to the client. So it passes it off to the view. The view then generates the HTML and sends it back to the client. Okay, so those three individual components you see over there, the model view and controller. Now there's three different sets of developers and this has an impact on access control because access control needs to be implemented in at least two of those places. All right, you've got the controller because I need to make sure the person that just made the request is supposed to be able to execute the business logic they're trying to execute. So that's one place. The second place that's mandatory is in the view because the view developer's

got to make sure they're showing the person the right interface, right? I don't want to send a bunch of administrative controls in a UI to a basic user that's only supposed to be able to see information. So, you have to check check access controls at the controller level. You got to do it at the view level. And then if you're accessing different objects within the database, you may have to do it there as well at the model layer. That's not an every request instance, but the other two are, right? because I'm always going to be doing some sort of business logic and responding with some sort of user interface element. So those two things have to be done. But a minimum of two

places that access controls need to be done. And different things happen if one has it and the other one doesn't. There's a weird behavior that can happen there. These become what we call trust boundaries within the application. Developers working with different parts and making assumptions about what other developers are doing. Now as a tester, the only input I have into this process right here is the request, right? Everything else is on the server side. I don't have any ability to control any of that. So if I want to test whether or not the controller is implementing an access control but the view is not, I really can only impact that by which session that I send in. Right? If I want

to if I want to determine whether or not the model is applying access control to the particular object that I want to access, well the only input I'm going to have is probably some sort of direct object reference parameter or something in the request. So I have very limited impact on that process because everything's happening inside the black box on the server side that I don't have access to. All right. So that's generally that's serverside MVC and the impact that that has on access control. Big thing to note here is just knowing that it has to be done in at least two places potentially three and those developers make assumptions about each other and we'll explore that a little

bit further. Then we have client side rendered model view controller and it's very similar right we still have the client the client sending the request to the router the router routing it to the controller where the business logic processes the request and does it or where the controller processes the request and does the business logic it might interact with the model and at some point in time it says ready to present a view and it sends the requiring information over to the view but the view is in a completely different place now isn't it the view is now on the client and this is interesting Right? Because when everything was happening on the server side, the view developer

had direct access to who the current user was logged in and it could be trusted because it's something that's being maintained by the server, right? Well, that's not happening here anymore. So, in client side rendered MVC, what has to happen is when a user is authenticated to the application, at some point in time, that controller has to go tell the view, by the way, you're this person right now. You're logged in as a basic user. you're logged in as an administrator. This is the interface that you should draw or should create or should build for the current user. That information is still managed on the server, but it has to be communicated to the client where the view is actually

being built. And guess who has access to that particular communication? That exchange. We do. The user does, whoever owns the client, the tester, the attacker. So this is going to give us some interesting control over what the user sees with the interface in terms of their privilege level and that gives us some additional opportunities for testing for access control issues. Okay. And we'll explore that a little bit further as we go through the other two steps as well. So this be this would be the equivalent of a spa single page application. We've heard that term before. That's what a client side rendered MVC is is basically a single page application. That's another term we use for that. And then serverside NVC is

basically every other app we test. So we'll put it that way. Like a multi-page application if you want to call it that. So the second step here once we've we've determined the design pattern. Okay. The second step is going to be discovering all available routes because we can't test for access controls in something that we don't know exists. So we need to so the goal in this particular step here is to fully resolve the attack surface as much as we can. Okay? Because only when we know as much as we can about the attack surface can then we go test the attack surface to see if it's missing any access controls. And there's a couple of different steps too here. I

think there's basically three substeps to each of these other parts of the methodology. So the first one is just using credentials. This is the most common one. Everybody probably understands what what I'm talking about when I say this. The simplest simplest method, right? Problem is it's not practical for all testing types, right? If you're doing a um a timebound pen test or something in crystal box or something like that, then maybe you've got credentials, right? Maybe during the scoping process, you ask for credentials and you have them. The whole idea is you take all the credentials that you have, you log in and you fully map the attack surface for every role associated with every credential you've been given.

Pretty straightforward, right? This is exactly what I did here for the demo project that we're going to be using is is what I I created an ad user account, mapped it, was given an admin account, mapped it, so that we have a fully resolved attack surface. If you can do it that way, awesome. Simplest, easiest, probably the quickest way to go about resolving. But it's not our only option because there are other cases if you're doing like a full-on red team, right? Or a full scope of or a a true pentest where you don't have a bunch of extra information, then you're not may not have that luxury. You may not be able to just create your own account or be given

one. there's going to have to be some other way that you go about discovering these routes. Okay, so that's what these other two techniques or approaches are for. Okay, so the first one here, this is unique to clientside rendered applications, right? This is one one of the reasons why it's important to know the design pattern we're looking at is the cool thing about a client side rendered application is all the routes to the server side are probably sitting in the source code, right? Once you pull all that JavaScript over that the client uses to build the various interfaces, well, if the server says, "Hey, you're now an admin," all that code's got to be in the client side to build the

administrator interface, which is going to include all of those API calls to the back end for the that support the administrator functionality because all this stuff is there. We just got to go find it. So, I got some different approaches that I take here. Um, the first one's going to be finding the client side route information. This requires some some knowledge of the framework and use. So you'll need to fingerprint the technology that's being used. If it's like React, is it using Vue? Is it using Angular or something else? Have a little bit of knowledge about how that manages its internal state, right? And how it manages its routing if it's client side routing information. Because when you're in a

single page application, the URL still changes and moves around, but all that information is basically being handled on the client side based on a client side routing table. Well, you find that routing table. you start tracing those routes down into the individual components that do the stuff and those components will have the API requests in them and that's how you can use that information to find your way to the serverside API calls. Another way to do it which is which is probably a little bit easier if you don't have a thorough understanding of the framework that's being used is just search for the calls themselves. Okay, so fetch is an internal JavaScript library very common

way to make serverside API calls. You just search for the fetch function, right? Axios is a very common library for making API calls from a front end. So just search for usage of the Axios library. Axios dot. Now Axios itself right also happens to names it its methods like post and get.put anddelete where fetch is usually just pass in like another variable inside of the function. But you can search for those methods. So search forpost parenthesis get parenthesis and you're just doing all of that inside of your interception proxy inside your browser wherever you have that client side code. And to quickly demonstrate that for you if I go over here and this is my BERT project. Like I

said I set it up by mapping the entire applica both of our test applications. Um if I go to the test.onhub.com which is our single page application and I rightclick and I go to engagement tools and search it. If I search for like fetch open parenthesis and I'll restrict it to scope and I'm only looking inside of my response body because that's where that stuff's going to be in the response body. I see here that I I' it's I've got a hit here and it's this thing called fetchwrapper.js. So if I go in here and I click on this and start to look at the code, let's look at the response here is fetch. So as I see a response await for

fetch. So it's waiting for fetch. So fetch's being called by something else. It's being called by this function called request. And this function by um called request is being used by something called fetch wrapper. Okay. So it's basically wrapping wrapping wrapping this fetch. It's kind of abstracting it out and creating their own little request API here. So I have this thing called fetch wrapper. And that's kind of the root of this. Well, now let's go look for this thing called fetch wrapper because that's probably going to lead me to the next step. Get rid of the parenthesis there. And I see some stuff here. Sure, it's going to show me f fetch wrapper again, but now I have this services API.js,

which imports that fetch wrapper on the client side. And then if I look down through here, you'll see all of the API calls. So for access token interactions, I have a post request and a delete request to whatever this base URL is, which I would be able to once again search the client side codebase for that and find that. It's going to be hardcoded in there somewhere most likely. And I see all different endpoints, all their expected inputs, whether and their methods. I could now have just by looking through this API file right here, AP.js, have resolved all the server side endpoints that I would need for that particular applications. all the ones that I'm that

all the ones that the developer intended to expose, right? That doesn't mean there aren't some hidden ones that aren't necessarily being leveraged by the front end, right? But this is a way to do that. So you can look for the library itself. You can look for the message method calls. Like if I had searched for delete open parenthesis, I would have found it as well, right? So just a couple different methods that you can take to find this stuff. And if you don't like looking at client side code, just say, you know what, I don't do code. Then just there are tools that do it for you. Okay? Look for anything that looks like a URL. You could just grab a

regular expression off the internet or something or have AI build a regular expression for you, throw it in here, look through all your serverside code that way or use an extension like linkfinderj orjs linkfinder which basically does that for you. It's basically a passive analyzer extension runs inside Burp, looks at all the responses, find anything that resembles a URL and just adds them to a log file for you. So you can quickly go through. Now you're going to have a lot of false positives to weed through if you use an extension like that, but if you don't like looking at code, that's an alternative, right? So that's some ways you can leverage client side code

analysis to resolve the attack surface. And then the final way to do it if not if you don't if those other two aren't an option is going to be fuzzing. Right? I would imagine all of us here have done something to this effect before if we've done a web app pen test. So you probably heard of tools like Durbuster, Derby, go buster, fuff, right? These are all fuzzing tools that are some of them are singlepurpose designed for finding web web URLs and stuff like that. Others are more configurable fuzzers, but there's actually one built into Burpuite Pro that already does the same thing all of these other tools do except has some additional advantages and it's called

discover content. Has anybody here ever heard of discover content before? Okay, got a couple of hands. Well, if you're using one of these other tools and you're like me and you're OCD and you'd rather everything just be in one spot, like discover content is a really good way to go about doing that. It's basically the same logic that exists in these tools, but it's built right into Burp. And I'll show you where that's at. So, I'm going close the search and let's say that we're uh was it discover content? It's an engagement tool. So, you can right click on any of the targets and go to engagement tool and there's discover content. Okay. Now the this is where you would

start it and have it run and of course it's going to populate its own site map but it's very very configurable and I could go through and line by line and talk about all this but I'm not I'm going to spare you that for now. I imagine there's lots of YouTube videos that would do that but it's exactly what you think it would do. You can use custom word lists, right? You can fuzz files, you can file directories, you can fuzz files and directories. You can make it recurse. You can do all kinds of stuff with it as far as file extensions go. testing for file stems, even without extensions, which would be necessary for

something like an MVC application, which doesn't typically end with like ap.jsp or something like that. But some of the other benefits that this gives you is because it's already inside of Burp, it can actually take all of its findings and go ahead and add it to your site map. Because if you use one of those external tools, you always have to figure out a way to get it back into your Burp target sitemap. Well, now you don't have to do that. It's automatically going to be there because it's built into the tool. But it can also take all of the words that are in the application that you've already discovered up to this point and use

those again in the word list which makes sense. Developers might reuse their words, their directories, their file names or so on and so forth in multiple places. So this this handles that for you as well. It also does some intelligent guessing like if it sees a particular pattern being used for a directory or a file name, it will try variations of the pattern whether it be like you know spring 1999, spring 1998, fall 1999. There's no there's no clear documentation on which algorithms exist within Burpsweet Pro to do that, but that's there and it's another handy tool. So, if you didn't know that discover content existed, highly encourage you to take a look at it. Now,

one thing to be aware of is recursion logic. Okay? Because all of these tools, everyone listed on here, including discover content, which is Burp's tool, they only they're all they were all built on the premise that applications are hierarchical. Because if you think about old school web apps, they're hosted on a file system. And you can't have a file at three layers deep without having a directory at layer two and layer one, right? It's all hierarchical and builds from that. These tools assume that, which means that if you've got a resource sitting three layers deep in the in the URL path that and there's no layer two or layer one beneath it, this tool is not going to find it. It

will not recurse to the second level unless it finds something at the first level because it believes everything is hierarchical. Well, it's taking a step back when I was talking about NVC and how there's these routers that map URLs to to to controllers. Those URLs are completely custom. A developer can make a URL look however they want. It could be seven layers deep without anything being at layer 1 through six and that's a valid resources according to their routing table, but it would not be a valid resource according to these tools. So, keep that in mind. If you're dealing with an MVC application, fuzzing with these tools, no matter which one you use, is not going to recurse the way

that you think it might. So, you're going to have to use something else. Perhaps intruder is an option there. Intruder is Burp's fuzzing tool. It's not going to intelligently handle all this for you. You're going to have to do all the configuration to set it up to fuzz this way. But you with with something like intruder or even turbo intruder, you would be able to do a more uh a more aggressive true brute force fuzz, which would go to further directory depths. Now, I caution if you're going to do that, don't use a big word list because you'll sit there quite literally for years. Okay, so make sure that you just be mindful about what

you're trying to get the tool to do, understanding the application enough to know whether or not the tool is even going to be effective. And then the word list that you use for this are huge. You don't want to use like the Rockyu password list to try to brute force directory and file names. Okay, so there's two different methods I've I've really enjoyed that were used to build word lists. The SPN digger and the Git Digger word lists. They were built by someone crawling open source code repositories both on Git and SVN right those there's Google cloud there's or so old Google code GitHub Bitbucket a lot of others they crawled open source code repositories harvested directory and

file names created a list out of them all right that's pretty reliable the other ones here robots disallowed and raft they basically pulled down the x number of the top Alexa 1 million websites took out the robots.txt txt files, separated out all the files and directories from within those uh robots.txt directives and created word list out of those. Right? Two really good methods for building word lists for this type of fuzzing. And just know that those resources are out there because it's only going to be as good as your word list, right? If you garbage in, garbage out, right? When it comes to the word list for this type of searching. All right. So, now that we've at this

point in time, you've done just about all you can do to resolve the full attack surface. All right. So, we've looked at the architectural design pattern. We've resolved as much of the attack surfaces as we can. Now, we want to try to go apply the appropriate technique to figuring out whether or not these resources we discover are properly applying the access controls. Now, there's a couple different methods for this as well. The first one here is manual brute forcing. Don't do this. Okay? We've probably all done this at some point in our career if you're doing web app testing. It is not necessarily not anymore. We have tooling that we can use that make our lives much

easier. But the manual force browsing, the concept of that is literally going in and trying to take a another session that shouldn't have access to a resource and literally try to go to it. For a get request, that's pretty easy, right? We copy it, paste it in the URL, hit the send button, see if it goes through. But when we're dealing with get oh a post request and puts and deletes and things like that. Well, now we're going to need to use our interception proxy. Send it over to repeater. Change the session cookie or the token or whatever it might be. Hit send. See what happens. And it's a long process, way, way more manual

than it needs to be. Okay. Now, the process of of of forced browsing is going to be how we do it. We're just not going to do it ourselves. So, don't do this. Okay. This would be slow um slow and inefficient. So it's there, but I recommend you not do that. This technique here, right, UI privilege escalation is this is only valid for client side rendered applications. And this is going to feel like a vulnerability. Okay, I've had developers come up to me after this talk and go, "Oh my gosh, I didn't realize that that actually was a thing." This is not a vulnerability. This is simply how single page and client side rendered applications work. But remember I said

when I was going over the diagram at some point in time the backend has to tell the front end who's logged in right now. And when it does we have control over that process. This is inherent to single page applications to client side rendered applications. We're always going to have this bit of control. And our goal here is to say we're an admin right or we are somebody that we should not have access to the rights that they have on the server. So the goal is to get the user interface to prevent a bunch of feature sets that we should not have access to and then test and see if those feature sets are actually

accessible to us even though they shouldn't be. Now there's a lot of different ways that the server could tell the client who's currently logged in and that's what you see these bullets right here. Sometimes you'll see that they just pass over like a user object and that user object will have a bunch of information or properties about the user. One of those might be the role or a flag that says is admin yes no true false something like that. So that's one way you can do it. Sometimes you'll see a permissions object be passed over and this is basically just like a list of permissions that belong to the current user and the client will read that and

say okay this user has all these permissions. I will now present this feature set to them. That's one way you'll see a permissions map. Okay. And a permissions map would be let's say the client and the server are both aware of all the permissions that exist and the server just sends basically a true false mapping from to the client that says okay apply this mapping to the permissions all the ones that are true are the ones the user has access to. I've seen that in fact that's a really good candidate for the whole substitute everything false is true thing. Has anybody ever done that with Burp before where you just say Burp you go to the

proxy and you do a match and replace everything false turn it to true. Right? It will horribly break things, but it might actually do some really interesting stuff as well. It's kind of like that. Now, if I see this permissions map come through and I see like a bunch of true falses, I'm just going to turn them all to true and see what happens. This is that's one way it happens. And then another one is you may have like an explicit list of components, actual component names that come across that tell the front end you can build these particular components for this particular user. That's very similar to the permissions approach. It just may look a little different.

functionally it it behaves differently on the client. These are just four common ways that I've seen it, but it it it could be any number of ways. It's one of those things where it doesn't the developer just has to let the C client know. They can literally do it any way they want. These are just four ways that make sense that I've seen it done and that function pretty well. And heck, some of them may be defaults for certain frameworks and stuff. Um, but those are the ways that you can expect to see that. Now this is going to happen either during the authentication process or right after it. It has to happen before it creates the view, right? And that may

be actually in the response with the token or with the cookie or whatever. It may be a simple request in response that gets sent right after that. But it's going to happen before it draws the view. It's got to get that information from the server. Our job is to figure out how it's doing it and then manipulate it in a way that benefits us. Okay? And so that's what we're going to do here. So we got four different ways that we can go about doing that with Burke. And let's start with the first one here. So intercepting and modifying. If we go over to here, I'm going to close down discover content. And let's look at own this is

test.hub.com. So onub2.0. I'm logged in right now. And notice I have access to notes, scans, messaging, and logout. Okay, notes is basically where I can just keep notes about scans that I'm running. Scans is where you can run all these different tools. provide the arguments there and it'll asynchronously run that stuff and give you some information back. These are this is basic user functionality, okay, for this particular application. There's a Slack-like messaging interface. You can modify your profile and of course you can log out. That was a basic user. Now, what I'm going to do is I'm going to log in as my basic user and try to find I'm going to follow that authentication

process and find out where it's receiving that information from the server so that I can manipulate it. So, I'm going start the process. And this is a passwordless authentication system. So, I'm going to do this. Log me in, please. It says the code is required. So, let's go to my little makeshift inbox here and grab my code. And before I submit the code, I'm going to now go turn my interception on. All right. And now I'll submit the code. Okay. So this is all these options requests you can ignore because that's all cross origin resource sharing doing what it's doing. So we've got this going across forward. I'm going to get the options back. Now

here's my post request with my code and my code token that's going to respond because the code matched. Okay, it was a su a successful login. I received the access token. Notice I'm so this is the successful authentication here. Notice I don't see a user object or any of this permission stuff. None of that stuff is here. So, let's keep following the process. We see another options. We'll let that come through. And now we have a get request to something called users.me. This is not something I did. This is something the front end is doing as a part of the authentication process. And we probably can assume that this is going to be the thing we're looking for

here. We hit forward and the response is a user object. And you can see the ID, when it was created, name, email, avatar, all this good stuff. And there's a property called RO. What What should we change that to? >> Admin. All right, let's try that. So, it says the role is user. Let's change it to admin. And then we'll go ahead and turn interception off at this point and let that flow through. And now we see here that we are still logged in as Tim, right? That's still my avatar. But now I see the user interface, the tools inter and the tools interface, which are not user level stuff. So now I'm looking at the admin

interface still logged in as Tim. And now my job is to go in here and figure out if I can do these things. And sure enough, at least in the in that in with regards to those two things, the enabling and disabling and promoting and demoting accounts, I'm getting 403s. I'm not able to do that. So once again, this is not a vulnerability, but it gives me the ability now to test for serverside resources through the interface that I couldn't do before. Right? So now if I didn't want to go through and do all that source code analysis, this is going to allow me to resolve those serverside resources and interact with them in a

way that administrator would. Now if we go over to tools, kind of a similar thing here. This is where you add tools that then users can run. Of course, it' be nice to add bash to this. Try to add it and I get the do not have permission. If I try to delete one, I also get I do not have permission. Okay. So, as far as administrator feature set here, it does not look like there are any access control issues, but there's actually one sitting right in front of us that we may not have realized. Should I even be able to see this content? No. Like, why can't I even see users roles and statuses as a as another basic

user? I shouldn't even be able to see that. So, where did that come from? Um if we look at our proxy history there is a get option for slash a get request for slashu slash users that has all that user data in it. So this is the request in the response that populates the you the user administration interface. I probably should not have been able to access that right probably should have been either two things is wrong here. One of two things. they're either either that user's response is being used in other parts of the application that I do have access to and it's just returning way too much information which is an information disclosure issue or I

shouldn't be able to access this resource at all and that's an access control issue. If we go looking through the app, we'll see that this request and response is never needed by a basic user. This is an access control problem. Okay. And that's all because we were able to force the user interface to show us this stuff and that and then it revealed that. Okay. All right. So, the other way we could do that, there's a couple different ways you could do, you could use a match and replace rule. You could easily just create a match and replace rule that does exactly what we just did. Just looks for that the role equals user and change it to roll cloud.

You're good to go. The other thing you can do is modify this stuff straight up in local storage. So if we open up our uh developer tools here and we go and we look at storage, we have session storage and we have local storage. And if a developer it wants to create the user experience where you can close the browser and then reopen the browser and still be logged in or close the tab, reopen the tab and still be logged in. They're going to have to store the user that user information including the token and the user object somewhere in the client side in the browser so they can retrieve that stuff and give people that sensation that they

didn't have to that they that they never really got logged out. Okay. And the way they do that is in local storage or session storage. And we can see it's being stored right here inside of local storage. This developer wants the user to be able to persist a close of the browser and reopen or um even a restart of the computer because this is persistent. So now if you look here, of course, we're going to see that role is there again. And so we can just modify this. And then right now we're already admin. So I'm just going to switch this to user. Hit enter there. And it didn't really change anything yet because I'm

in local storage. But now I want to force the browser to reprocess that user object. And I can do that just by refreshing. And now you can see we see notes, we see scans, and all the other regular user stuff again. So we could just go in here and just flip it to admins right there inside the user object. The final way and probably the most complex way is if you know enough about the framework that's being used. That stuff right there is is is how it stores and makes things persistent. But these client side rendered applications have a client side state that manage it's inmemory. It's an in-memory state that manages all of these things um that the view is

reactive to. And if you know how to interact with the state management system for the framework, you can just do it right then and there as well. So in this particular case, it's a view app that uses PA. And let me look here. I'm going to cheat if you all don't mind. Get active pin state value. That's right. Okay.

Uh let's see. I think it's value dot off. Yep, I missed a thing there.

Here we go. User info. Roll. And you can see there it is. User. If I just set this to admin, I want you to watch the upper right hand corner of the browser window. What happens to the navigation menu? It instantly changes over to user tools. Okay? And that's because the entire application is reactive to its internal state. If you know enough about the framework and you can go into the internal state and just start modifying values, the front end will react to the changes that you make to that state, which in this particular case, there's a user object stored there that's that the actual uh front end is looking at to determine which user interface to build.

And we just tell it, hey, by the way, I want you to now build it for admin. And it's watching those values to see when they change. As soon as it changed, it redrew the interface. And now we see the administrator feature set there. Okay. So there's a couple different ways that you can go about UI privilege escalation. Again, not a vulnerability, it's a feature. Okay, it's a feature that we can all leverage to be better at our job. Now, the final thing here, the last thing that's as part of this talk is that and it's the third way that we can go about doing this, right? One is the manual force browsing, which I don't

recommend you doing. Second, UI privilege escalation. I absolutely recommend you doing that if you're dealing with a client side rendered application. But the final thing is leveraging some access control testing tools that are at our disposal. And these basically take that forced browsing thing that we told you not to do and automates that process for you in a couple different ways. Now, there's a built-in tool inside of Burpuite Pro, which is the way that I highly re highly recommend doing this. It's called compare site mapaps. Has anybody even heard of compare sitemaps before? It's very rare that people have heard of this, but it's going to be the way that you do this moving forward. Okay. The

second the second option here is using one of the a couple of extensions that do this. So, there's off analyzer, authorize, offmatrix. A lot of folks I found use autoise mainly because they've never really looked at off off an Analyzer. Off Analyzer does the same feature set, a little bit better, a little bit cleaner, a little bit better interface. I don't particularly use the extension personally. I like using compare site mapaps, but we're going to walk through both of these because I think some people may like one over the other. I want to make sure you have a couple of options. Okay, so we're going to walk through using the compare sitemaps technique for this. We're going

to walk through the off analyzer techniques for it techniques for this as well. Since we got three different roles in this application, unauthenticated, basic user, and admin, right? Normally, you would use this technique for each level, right? You would test you would use you would test from unauthenticated to authenticated, and you would test from basic user to admin. And you would do it using one of these particular techniques. Since we're going to apply two techniques, I'm going to use unauthenticated to basic user for compare site maps. Then we'll flip over and we'll do basic user to administrator over alt analyzer and you'll get a taste of how each of these work. Okay. So what compare site mapaps does make sure.

Yeah. What compare sitemaps does is it gives us the ability to take our current sitemap that's sitting inside of our target tab. All right. And rec crawl it with a session context of our choosing. So our entire attack surface is in here right now for www.onub.com. The entire attack surface is there. Right. I I logged in as an admin. I mapped it. I logged in as a basic user. I mapped it. I did it from an authenticated perspective and I mapped it. So the entire attack surface is there. So when I do compare site maps, I have a couple different options and I'm I'm going to get to select two site maps. The first one's always going to be

the current one. It's what currently exists inside of Burp. So I use the current site map here. And then I only want to use selected branches. And if we go over here and make sure that we've got the right branch selected, which I don't for some reason. Make sure you got the right branch selected. I want to use the selected branches and only use inscope items. Before class, before this started, I went in and removed the login and logout resource from this because I don't want compare sitemaps logging in and changing it session context or logging out and changing it session context. So, it's something I did offscreen. Um, but that's why I'm including only in scope stuff because

it's is excluding those things. So, that's sitemap one. It's what's currently there. This is where the secret sauce is. In sitemap 2, you could tell this tool to rec crawl the entire sitemap one, but do it with a session context of your choosing. In this particular case, the way that we set the context of our choosing is in the browser because what Burp tries to do is mimic the session context of your browser. So, if you're logged out in your browser, Burp's logged out. If you're logged into your browser, Burp's logged in. Okay? So, all the thing only thing we need to do here is go over to ownhub. And I'm currently logged in. I

wanted to log in on purpose to show you the menu here. So, testing notes, artifacts, collaborator, own mail messages. This is a basic user interface, right? We're not seeing any administrator stuff here, but I don't want to be logged in anyway. I want to be logged out at this point in time because I'm this first test is from an unauthenticated perspective. So, once I've done that, I just tell it request sitemap one with a different session context. And then all these other settings, you can basically just use the defaults. If you wanted to go a little bit faster, you could up the threads, but this happens so fast, it doesn't really matter. Hit next. As far as request matching and

response matching, I don't really care about what that's trying to do because we're going to do the analysis ourselves anyway. So, I'm not even going to pay attention to those things. And very quickly, it processes and is now it's doing the forced browsing. Remember all that forced browsing I said we would have to do? That's what it's doing right now. All of it. So that we don't have to do the gets and the posts and everything else. And as soon as it finishes finishes up, it'll give us two different site maps to analyze. Site map one we're not interested in because it's currently inside of our Burp. It's sitemap 2, the rec crawl that we're interested in. And

so what I want to focus on here is stuff that I shouldn't be able to see. So I'm going to sort by URL. And what we're going to do is we're going to go down and look at the stuff I shouldn't be able to see and determine whether or not I got the expected response for that. That's the key here. I'm also going to get rid of things that are just that didn't have responses. Okay. All right. So, going down things I should not have should not have access to from an unauthenticated perspective. Admin tools shouldn't have access to it. So, I get a 302 redirect back to the login page. Is that safe? Yeah, that's safe. That's that's

expected, right? A lot of times when you try to go to authenticated page from an unauthenticated perspective, the application's very nice and says, you know what, I'm just going to go ahead and send you the login page and then when you log in, then you can come back here, right? This is user experience feature. So that's expected. Admin tools add 302 redirect back to login. Remove 302 to login. Users 302 to login, demote 302 to login, disable, enable, promote. All those seem fine. Okay, all of those are redirecting back to login. I shouldn't be able to get to artifacts. That's a user feature. And once again, I'm unauthenticated. Redirect to login. Login. Login. Login. Login. Login. Okay.

Favicon. Yep. That's available to anybody. So, I can get a 200 for that. That's safe. Home. Right. Where's that redirecting back to? It's redirecting back to slash, which is a reasonable home for an unauthenticated user. So, that seems fine. I should not be able to view mail. That was an authenticated feature. Sure enough. 302 to login. Login. Login. login. All that looks good. Okay, that's still Are we still in mail? No, now we're down. Now we're down to messages. Okay, messages also a user feature that requires authentication. 302 to login. Log Wait a second. That's not redirecting me back to login. I have an endpoint here called SLM messages slash unfurl which appears to be a component of the messages feature

which requires user authentication to get to yet for some reason I'm getting a 200 response here instead of a 302. What does that tell us about this resource? It's potentially missing the access control. Right? And if we did if we went back and we looked at the we went back and did an analysis of the messages interface and saw when that request and that response took place, you would absolutely conclude, yeah, this is a part of the messaging interface that I should not have access to from an unauthenticated perspective. And bam, you found an access a missing access control issue. Okay, it's kind of like a needle in a haststack that we identified. and you just continue and

you just continue down the application knowing that you're looking at all the responses from the perspective of an unauthenticated user to to figure out whether or not you should be able to see it. And that's the only one that you would find in this particular instance here. So I'll save ourselves the time by doing the rest of the analysis. But it really is the tool did all the heavy lifting of making all those requests. We just very very quickly with the context of knowing the application look at the responses and determine whether or not we're seeing what we're supposed to be seeing. Okay. And that stuff will start popping on. It'll start jumping off the

the table at you. Okay. All right. So now let's move over to the other method here, which is going to be off analyzer. And with off analyzer, we're going to test from the basic user perspective to the administrator perspective. So let's go over to our extensions here. And I should already have that enabled, which I do. So here's off analyzer. So the way off analyzer works is you give it the sessions that you want it to use at the top where it says sessions. So we need to go in there and give it a session for our for our target user which is basic user. Okay. And then what we need then what we do is as the user we go into the

browser and we crawl all of the stuff that we should not have access to from the session that we put in off analyzer. So what we're going to do is we're going to give off analyzer a basic user session. Then we're going to go log in as an administrator and crawl the administrator feature set and then come back to off analyzer and it will it will have done some analysis to tell us whether or not we saw anything we shouldn't have been able to see. Now the thing that jumps out the thing that I think about when I think about that process is wait a second I'm having to do the manual analysis again or the the

manual interactions again. These extensions had the humans do what they're bad at and the tool do what it's bad at rather than where we compare sitemaps had the tool do what it's really good at and had the human do what it's good at. So this takes kind of a backwards approach in terms of exercising the tool and the user's strengths, but it does work. And so I'm going to show you that here. So the first thing we need to do is is log in as a basic user and grab a session. All right. So, I'm logged in. I'm going to go over to my proxy history here. And grab one of these. Okay. Actually, I'm in the wrong app.

Actually, no, I'm not in the wrong app. It's just that the other app is still firing off requests. So, this is the one I'm looking for right here. So, this is going to be my cookie with a valid user session in it. Let's copy that. Go over to off analyzer and we'll call this basic user

and we'll give it the entire cookie header. Okay, that's going to be my basic user setup. Now, what I have to do is is I have to log out of the application without destroying the session. So the way I'm going to do that is just open up the dev tools and delete the cookie because otherwise if I click log out here to login as the admin, what's it going to do to the cookie that I just gave it to off analyzer? If it's a well- behaved, properly secured application, it's going to destroy the cookie and the session context won't exist. So I'm going to go into the storage here, just delete this right out of here.

So now if I refresh the page, I should be logged out, which I am. Perfect. So now let's go in and log into the admin account. Well, that's not great. All right, let's get rid of this because it's actually defaulting the notes from the last one. Okay, here I am logged in as administrator. You see my collaboration, all that good stuff there. This is or uh collaboration for mail. And then you have the admin interface for tools and users. I'm now logged in as the admin versus before when I was logged in as the user. So now what I want to do is now go in and enable Alt Analyzer because right now it's stopped. So I'm going to start it.

And now that it's starting, when I go crawl all those every time my browser now makes a request, Burp's going to capture that request, replace the session cookie, and make it as well. So every request I make, it's going to make an identical request by replacing the cookie with the one that I gave it. And it's going to do that for every one. And it's going to give me a mapping of those of the both of all the responses from all the from all the crawling that I do and highlight areas where it thinks it saw something it shouldn't. So now you can even see this is still coming from the wrong application. So let me I want

to get rid of I need to get this thing logged out. The other application is still pinging because it's doing some long polling. All right. So we won't have that anymore. So now I'm going to go in here and and map the stuff I should not have access to from a basic user perspective. We'll start with tools. We'll try to add one. Of course, as an administrator, we're going to be able to, right? So, I just added one and deleted one. Go over to the users. Promote, demo a user, disable, and reenable a user. And if we looked around the app, we would find that that's pretty much all the administrator stuff that exists. I mean, within messages,

you can see the administrator has the ability to delete everyone's messages, whereas like Taylor would only be able to delete her messages and so on and so forth. For the most part, this is the stuff that we're interested in. So, now let's go look at the table and see what it shows us. So, it says when we went to admin users, which is the user interface, we got distinct differences. And it says that that's green because uh for my response for the original was a 200. That was the admin. My response for a basic user was a 403. Okay. Tool did the right thing. It recognized different responses. So, that was a safe response. Now let's go

to admin users enable three. It shows red because it got the same response for both session context. And if we look at that for the original user which was the admin context in the browser I sent the request to enable user 3 and it redirected me back to admin users. Right? So I'm in the admin users interface. It fires off a request to disable that user and then read redirects back to the user interface where you can see that the user's been disabled or promoted or whatever this one's doing enabled. Okay, basic user same exact response. It would be very easy to look at this 302 and go, "Oh, you're being redirected back to login,

right?" But let's look at where it's being redirected back to. It's being redirected back to admin users. the same exact behavior that was happening when I did it as an admin. It did it as a basic user which indicates that that particular resource is not applying the access control properly. Okay, that so the tool's not wrong. It's the same. If we used compare sitemaps, we did the same analysis, you would find the same thing. And so the tool worked. It just takes a little bit longer to when you have a large application, you have to go remap it every single time to for in order to do its analysis. It takes a little bit longer to get to the answer.

But the answer is there. It will recognize these things. As you can see again, admin users different. So that's safe. For disabling, you got the same response. For demoting, we got the same response. For promoting, we got the same response. All four of those are missing the access control. And this is actually a very important demonstration here because admin users is the user interface. Admin users enable three is a business logic controller. Remember how I said you have three different developers, a minimum of two different developers that need to apply access controls? This is a perfect example of the user interface, the view developer, where it's the most obvious, they're applying the proper access control. I can't see the feature.

Okay. But the but the controller developer that's in charge of protecting the business logic where it's not as obvious because it's not straight up in your face when you're looking at the interface, they did not apply the access control. And that's where you have that problem. there's a trust boundary there that was broken and we found it and are now able to violate that. Okay, so that's what these tools that's what these tools and these approaches help you to do. Any well I'm starting to act like I'm teaching a class here. Are there any questions from the class? We'll get the questions here in just a moment. This is actually something I teach in my

both my PWAPT and my PBAT classes. Uh we obviously have a little bit more time to go a little bit deeper. Uh but this is the gist of what we talk about here. All right. And so that's how you would use these various sets of tools that are available to us to find access control issues. All right, so that's how we as testers are going to help tame this storm. All right, that's how we're going to do it. We're going to find these vulnerabilities. Now, what do we tell the developers to do to fix them? Well, these top two are things that every development team should be doing pretty much regardless of their level of

maturity. I think there's probably some developers in the room that would be that would chuckle at that, right? But maintaining a well- definfined permissions model and then just just doing basic peer reviews like anybody like I'm sure those of us in here that are doing pentests and writing and writing reports. People peer review our findings. If your team's not doing that, I highly recommend that you implement some sort of peer review process. Okay. Same for developers when they write code. Typically there's some sort of peer review process in place that makes sure our well-defined permissions models being applied. But then even beyond that, right, if it's a more mature development team, includes security user stories. So if you improve your agile

process is to include security user stories rather than just functional user stories, right? Bake it bake security into the process. Make sure that features do not get shipped without meeting a particular criteria with regards to security. You can build those things around access controls, right? And then security unit testing. So there's mature development teams are probably already doing some level of unit testing where they're testing different features to making sure they function before they ship them to production. You can incorporate security unit testing as well which is more interested in making sure there aren't security issues there rather than just them being a functional feature set. And these things you can actually deploy in the CI/CD pipeline to make sure your

applications don't ever even hit production without being tested for potential access control issues. Okay, so these are the recommendations, the general path of recommendations that we would send our clients down if they're looking to prevent this from even happening. Okay, so that's all I got for you today. I hope you enjoyed that. I hope you learned something new. I hope that when you go to work on Monday, you have a whole new sense of how to go find these particular vulnerabilities and you start finding the one in every assessment that that I have found to be an average for me. Um, if you got any questions or anything for me, I'll be around the conference for the rest of

the day, but you can also contact me here. It's my email address. Um, if you're interested in training, I am going to try to start spinning up my training. I haven't trained much in 2025 because I took this new job early next year. I want to get back into making my PBAT and PWAPT classes public again. Um, that contact us, get on the mailing list and you'll get alerted as soon as those classes become available. You can also follow me on my socials, LinkedIn, and I don't do X anymore, but uh, LinkedIn, you can always find me there. I always make announcements there as well. Otherwise, thank you so much for coming.