#NahamCon2024: GraphQL is the New PHP | @0xlupin
Other
n the talk "GraphQL is the New PHP," we dive into how to find bugs in GraphQL, similar to early PHP days. It's all about sharing tips and tricks for bug bounty hunters to spot security issues. This talk is like a collection of what I've learned, the mistakes I made, and some wins along the way.
https://www.youtube.com/watch?v=tIo_t5uUK50
June 5, 2024, 6:58 p.m. - by quas
TRANSCRIPT:
hi everyone and welcome to this presentation graph kill is the new PHP uh my name is Lupin I'm 22 years old and I've co-founded Lupin and homes a company that uh we're running with my brother and I've been doing back buy hunting on haakan for the past four years uh something like that and today we are going to talk about graph security and if even compare it with p p security so uh why do I love graphql I hate it I actually hate it uh but why do I hate graph because it's slaggy it's complex and I never understood where is a subscription operation anyway uh but that's all the reason why it's my favorite Target uh because uh my comfort zone can be the same as other people comfort zone and if I try to go outside of my comfort zone maybe I'm going to find new area of research uh new vulnerabilities that other people might not have found uh so that's why graph for me is the best uh Target but okay what is Graal anyway uh Graal is meant to be an query language for apis where basically we can describe the data present in your database and then uh request them but only the data that you want for instance if you have a project named namc then you can request only the the tagline and this is exactly what you are going to receive graph is meant to be an Ever evolving API endpoint uh where basically you do not need the versioning anymore and where the client can request only the data that they want in Graal there is certain type of operation there is the queries uh where basically is meant to search and fetch uh data the mutations are what in rest is the delete the put and the PST where you create uh Delete or uh update any kind of uh data and then there is the subscription operation uh which is basically meant to fetch uh data but when the data are evolving over time where they can change over time and basically you create a long in connection uh with the graph server to the the meain of a web soet for instance in order to see the update in the data so basically subscription is like some kind of query of a web circuit uh let's talk about my Recon process uh to identify a graphical endpoint so I could use burp or kaido put a rule and every time I see a graph C I'll try to dive in but I really like uh to just hunt on graph C lately so um basically what I did is I put a lot of the domains of different targets and try to identify only the graphical line points uh and for that I created a script pattern code uh that will open an adless Chrome and then hook all the EX chair requests until a time out theet I think I've put between two and 5 Seconds for each page and then if one the XR requests uh match one of my rules uh then it's a grq and so my rules are if the body is adjacent uh and contain the query field name or if there is a mutation in the body then it must be graph or if it's a get request with a query as a parameter uh then it could be graphql too um I could as I say I could use also nuclei or any other graph qu Point identifier uh but I had a lot of false positives and this techniques really gave me aot less false positives and more pertinent results so I I'm quite happy with this technique once I identify a graphical endpoint my goal is to try to see if there is an introspection that's the first thing I do an introspection is an operation in graphql where you can uh basically describe all the schema of the data all the operation all the mutation subscription fragments uh present in the the graphical schema uh this is like a Swagger that will be updated automatically and that is present natively in graphql um so introspection is really interesting if you want to to to have like entire documentation of how to interact with the graphical endpoint and once I have an introspection I go to gql spection uh this is the tool that is a successor of the real famous nql um and basically it allows you to enumerate all the requests possible for an introspection all the requests that you can do to the graphical backend and this is where we are going to find maybe undocumented codes by documented I mean present in the JavaScript so that you can read uh but with an introspection maybe you are going to have uh calls that are not present in production or stuff like that so it's really interesting okay so now you have a graph C and check for introspection but the in introspection is forbidden yes because you can disable introspection uh which is actually one of the best practice in graphical security uh but don't worry you've watched this talk and you know exactly what to do when introspection is disabled uh basically graphql doesn't want you to fail and uh will actually help you to find all the fields name uh correctly with something called the field suggestion and so each time that you put a keyword that is really close to a keyword uh present in the schema uh then it will prompt you like give you an error did you mean for instance update user detail uh and that behavior we can f it uh with a tool called Clairvoyance Clairvoyance basically uh is a tool where you input a word list and then it will fuz all the keywords present in your word list until it matches a did you mean uh response and from the determin it will try to reconstruct an introspection schema uh on a Json format and it's a recursive so each time it finds a field it will then fuz all the different uh each time it finds the queries it it will fuz all the fields present in that queries same thing for mutation and all different operation and everything is recursive something that you be you you need to be mindful when using this tool is like it's the request per second uh this tool sends a lot of requests per second and I already managed to uh do a Dos on several targets just by sending this Tool uh so you really need to be mindful of that and also the number of threads uh the threads are more like for if you want to have the best uh result possible and not forse negatives and then be mindful of the quality of your word list and that's always always super hard to have a great word list um and so to have a good word list uh there is one tool that will really help you when doing graphical security and this called tool is called J whizzle uh basically J Wizzle is a JavaScript IST analyzer it will uh parse uh the JavaScript code as a tree and then uh provide you an instant overview of uh the code uh of course it's a commercial tool so might not be suitable for uh beginners uh to invest in this Tool uh but there is an alternative oppos alternative coded by the amazing t n n uh called J loose uh I hope I pronounced that correctly and uh this tool is completely open source but it require more custom code and Advance setup so if you like to take in goang code uh this is B basically the best alternative for you uh but basically my usage of J whizzle is um that I go find all the graphql queries mutation and operation that it found and then I will use the feature uh to generate a word list out of all the the queries that already present in in the front end uh by doing that I I know that I'm using the words that the schema is using because it's already present in some queries and so I might find new queries and reconstruct uh the entire introspection and maybe also find uh undocumented field names and operations so it's really uh the perfect match with Clairvoyance okay so now that we have an introspection schema uh what do we do uh here are some techniques and real world stuff that I found on my bu Journey uh the first Target I I found this name funny because it's flying inside the cuckoo nest you will understand why uh the context my target had multiple organization with multiple users uh where basically the the the company was uh handling credit cards right and each user had a from viewer up to Super admin but only the admins could view the balance of the credit cards and so of course we had an introspection so all good so far and uh my goal was to see if there was a permission error from a viewer if uh they could see uh the balance of the credit cards so I sent uh the credit card query operation and try to get the balance amount uh but of of course it was forbidden and the error was uh the this user can't query the operation credit card which is super interesting because it doesn't tell you you can't see the amount of the credit card which is uh the the business rules behind that it says that you can't uh send the credit card query so what if they put the security on the queries but not on the final object that you want so the balance amount okay let's try something out of this I created a tool specially for this target uh called inpi I wasn't really inspired by the name at the time um and basically you provide an object type uh that you want to leak or to have a privilege escalation to and uh and we are going to search it inside the introspection and search all the different Roots possible from qu is mutation that could leak uh this uh this object uh here's an example I I know we don't see a lot of things but here's an example of this running on the haan.com graphical introspection uh they enable introspection it is known it's not avability don't worry about that and basically here I um ask for the uh activities user completed the retest object and it finds all the mutation uh queries possible uh to access this specific object so now we have all our different Roots maybe we can find a varability where our object is nested inside other queries and other objects and this is exactly what happened uh in this privilege escalation uh where basically through organization account then balance overview account balances uh balance you had access to the amount object and you could see the amount of the credit cards from a viewer so uh that was a cool privilege uh escalation uh that was to as a medium vulnerability but depending on the context it could be tra as um high or even critical if you can leak pii data uh but the technique is really interesting uh Target number two where subscriptions are finally useful uh okay how do people can do bad security uh in the graph C Ram uh basically where you have a client saying Json and there is a web application file reading the Json and then uh if everything's good sending it through the graph server uh but the thing is you do not want to put the check of introspection at that level because uh for instance if the client say an introspection and the W uh blocks it uh but the graphql still enable introspection this is really bad practice to do something like that why because for instance if there is another protocol let's say web ccet where you can send the introspection instead of subscription you send um a query uh with the schema introspection then the graphql could validate it there is some graphql that through web sockets uh you can do all the other operation not just subscription you can do normal operation it is kind of weird uh to do that uh but some backend graph qu enables that so each time that that you have a graph qu let's see if they enable web socket and they know it and if you have a web application firewall uh that doesn't allow you introspection maybe to web soet it will uh do it and so websockets are so cool because you can uh just send your websocket and and bypass it here is an example of JavaScript code to do it to bypass web application firewalls rules uh this could work also for SQL injection store xss or any kind of injection that you want to do that could be blocked by aaf so uh if you have a web application firewall with the graph C let's try that and see what happened but there is another cool varability uh called crossa Web socket hijacking my friendch accent is horrible sorry for that um where basically this varability is like let's say the csrf of web sockets but the only difference is that you can also read uh the response and in order to have this varability you have uh a few requirements the first one is that uh the authentication is solely cookie based uh and then that during the exchange uh of the protocol uh the protocol upgrade uh for instance each time that you open a web soet it will first send uh to the server in HTTP and then upgrade the protocol with a one1 uh response that will switch to a web socket and so if they implemented the csrf adder at this level uh then uh it's not vulnerable uh and even if they don't Implement a CSF header and you have cookie based authentication be careful that you do not have an exchange of secret or gwc token right after the authentication I already had a Target that where I thought it was uh vulnerable uh but it was sending the GWT token right after connecting to the web socet and so I I couldn't guess guess that cross site right so it wasn't possible to exploit it but uh on this uh Target it was quite funny because uh we had everything to be vulnerable and you could just send a mutation uh to the web socket to in this context was to decline an invitation so it was medium but again you can read the response uh for for that so you could leak uh pii data uh depending on the scenario so every time that you see a graph kill uh check if they enable web sockets and cookie based authentication and see if you can have a read right it's basically like a course uh policy uh vulnerability uh but here directly on web soet so really interesting vulnerability too okay uh here is the third uh Target oh forgot to say forgot to say that this technique I was given by this book uh I I needed to do a shout out of this book blackhe hat graphql amazing book uh for graph security uh written by Nick Alex and Dov fari again hope I pronounce that correctly uh anyway I needed to do a shout out because this technique uh was from this book and gave me a pretty good boy so I need to to tell that they're amazing and so if you want to go into graph security uh check that book and so here is a technique that uh I discovered uh which is basically widespread vulnerability within graph C uh so basically this target was uh a bit different because here the query you could search uh for a secret uh within uh the the organization or the user account um and basically the search was like if it match uh a subword of the secret it will still uh provide you the the the the value uh so you could just enumerate all the secrets uh in plain text and so the first thing I tried uh was to transform that uh to a get request and uh and see if it works and yes it worked in on Burp you could send a get request here however uh when I wanted to go on Firefox or Chrome had a message not allowed so why does it work on Burp but not on the browser and the reason why is because the browser send an accept a text HTML and for some reason the backend uh wasn't allowing this specific header I don't know why this back end was behaving like that but if you change text HTML to text plane uh it will work uh however we can send uh that just by clicking uh a link we will need to um make the user visit a link uh that will then open an XS request so it's still possible in one click uh to have a CSR F uh however there was an X csrf header for mutations so I could only do get uh queries uh but I couldn't update or create data on the account and because it's a csrf we can't read uh the response in this context okay so let's find another way to exploit uh this Behavior what do we have here we have uh an sop bypass through ex share because um I then change the get back to a post uh but when you have a content type of text plane uh you there is no course policy and the same origin policy will not trigger an error so you can send post request through text plan and uh you can also change the acceptor to text plan because accept is an another that is authorized by same origin policy to be sent cross site uh so um uh we have like some kind of sop bypass here because the graphical server still understands where it should trigger an error when you send a different content type cool uh so we have cr Crosset quer is working uh but what can we do uh with that remember I said at the very beginning graph kale is so laggy uh and so but what I tried is that uh to create some kind of d service condition where I would use graphical alysis to repeat the same operation in one request uh more than 10 times and um what was funny is that when it matched uh a secret it was taking more than 1 second and a half to answer but where when the secret wasn't matching it was taking 200 milliseconds okay so wait a minute we can send request cross site and we have a way to discriminate when we have a secret or where we don't have a secret isn't that the perfect scenario for cross site search uh or excess search uh and yes it is because we have a search engine returning confidential data we have a crossed request working and this huge delay to to graph being laggy so the first thing that I did uh when I had everything confirmed was to check is there like a graphql uh research on EXs search and actually there was only one result on Google uh but uh they only the company that did this research didn't provide a proof concept only said that it was possible and it worked on a couple of targets uh but I wanted to have the proof concept uh so uh everything good so far I started coding at 7 pm my proof of concept uh then at 400 a.m.
I was crying in the bathtub listening to Billy Alish and then at 5 a.m the proof concept was working uh so how does it work uh basically the search engine uh could match uh chunks of four characters and it will retrieve the right secret so what I did is that I created different chunks and then I quered a character by character until it was matching a chunk and then I do something called sliding the chunks I don't know that the real word for it but for instance if it was matching ABC D then I will take the end of the first chunk that was matching and put it uh back at the beginning of my second chunk and then D EFG and that way I can link uh chunks and at the same time Brute Force character by character the the secrets that I wanted to retrieve and so for each uh check of of leakage uh I sent uh many times uh the same request and I was logging the average time uh because for instance if the user had bad Wi-Fi uh the excess search condition was like returning a lot of false positives and I didn't want that for pro concept and then for each uh query uh I wanted also to have um to send a 44 something that will trigger a 44 and that I know that the secret can't match that uh why I wanted to do that it was because I wanted to compare that uh to my average time and just say that if there is enough difference then I know that uh my check uh was confirmed and that it's not a false positive and I did a lot of Random mathematics because I'm really bad at math until I had something working on different computers and different type of connection so let's recap this vulnerability we had a graph get based uh request uh then we managed to use that as an entry point to bypass the same origin policy so we can send a request cross site then we used a famous D of service codition through graph alyses to create a big response time when our search result exists compared to our search result not existing and then uh from the JS we can leak secrets of the user and also I didn't sleep in quite three times uh but yeah this Vil was really cool and um and helped me secured a 26,000 dollar buy uh so really really interesting viability and I'm sure that is more widespread than we think every time that you you see cookie based authentication and get request and that you or that you can send the content type uh for instance in text plane you might have uh a vulnerability a CSR vulnerability but if you don't have a CSR vulnerability try uh to make the response time bigger in order to leak uh with an excess search uh well thanks a lot everyone for this presentation uh this was different type of Recon different techniques that I use uh when I I'm hacking on guel I hope that you liked it and uh have an amazing rest of Nam Khan have a good day bye-bye