← All talks

OAuth Hacking Marathon - Exploiting Common Security Pitfalls and Mitigating Them | Kaif Ahsan

BSides Sydney38:00167 viewsPublished 2025-02Watch on YouTube ↗
About this talk
Oauth is a crucial piece of the modern technology puzzle that enables us to experience a more unified and seamless digital ecosystem. In this talk, we are going to showcase a series of demos that exploit various vulnerabilities both on the client side and on the authorisation server of a fictional OAuth service to show the common security pitfalls and how to navigate them. In a cat-and-mouse chase fashion, the demos involve the developers patching the OAuth vulnerabilities, only for the hackers to identify a new, more complex attack to own the company again. These demos are inspired by real-world incidents and will illustrate how attackers actually exploit them in the wild. OAuth gives us immense power of letting our apps and services share data seamlessly across them. But like Uncle Ben said to Spider-Man, “With great power comes great responsibility”, OAuth can also be a blessing or a curse. And in this talk, we will explore what can go wrong with OAuth if we don’t wield this mighty power carefully. Throughout the session, we will also discuss defensive strategies and industry best practices to tackle these attacks. Additionally, we will analyse the root causes of these vulnerabilities and discuss how the future OAuth 2.1 version helps mitigate such attacks. So buckle up for a roller coaster live hacking marathon!
Show transcript [en]

hello Sydney how you all doing today good my name is Kai and today I'm here to talk to you about uh common security pitfalls and how to fix them in aat before we do that I wanted to start with a story and this story is of King Midas a very common story that some of you might know but the legend goes something like this that in the old uh Greek mythology we had King Midas who wished for great wealth and success so the god dinosis accepted his wish and gave him a power that everything he touches will turn into gold while that was super um good to have at the beginning pretty soon that blessing

became a curse everything Midas used to touch um turned into gold whether it's food or water or anything and the story kind of ended with Midas his uh beloved daughter turning into gold itself which is quite of a tragic ending to the story um and don't worry you I haven't walked into the wrong conference uh the talk is more about oath and we're going to explore how this powerful technology of oath can be a curse if not especially if not we did with K now uh a quick check on the room on how many of us um are aware how o Works a little bit on on the internally show up hands cool a few of

you which is good um it's totally fine if you're not familiar with oath um although this is not going to be an intro to oath or how it works kind of talk we will touch on all the relevant bits and pieces you need to know for to understand the attacks so let's continue with our story it was a very very long time ago in 2010 um at least that's how it feels in my head um the first oath one RFC gets published so oo which stands for open authorization basically wanted to solve the problem how can we share data between two apps without sharing the credentials now um unlike my modg app which continuously ask for my

bank password um back in the days it used to be a very common thing and you don't want to be giving away your sensitive credentials to every single thing so that's where the um question arised that hey how can we have a more connected ecosystem without um having to give our credentials and this thing picked on so we the very first implementations was actually around Facebook where we saw thirdparty apps coming and saying that hey um you can actually log into Facebook um log into our app using your Facebook credentials and seamlessly share your photos without uh with one single credentials and like any great technology people ask the solid set of questions um fast forward now oath is unanimous

every time you see um a login screen social login screen that says sign in with Google Facebook or apple or um you connect to apps like you connecting your J with your GitHub so you can share data across that is some flavor of oo plus some other Technologies at times but it's mostly the oo that is powering that so what is the mest touch when it comes to O now um fast forward from 2010 to now o has grown a lot there's over 30 rfc's that detailing all kinds of use cases for o so whether you are covering uh whe whether you're building a single page application or um um iOS or native app or even a very complex SAS product

there is some oath case that can cover you um that's one of the main benefits that comes with oath that it gives the developers the to implement all the bells and whistles they want to implement the way they want and that it that great power of customization and flexibility soon becomes the pitfall where there is a very high chance of misconfiguration as well now we're not going to cover all the misconfigurations that's going to happen in o o if we try to do that you'll be here until Monday and I might need to be taken away in an ambulance so we'll cover at least some of the uh very popular ones so let's let's look at one let's take an O

functionality imagine we're building an app and what we want to do is have our users the ability to log in Via their social media accounts pretty plain and simple so how do we do that in oo there is something called the authorization code flow so Flows In oo are essentially um procedures you can follow to securely exchange data there's four of them the authorization code flow is usually the most popular one and the more more secure ones um no need to get too much details into the other other three we'll cover this one in depth in here so how does the authorization code flow Works let's understand it very very briefly so we can understand the attacks

as well so here we have the three main parties we have our user uh which is using via browser we have the photoshare app which is our app that we have made and then finally we have the social media site which is the OD server and the resource server but hey what what does that mean so imagine you're trying to check into a hotel um your your client or which is our app that is requesting the data is is like the hotel guest the hotel guest goes to the reception desk and verifies all the permissions so that's the job of the a server so it's verifying the permission and making sure that you are who you are

you show your passport and then lastly you have the resource server that holds the data so in this case it might be a hotel room where we are trying to get access um so so the outflow or authorization code flow starts something like this the user tells the um application that um hey I like to log in via my social media and our app goes cool um hey social media site this user wants to log in Via you can you make that happen um and this is the initiation of the oat flow um and it looks like uh this big scary URL that gets sent through and all this or orange bits is o u par parameters that you need

to configure again don't need to worry about all of them but the main ones is your client ID that tells you that hi this is uh the client app that's trying to connect uh the redirect URI which is after the user has signed in or validated where do you go back and lastly the response type so which tells us hey what flow to do in this case the authorization code flow is what we're after so once you send in a request like this the author the social media site will then ask the user that um hello I am having someone ask that they want to connect do are you sure do you want to authorize or log in and this is the very

agal familiar screen you see where you uh whenever you're trying to log in that says that hey someone is trying to access your account um they're trying to access these information do you give them permissions or not um you guys have seen the screen a lot right I see quite a shake of hands so that's your typical o consent screen um once the user says that yep yep um um it is it is I who want this um then the social media side that okay that's very good now the some of the other award magic starts to happen um we get sent an authorization code so the authorization code is like a temporary token that gets exchanged for

an access code um so it's like when you are checking into the hotel you uh get a booking ID and you say your booking ID and you get uh let's say a room key card or something like that so it's a onetime thing that gets used so using that authorization code you change for an access code the access code is like an any other API token that you can use to access more information so yeah imagine this uh request where you have the uh you're sending a post request with the access code uh and a few other bits and blobs like telling hey I'm the app that's trying to access and my secret and you will get an response like this

uh with the access code same bank to you and what can you do using this access code this access code is that hotel key card that we were talking about using this access code you basically can ACC access the username and email from the social media site and then lock that user in or do whatever you want to do now in reality um there's a bit more complexity to it these days logging in happens using oidc flow where an ID ID token is used instead of an access token but they're almost the same thing so for our purposes we'll juste um assume that's the case um and to be fair many there's still many apps that will still

do the flow like this way so it's totally valid cool I know that was a lot so let's very very Briefly summarize it so we have the user request for social media login our app initiates the request and gets an au code we exchange that onetime alt code for a permanent access token and using that access token we access our data that's pretty much the aat in a gist does that make sense thumbs thumbs up and Nots which is good uh um then a food for thought so how does our app even know who requested the O code authorization code in the first place the short answer is currently it doesn't um oath without certain

parameters is stateless and anything that comes stateless and that complex has some interesting Avenues of attack so let's get started with that so in this case the players involved would be at three parties we would have the attacker the victim and obviously a vulnerable app so how this attack works is the attacker initiates the O request like we saw and it gets an um authorization code back we intercept this Au code um you can do it via like burp suit in this example like you can stop at that particular um request and just drop that request but basically get that uh code itself once you have the code it looks the request looks something like this where it's a that OD

code back to you and then the code itself and a bunch of other things and the important thing to remember is the OD code is sing Single use only so using that o code we can now try to fish the user to click on that link and it can be any fishing website that you can easily whip up but at the back of that fishing uh website there's two things happening um or there's two ways you can do the same thing basically in the background we are trying whenever the user clicks or visits our fishing website we're trying to restart that oat flow um so the rest of the oat flow is completed by the user remember up until this point

the attacker started the O flow they logged into their Facebook or whatever they got the O token back o code back and stopped it there they haven't used the O code to exchange for data yet the prerequisite for this csrf or type attacks is the user needs to be logged in session in their browser of the app so in our photo session photo share app let's say the user already is logged in there so when the user receives that access token and then um continues the flow they actually get back the users usern attackers username and email what's what's the benefit in that um so so the user's account the account that is logged in into the

browser now gets associated with the attacker social media so the application request looks something like this from the user side so the user browser sense that hey I've got this access token back can you please give me the email address and name associated with it and the app is our application checks that um access token and it's like yep we have Mr attacker registered for who started this flow and hence this token belongs to them so we're going back Mr attacker's name and email and in the browser um because our app doesn't know or have any state it doesn't know who has generated the flow in the first place it will take the attacker's username email and it

would associate with our current logged in session in the browser and that's the final flow so whenever the attacker now logs in it goes to photo photoshare app and says hey I want to do social media login it will actually log in the photoshare app but the users's account not their account um and suddenly all the users photos now becomes the attackers so how do we solve this issue um something called States um not this one we just need one which is the state parameter so the state parameter is a randomly generated unique parameter that is specific to a user's account um again what does that even mean so at the start a random value is generated and tied to

the user's account so whenever an au request comes back we check the state parameter with the um with the AC accompan sorry with the user to see who is uh is it the one who requested it or not so to make things simple or given an analogy think of passport checks you when you go you create a passport and that is usually associated with some details of yours and every time you go in and show your passport we check the passport detail uh or the passport number which is your state parameter and then the details associated with that so if I go and say that hey my passport number is this it will say that um

actually sir your name is not Mr Bean so you're not going to be able to use this passport um so and then uh we move on so we implement this check um across our request so this is our original request which does not have the state parameter we pop the state parameter in into that reest which is a randomly generated value and in our code it looks something similar to this where we are storing the state parameter along with the user ID and the time stamp the time stamp is important because we don't want to be let's say someone started an O flow yesterday and that gets completed today now that is fishy what what took you so

long to log into your Facebook um things like that so we wanted to make it time bounded as well so we basically say that Yep this is the O code that we sorry the state parameter we generate and here's the user associated associated with it so and we pop in that state parameter in all the request um that follow through from there um and once we receive a request it looks something along the lines of this where if it doesn't have a state parameter we say nope it's false this request is invalid we check if the current user is the one who started the request not start sorry apologies for the typo um started the request and if

it's not the person who um started the request we like no sir you you can't your state parameter doesn't match it fails or if it is the user who started we also check how long ago you started it and if you took too long we're say say kindly can you start it again so that's pretty much it in terms of um validating State and our data now is safe um which brings us to uh another type of attack let's try to change roles a bit instead of our apps asking for data let's consider other apps asking um us for users data um why why would that be so why would your app need to exchange data with

others in in in these day and age some of the most common use cases you seeing of you your opening up your app to others is obviously you have plugins and thirdparty apps um that's a more Niche use case but a better use case is probably having more better uh integrated user experience so whenever I copy paste let's say my J link or something in bit uh GitHub I want to be able to see the uh issues name or ID um those kind of interchangeability happens via oo similarly um taking actions on behalf of the user as well whenever something happens in my app um let's say whenever the issue is updated I want an

automated slack message sent to the relevant stakeholders so those kind of interconnectivity is again um these days it's not just a wish list users expect your app to be integrated and available to other um popular apps and ecosystem like that so it's quite important you do that and how do you actually ensure that you're not um sharing passwords across with other random apps thankfully this is a talk of oot so we know that problem is already solved and hence comes in the other benefit of sharing password not sharing having to share passwords with other applications and what's the fundamental thing wrong with sharing passwords is it gives you access to the entire Kingdom so it's not

just if you imagine you wanted to check into a hotel and then your hotel key card instead of your room it gives you access to all the other rooms that's a bad scenario with passwords it can be like that but with oath now we can lock it down and the way o manages to do that is something called Scopes um not again not this one but something that looks like the scope uh check screen here you're actually giving out explicit Scopes to uh approve to your app now Scopes are really powerful it makes it makes it possible to have fine grain control on the tasks you want the app to do and block the task you don't want the

app to do um and that allows us that makes o so powerful because it gives you this very granular control which otherwise wouldn't have been possible and like Uncle Ben said to Peta uh with great power comes great responsibility so we need to make sure that Scopes are being treated properly as well here in lies comes the second Pitfall where we have put in too much responsibility to someone that probably does not uh deserve it and it can spiral in all sorts of ways um in particular we to look at broken a Scopes so what does that even mean so the first even Pitfall that can begin is overprivileged Scopes imagine a request like this where an app starts uh to

authenticate but it in the meantime says that hey actually uh this token you're going to give me I need admin access read I'll read all write all delete manage users and manage system billing as well um why why do you need so much um a lot of the times if you are oversharing scopes that basically pretty much goes back into that root problem or what was trying to solve now now the audience here is fairly smart you might be thinking hey why do we even give that broad Scopes what's the issue with it so when we were rolling out oath and stuffs in atlassian what we figured out that one of the biggest pitfalls is how do we

even have smaller Scopes th applications we have often have very big permission models that do not accept very granular permissions like just read that particular issue or something like that it assigns a user-based um permission model um and that was an easy fix but what that lead to is the second Pitfall um okay sorry I missed a slide which was many apps when they start they don't have granular Scopes it's an easy fix you just have granular Scopes but that leads into the next Pitfall that we see a lot is something called scope explosion so what Scopes explosion so it's the case where our app has accumulated an huge number of weird Scopes that it's too hard to manage

let's have a look so when we start we have initial list of scope which is um all the users and it's around uh it's based around the users which is great but as our application grows in functionality and use case the types of apps we want to integrate to our Scopes can hugely increase too and what becom what was super useful once can become really hard to manage and you can even cut yourself with it and a common example is when you're trying to create a request like this and you need to encode all kinds of Scopes it's really really easy to misconfigure and like we saw in the last demo whatever is hard to

misconfigure will be misconfigured sorry what is how to configure will be misconfigured one of the good ways to to get around this issue is implementing a scope hierarchy so what is a scope hierarchy it's basically a type of uh organizing your permissions in a tree based model where you're saying that hey the admin is the top level and where you get all the permissions but if you just want the profile view you go down the tree step by step and until the section you have and then only ground that having a tree based model like this instead of just a flat scope reduces complexity a lot and it makes it easy to analyze as well um

there's a bunch of other things scope is one of the big issues uh whenever the first step of oat is implementing scope the next big challenge you'll see uh for organizations that maintain um o is how do you manage Scopes now we don't have time to go into all the different ways uh you can manage scope but certain things I wanted to sort of bring in um attention for you guys to investigate further on later is how can you do role based scope grouping things like scope templates so instead of implementing Scopes differently for every different functionality having a template and um achieving scalability through it and lastly regular monitoring of scope usage and audits based around that we have

found all kinds of funny things when we go back and try to do scope audits cool scope validation though uh or what to validate in a scope is only part of the problem when to validate of the scope is a very important U other half of that whole puzzle that often can lead to the second Pitfall which is not validating scope on each request and what do we mean by that imagine you are an application you and you allow other apps to connect with you what can happen is a malicious app or Plugin can request elevated Scopes from what then what the user approved so imagine that Google screen where the user clicks on read username read um

user email and then sends it to the app and the app requests that to you but you can actually later on say that hey it's actually not just read give me write permissions as well so how does that work let's say the request flow we say that read profile is what was requested we send the alt code when we are going to exchange that a code for an access token we can send the Scopes again and that's a functionality ooth actually supports we can say that um yep actually um I won the access code but um sir can you actually give me uh read not just read profile write profile and admin as well and if we don't verify at this

point that this o token was given for particular Scopes if there's no validation is there we are actually going to send back that elevated access code which will have read profile profile and admin which is very different from when when we started the request for an O code um again how do we um solve this one of the common issues obviously we're talking about is tracking Scopes in every major step but Scopes can be tied with your state parameter like we mentioned that state parameter needs to be checked at every single time when you're sending in that request instead of just a state parameter with username and email you can also Chuck in the Scopes that was

requested by that parameter and at any point if that changes you can track that hey um the scope you requested versus what's in that state parameter does not match so you can reject that cool so takeaways for this um one of the biggest pitfalls of O becomes a systematic way for managing Scopes and ensuring that we enforce scope at every step of the flow becomes super important as well cool let's talk about another oath superpower now oath when the user uses it they only see two screens the first initiation that hey I want to connect and the second screen which is the consent that yep I want to connect this but we know in the

background that's not the case um we just saw under the hood how many stuff goes on and just having to explain it on a high level made me look literally look like this meme trying to uh draw some of the weirdest connections but the good thing is the user doesn't actually see that um and which is seamless this seamless flow is achieved by something called the redirect and call back uis so this redirect and call back uis is a parameter that you configure that goes across along the flow and it knows where where to send the user back and take into different steps so that ping pong that happens that is powered by this redirect call or call back UR

what is super important about this though is you configuring both the O client and the providers configuring the ECT URI in the first place and configuring it well because if you don't configure it well the user after that initial check-in and validation might come up into a scenario that they didn't really want or bargain for so um this in lies becomes another very very common Pitfall we see across oath is improper redirect URI configuration we sometimes really don't know where did it come from and where are we going um now uh I I was trying to see okay how can I do it a bit differently um so I was going to say if if you redirect URI misc configs where

some people how would they be like so the first one we have that I trust everyone which is you you as a provider or a client not having any validation at all um and that's you might saying yo that sounds very risky but you'd be surprised in um so many apps especially once using o one actually do not do a lot of this validation so what's wrong with not doing URI validation at all um it can lead into this kind of sample attacks where the first one the attacker just instead of the original call back that is autogenerated we pause that request using burp or anything and then replace place that you direct U with our

own malicious one and then send it to the user for fishing so whenever the user clicks on that link they will see whatever a that that um uh authorization flow and then they come back and they now into our malicious site the other thing you can do is try to collect the tokens in U fragments so the O token is sent across in the fragments itself so if you craft an U URI something along the lines which uh sends you to um a site that will just collect the OD token along the way and when the user clicks on it their a token will be captured and then sent to the attacker as well the

other more realistic case to be honest is what we see is around rejects uh when we're trying to validate uis it's not really one or two or three domains we have often our applications have hundreds of domains and subdomains and when we try to cater for it we can it's very easy to make uh mistakes um some of the examples with that kind of model is you can easily Craft um a Rex bypass which we saw um pretty commonly out in the wild and lastly something called the double redirect attacks where you start with the proper um URI but then you Chuck in another parameter that hey a double redirect but this time it goes

back to this original site and then again goes back to this site sometimes the app process it is twice instead of this redirect URI you can you could have used other uh prototypes like um next which in url uh World means that when you go back to that it will be redirected into that site um lastly we have the Local Host it's very very common to see that uh in the allowed redirect list because of testing or anything like that uh any testing sites uh lingering around as well and what that does is basic basically um an attacker then do DNS rebinding or similar type type of attacks to craft um an URI that will

pass your validation but then takes them back to the malicious side next up again um let's say you're fed up with Rex um uh it's really a skill issue you realize you admit it and then you move on with pattern matching that hey I'm not going to do that I'm going to look for specific patterns that inli brings in another uh interesting point we have seen a lot in the wild is trying to match certain URL patterns that resemble their app and that easily again can be done the same types of attacks of domain prefix or can be bypassed using a double redirect submit attacks um cool so takeaways from you uh trying to protect Uris exact

matches is your friend um when possible having the most exact match is what we want to be um having an allow list when possible is also great again um like we mentioned it's not just one two three or five domains sometimes it's hundreds so managing this and having an allow list is difficult but it's often well worth the effort and lastly if you're trying to use Rex please use with caution because that can often lead to more complications than you bargain for cool like in summary we saw that with uh we have a great power so how do we in wield it with great responsibility um if you're just developing an O app there's lots of good developer

checklists um the one I try to use a lot is from this uh GitHub repo it's quite comprehensive um H it's quite old as well five years um ago but it's still a lot of the checklist hold up so it it does the job um on the other hand with some really important things that we didn't really get to touch it is flows around oidc and a bunch of other ways o can be exploited if you want to dive deep into some of those um the RFC 6819 if you just search for that that will get in get you to this RFC called oath 2.0 threat model and security considerations it's it's one of those

blessings that um it's a gift that is that keeps on guessing giving every time I have a a related Security review to do or just an app to um develop I go in and make sure that I'm checking all the boxes from this threat model uh it's been um really useful um with that I conclude the talk thank you so much for listening um any

questions hey K thanks for the talk I really enjoyed it um I had a question when you were showing off the redirect misconfigurations one of the impacts was ssrf um I wanted to ask if that's usually like a full one or it's like blind it is um usually blind because uh the redir once the redirect happens the O code exchange and everything H doesn't happen on the browser that's happening more on the client's end from uh Client app to the authorization server or the resource server so uh sometimes in the redirect URI we have seen things like path traversals where you can try to Traverse path and try to get a response back that um yeah the you're not

supposed to get to and other kinds of uh flaws as well it's a bit harder to do but definitely

possible he thanks for the talk um just want to ask with like the common likelihood of like redirect Ur I think it's in my experience I've seen it a lot but in terms of uh valid of like the scope and whatnot is that like something you see often in the wild uh for sure um especially uh that's something that happens with more Niche apps that don't have that granular Scopes um they can it's a two-way problem so the first one is if you're the provider um you need to have that infrastructure to even support very granular Scopes and it's granular Scopes and that principle of list privilege and everything is very easy to to say that

hey do principle of this privilege but what we have found when you actually want to go and try to map all the types of requests that can come in and the resource you can um achieve and map it to granual scope it was very difficult and it was a very long-term project that we need to run um the scope upgrade attacks is something that we do see a lot so U validation of that scope is super important we see that all the time when because um especially if you are a relig open application let's say uh Google right just using them Google has thousands of if not millions of apps in the marketplace and a lot of those will

require a sort of integration with Gmail or Google um when you have that many apps and you need to trust a lot of them you really need to Val ensure that you're not trusting them because some of those apps or plugins or third party could easily be a malicious uh malware or something that tries to Elevate scope later down the track so yeah that's something scope a grade is definitely we see a lot especially if you own a Marketplace or any kind of plug-in based things like atlassian has a huge Marketplace we always see those kind of malicious apps trying to do scope upgrade attacks any other questions making me joke hi um thanks for the talk I was

wondering about um is it common to see issues around mismatching the state parameter with the actual or code itself um and so you know you'd get oh this is the or code and you have a separate state code and the state code is requesting different privileges that the original or code was intended for or something like that so if I understand correctly so a state code was generated and basically um you you take your state code and punch it to someone else and try to bypass is that what you're asking yeah yeah um H it's the similar type of protection and I I'm sorry if you're not familiar with the are are you familiar with csrf

uh protection or csrf tokens not really okay so um to break it down into a very um uh easily digestable way so state is tied with your user ID so each state uh when you look it up in your database it is associated with the user ID so when you in a realistic way when you look up the state and the user ID that also has the um Au code tied with it like hey here's the state here's the Au code that was requested by this user so that's where you do the validation um so that's where the cross check comes in handy does that answer your question have to elaborate that's yeah like put me there on the spot

mate cool any other questions going once going twice sold yay um thank you everyone talk and just a little present from bides here thank so much um I know the talk recorded but if you guys want the slides feel fre to hit up happy to share that afterward thank you