
Good afternoon everyone and thank you Bashid by for the introduction. So client side to critical is the topic and let's see what we are going to see ahead. So first who am I? I am Satyam Gauti. I go by the name of Rogue SMG. I'm a full-time bug bounty hunter. I was an ex chapter leader at null Ahmedabad. I also create contents content on YouTube and I go by the name of rogue smg there and we also have founded a a small thing for the community and we are developing that at barrack.armmy and with me I have Kulip Pandya and over to him for the introduction part. Hello everyone, myself Ki Pandya and me and Satyam both have like kind of very
similar bios. I'm also a full-time bug bounty hunter. I am also an accepted leader at Nalamabad. Uh most of you may know me from my blog at kulib.io and I'm also co-founder of barracks. Over to Satyam. So this was just a small about who am I. Now let's look at the agenda for today. So first we are going to see why we are doing what we are doing obviously. Then we'll have a very technical breakdown of how the JavaScript works, how client side things work. Then we'll see a debate between observation and automation like why not just automate everything and why even bother doing all this. Next we'll dive into the psychology that led us to
finding critical issues and which enables us to find critical issues without going crazy. And finally we'll see overcoming some challenges and that's pretty much it. Thanks. So 2 days before uh this came on my in short feed and I just wanted to add this here. This is just to give a context to you guys that sticking to the basics even in this modern era of AI definitely can land you bounties. If people can still rob using pigeons, we can land boundaries without using crazy automation or stuff like that. So this was just for that context. Now Java, what is JavaScript? JavaScript basically is just a piece of code which helps to make your web applications dynamic. So whatever you
see all the interactions happening on the web page everything happens through JavaScript and that is the only piece of code that we are able to see from a blackbox perspective right and web tech by nature is stupidly designed in such a way that we already have access to that client side code and as you can assume if we have access to some kind of code and if you have access to information and you know how stuff moves then it enables us to create a gateway of f word ups. So yeah and before you guys uh sue me let me tell you that we are obviously going to see stuff beyond the basics which are the hardcoded stuff like API tokens,
secrets and passwords etc. and examples will include. So these are the examples. Uh of course we have we can have the hardcoded secrets in the JavaScript code. We can also have undocumented undocumented endpoints which are basically endpoints which you will not find anywhere in the flow of the application but they are documented somewhere in some form in the JavaScript. We also have flawed custom functions and critical logic on client side. So this basically means that some kind of critical logic or calculation is happening on the client side itself instead of on the back end. So these are a few examples of what we are going to see ahead. Now let's dive into the technical aspects of JavaScript and client side
stuff and for that let me hand over the mic to Kulib and he'll take this forward. Thank you. So thank you so much Satam for the introduction. Uh now we'll see all the technical stuff and uh very uh small and uh big uh what do we say tips and tricks about JavaScript. So next so the technical agenda for today will be unminifying JavaScript then making sense of JavaScript source maps. Then we'll see how to override JavaScript and how to unbundle JavaScript. So first up we'll see JavaScript unminifying. Now if you open a web application and before you even try to analyze uh any JavaScript you'll likely see spaghetti code that looks like this it doesn't mean anything to you because
we are not robots. We cannot understand minified code, right? For us to analyze something or or to even makes any sense of JavaScript, we'll need unminified code. So now I can already hear some of the AI bros in the back saying that just throw this into GPT. Just give it to GPT. It will give you unminified code. But let's be honest, that's not practical because context of AIS is limited. If you throw it uh JavaScript files are very large. Uh in fact in production application JavaScript files are large because they are mostly bundles and AI has limited context. JavaScript files may be like 8 8 to 10 megabytes of megabytes of size but the context might be like 2048 bytes or
something something like that. I'm not an AI bro. So one technique that you can use is in the previous file the file name was barrack dot min.js but if you want to uh minify the file you might try you might try simply like barrack.js JS you you may remove the main keyword from the file and it might it might show the unminified file like this is purely luck based it might be your luck if you see the unidentified file but this works in like uh 3 to 10 3 to 10 files. Next up we have JavaScript unmapping. What is a webpeg? When you create a web application using React, it will create a webpe. The webpeg looks something like
[Music] this. Let's go. In a webpeg, you will see lots and lots of comments and it uh and references to Webpack. Like in the first line, you can see it says Webpack bootstrap. Many of you may have seen files that look like this. And at the at the very end you can see there is index.js.m map file. So what is this map file? If you open if you open the file it looks something like [Music] this. So here this is the typical syntax of a map file. You don't need to understand the syntax because we'll just throw this into a tool and the tool will unmap the file for us. Next. So the tool is called unmap. Here
you can see we are throwing the app dot js.m mapap file into the unmap tool and the and the unmap tool will take the file and uh and unmap the actual webpack into individual source files. So here we can see the file is main typescript file. The indivi the the file that we initially had was index.js JS with a lots with lots and lots of Webpack stuff. But here we say that we have main.typescript. This is the actual file that the developer [Music] wrote. Next we'll see some of the limitations of BJS linkfinder tool. Now many of you including myself use this tool but this but even this tool has its limitations and we'll see how. This is
the typical output of the bug jsls lenfinder tool. You can see there are some endpoints and
urls. Now here in the screenshot you can see that there is a request to API v1 leaderboard. But if you search the output of the bub js linkfinder you can see that the leaderboard endpoint is nowhere to be found. So the front end application knows that the endpoint is present. The back end knows that the endpoint is present, but the bubs linker tool doesn't show us like it's not the tool's fault because it uses rejects and the front end applications are constantly changing. So, it can't keep up with with all the changes. Next, so to overcome the limitations, here are some strings that you can search for in in the JavaScript files. The first one is B URL. The next
is B URL and so on. Now the most success that I found was using the base URL string. Almost every f every JavaScript file that I saw this uh this string in, I I definitely see many hits. Now let's see a quick demo. Here is JavaScript file. If I search for API URL, you can see there are zero matches. If I search API and URL just API URL, we see that there is one match but uh no direct endpoint is revealed here. If you search for HTTPS, there are 19 matches and many endpoints are shown. So this is a good starting point. If we search for / rest or rest/ similar variations, there are no matches
to be found. Next, if we search for /v1, you can see there are some endpoints. For example, there is API v1 programs. Then there is I think almost all of them are API v1 programs. But here you can see if if we search for base URL, you can see that this API v1 admin programs is generated dynamically from the base URL variable. So this is how we know that uh this endpoint is uh is existent on the back end. But if we use if we just you rely on bubs link finder we'll not find this entity many times and it helped me achieve many great bounties. So before we start with overriding I want to tell you that
JavaScript is a piece of code that is sent by the server but it is running in your machine your own machine it runs in your browser. So if something is running in your machine then you should be able to control it correct. So JavaScript overriding is exactly that. JavaScript overriding is modifying the JavaScript that is sent by the server and modify it to suit your needs to suit the application that you are testing. Now why do we need to even override things? Because we are not paid to do this stuff. The developer was paid to write the JavaScript file. Correct? Why do we even need to modify the JavaScript that was wrote by him? because we we need to modify the
JavaScript to overcome tricky client side encryptions and we can also use this to find dynamically generated endpoints. Next, next up we'll see a case study and a demo. So this was this was a b this was a report in a public program that it was my first public program bounty. So this is very close to my heart. So upon opening the page, it was a simple 404 page. Now most of may like just throw the domain away by just seeing this page because it's a 404 page. There is no attack surface later, right? Many experienced people might try to brute force the brute force here. But even after brute forcing you won't find anything because uh this is running
currently local on local host and I know there are no files here. But if we click multiple times on the image of the dog we can see an alert saying dev mode enabled. So this is I actually I actually found this thing in a production application by a multi-million multi-billion company. This might look something uh straight out of a CT but this is actually uh this was actually found in a production replication. Now after after the demo it was enabled. Many functionalities were visible to me. The first two were login and sign up obviously. So I created an account. So I created an account and I tried to login but when I tried to login
the request the request body was encrypted the request response was encrypted and the whole request was signed using [Music] hmeag this this meant that if I replay the same request in repeater tab it will be it will not show any response. It was a single use request.
Next and the nons that you saw in the previous request was retrieved from the API v1 keys endpoint. So to sum it up the application flow looks something like this that once we enter the credentials the the application was sending a request to API v1 keys. It was retrieving the nons it was retrieving the a secret key. It was retrieving the hmeag key and then it was encrypting the username and password. After that it was concatenating the nons to the URL and then calculating hmeag using hme key and uh hm key the url and the request body and then it was sending the whole request. So that is why the request that we saw previously was totally encrypted.
Next. After logging in, we see there are two more functionalities that are available to us. The first one is consultations. Sorry, consultants and the other other one is my consultations. If we go to the consultants functionality, we can see there are four consultants. One one is barracks sensei and so on. If we click on book consultation, we can see the consultation is available in my cons in my consultations. Now upon clicking the show details button that we saw previously a request to API v1 orders and then order ID was sent. It was a get request so it did not have a request body. This just makes life easier for us. Next up, we'll see how I managed to
override the login function so that I can login with arbitrary credentials and even maybe brute force them. So, we can we can override a JavaScript file by just right clicking and clicking override content. If you are doing it for the first time, the browser will ask you to select a folder where to the where to save the over overridden files. So, we click on override content and here is the do login function. This function is doing the actual this function is sending the login request. So you can see there is a uh there is a function called to this.process request then API v1 login along with the request data and the post and the post uh request
type. Now previously the function didn't have anything but we overrode the function and added a simple console.log. Why did we add a console.log? We just want to see that that the uh that the JavaScript is actually being overridden or not. If the JavaScript is being overridden, then we'll maybe add anything uh any other code. So we try to login and here you can see a log in the console that says I'm overridden. That means that we have successfully overridden the JavaScript file. Now to actually get access to this process request function, we need to export the this object. So we do it by clicking window. HTTP equals to this. This will this will make sure that the this object is
available from our [Music] console. Now once we have exported the object, we can uh directly use it by typing this.process process request and we'll be able to use the process request function directly from the console. Now we can send any type of request that we like without having to worrying without having to worry about uh any signatures or any encryptions. So here for an for example I'm sending a login request to API v1 login along with the username and password of AAA and it is a post request and you can see the the request is successful and the response says login true meaning the login is successful as
well. Now the orders request look like this API v1 orders as I showed previously. Now there might be an ID here. The ids are numeric. So how do you even uh start testing this? So we'll see how to detect detect and exploit this ID door manually and using JavaScript. So if we try to do this manually, you can see the first time the first request we are sending is API v1 and the order ID is 10. That says 404 not found. We change the order ID to 8. It's again says 404 not found. We change the order ID to 7. It again says four 404 not found because these order ids may or may not exist but we don't
know that yet. So you can see the pattern here. We have to change the order ID every time we need to send a request. But this is not feasible. If we want to send if we want to enumerate order ids from let's say one from a th00and we can't go on and type uh and call this function every time. that will take way too long. So to overcome that problem, we can simply use a for loop inside the console. The for loop uh the example for loop here starts from 1 and it goes to 10. So we are just uh checking if there are any orders from 1 to 10 and right off the bat we see that the order ID one
is found. It the order ID one is by user ID also one. But if we check in the in the work screenshot our user ID is four meaning we are able to retrieve orders from another user and all of this was automated by by this phone loop. So to summarize, we found we found a page, we found the hidden error mode, we logged in, we signed up, we signed up an account, then we logged in, then we found the orders orders functionality and we exploited it using JavaScript to retrieve orders of other [Music] users. Now, here is some more content. This uh this actually doesn't belong to web application but uh this this belongs to mobile application Android and iOS
application but this is this also contains JavaScript and this talk is about everything JavaScript so that's why it is here. So what is a what is a bundle? First of all, a JavaScript bundle is a combin is a combination of all the client side code along with all the libraries so that the application can run without having to having to access the uh external libraries using internet. If you are if it is an Android application, the file will be index.android.bundle. If the application is an iOS application, the file will be main.js GS bundle. How do you know that a file that that is index and Android bundle is a actual JS bundle or not? So you can
simply run the file command on the bundle and it will say how much JavaScript bite code. So that's how you know that it's a legit bundle. You can also simply try to c the file and it will throw random coverage. Again we are not robots. We don't know all of that what all of this means. Next to to convert all of that gish into into something that we can actually analyze and something that we can make sense of we can use the hermas-dec tool. This this actually Hermas DC tool contains lots and lots of uh lots and lots of many many tools that we can use to analyze this. Next go one of one of them is HBC-d decompiler. So
this is part of the herd- dc tool set. How do you how do you unbundle a bundle? you you simply write hbc-d compiler then the bundle name and the file to which uh we want to store the output after the tool is uh done running you can see the output shows something like this this is not uh actual JavaScript this is just uh this is basically something that you can make sense of next up we have a case study in this bundle thing. So this is this was in a target on synag team where I found AWS secret keys inside a JavaScript bundle. So first I just simply decompile the file using APK tool APK tool d then
the file name. Next then in the assets directory I found the index.android.bundle file. We you can see we ran the file command and it shows that it is a hermer JavaScript bite code. I ran the file through HBC decompiler tool. It it showed the output in the unbundled.js file. And in this unbundled js file uh I search for strings like base URL B URL API URL API URL and so on. So first we search for B URL and it showed many many [Music] URLs. Next up I tried searching for secret. Now when I search for secret secret you can see there are v various uh various things that match secret and one of them was AWS secret keys.
Obviously I'm not going to show the screenshot here and and while trying to trying to take screenshots of for this particular presentation I came across more secrets inside this file that I didn't initially found. So that was at it about the technical side of stuff. Next up, Satyam will take take you through mindset stuff and and more about how he found he how he finds many crazy bugs through just through mindset. So over to you
Satam. So thank you Guli for all the technical insights. Now for the people who are sleeping or who might be as lazy as me, let's see what is in store for you guys as well. Uh we were supposed to remove this. Okay. So almost every one of you might have especially in India you might have that one annoying neighbor who keeps on asking you questions and who want to know each and every detail about your life. Right? So this is the mindset that we need to have when trying to analyze JavaScript files or manually looking into the client side code. Keep asking what if. Assume that the developers are lazy like me and stop taking things at
face value like that annoying neighbor and try to find every intrinsic details about the code or the analysis that you are doing on that file. So for example and to back this this is just a snippet of JavaScript code that I came across in an application which I was testing on and after 2 to three days of tinkering around this is some thing which I came across and this might not seem trivial but if you look closely there is a space in between the bearer and uh the token when it is getting appended. Now I'm not sure if this was the exact reason of the bug that I found but this uh this seemed interesting to
me and I tried a bunch of things. I tried a bunch of things but finally if you can see uh by providing just a single space after bearer and passing that as an authorization token I was able to bypass the authentication of the web application. So anything if you try to provide anything apart from a single space you uh you are thrown a 403 or 401 forbidden code and you are not able to you know access that uh that particular resource and this was just around one or two months back I guess. So welcome to 2024. This was a subdomain of the same target and for this the same thing did not work. A single space was not
working. So instead of that I again tried a bunch of different things but as you can see any alpha numeric character just a single alpha numeric character if you append after a beer we were able to bypass the authentication and access all these endpoints. So this was again welcome to 2024. Now how many of you have been in a situation when you know and you are certain that there is absolutely nothing in the fridge but you still keep opening it and in the hopes of finding something new. How many of you guys have been there? So great. Now that is again another mindset that I want you guys to have when trying to perform bug bounties
or bend testing or whatever it is. Right? So always assume that I'm stupid. So that means like for the first two or three times you are trying to analyze that file or that application you are not going to find anything stubbornly unless and until you do not find anything in that application don't move on even if it's a very small trivial thing as we saw in the previous example if I had just given up like every nothing is working then I would have I wouldn't have found that critical bug and assume that everyone is noob the bug that kulp showed was found in a public program and it is a very mature bug bounty program so a lot of hackers
already might have looked at the you know at the target probably but assuming that it was it would have been found or something like that then we would not able to have found that issue as well. Now for another example, here is just a GraphQL query which I had found in a target. This was probably for Sync if I remember correctly. And this is just a query which uh creates a referral code, right? So the issue here was this is a target that we usually keep on hunting and coming back to, right? So two to three months back there was a similar query which which was present in the application that we found through the
JavaScript code that uh which which was referral details and it was exactly the same endpoint and exactly the same query and returned exactly the same things that referral detail returned but referral detail was not present 2 to 3 months back and it was not present on the on the target when we were testing initially but after we we already had reported referral details and we had already awarded bounty for that. Now two to three months back again we found referral detail and we again reported that and we were so certain that uh it would not be accepted in the first try that that we we also added a comment with the screenshot saying that this is
not a regression and it's a completely different query so that the tri do not get confused but as expected they initially rejected uh our vulnerability saying that it's the duplicate which contained the exact same query and method but finally they had to agree that they it looks like we missed the s. So this was just to show you that how trivial or easy things can be and we do not make we do not need to make everything so complicated. Now let's just see some other examples and case studies so to back the mindset part. Now this was another piece of JavaScript code uh for another application that I was testing on and I tried a bunch of different
things. If you can see there is a path or query uh there is an API path which is being formed. Now here I tried a bunch of different things and I replaced the ID and X with numeric stuff and tried a bunch of different things but nothing was working. It just keep throwing a 404. But what interesting part I noted was after the test API if you see there is no slash. So I got curious and I just tried this and it worked. So basically I don't know if the developer did it by mistake or if this was intentional but instead of test API/ API if we if we provided test API API without any slash that led us to bypass
the authentication and access for the endpoints. So this was again very simple and this was just a piece of code that we found in the JavaScript file. Let's see another example now for the idor part which kulp shared with us. He he probably shared the target with me and he explained to me the scenario of one bundling and minifying and everything 2 to three days after uh two two to three days after that and I was just exploring the the target which uh which we are discussing on and I was just uh uh the objects the request as we saw as we saw were all encrypted and I was just exploring the console part and
opening all the objects one by And in that we found I I don't think if it's visible or not but as you can see there are current addresses which are being disclosed directly to any end user. Along with that there were also PAN cards and Aadhar card numbers being leaked as well. And for this we I hadn't even opened BSuit itself. So this was just basically F12 hacking that all the Twitter bros keep telling about. So that was it and uh that was all for the talk and for the key takeaways as we as you saw like nothing is obvious. Ask stupid questions, try stupid things. Nothing is obvious. You you don't know how the developer is thinking. What is
their what is their mindset and how are they going about things? Find your thing. It can be recon. It can be automation. It can be manual hunting as we saw. But find your thing and try to be as good as possible in that. Keep things simple. Explore don't abandon. So if you are good at JavaScript or let's say recon, always try to explore different things or let's say AI is getting crazy nowadays. So explore those things. Try to learn new things but do not abandon the basics and you know keep forgetting that nothing is obvious. Stay hungry, stay humble and don't collaborate. Don't just collaborate. Make friends so that when you find such lazy bugs there can be
friends like Kulp who can explain you all the technical jarens and all that kind of things. So that was us that was it from our side. Thank you so much. And if you have any questions, we'll feel free to ask. [Applause]
Yeah. Hey guys, it was really a nice talk. So I'm loveless Jooshi and actually it was nice demonstration, nice PBD and all. Thank you. Yeah. So I have a really basic question. So when you explained around the ReactJS applications, so these days only a specific bundle is loaded in the front end, not the entire application, right? So how do you guys like what is your approach to test that particular application? Because a specific bundle is loading and there might be hundred of bundles, right? So how do you guys automate that thing? Do you download each and every bundle? How do you inspect those things? I think Pul will be able to answer that better. Yeah. Oh, actually I don't
automatically anything. If there are like 50 bundles, I will download 50 of all 50 of them and analyze all of them manually. So that's just me. Okay. So there is no automated process. No, sure there are a lot of tools available, right? Everything you saw there is probably a tool which might be able to do it better. But as you saw that AI or the tools they they lack context and clarity like they do not follow intuition they follow rejaxes they have a you know a specific set of rules that they follow and repeat over they if if for example let's say I when I when I showed that bug where we just included a single space if we if I had
you know automated that through a tool it might have missed a tool or scanner might have missed that because that's just our human intuition that we you know we We tend to dive into rabbit holes. We tend to go with our intuition. That doesn't happen with automation. So I'm sure there are a lot of there might be some tools which we are not currently aware of to automate that kind of thing. But this is just our approach and we like to keep things simple. Cool. Cool. That was nice. I have one more question. In the start of your talk, you mentioned that uploading a JavaScript file to a AI tool basically any chat GB or so is not
recommended and you said around the size like around 8 MB or so I guess. So I mean have you guys tried to upload a zip in AI and all like you could just zip a application and a code. No actually I tried to upload it I do try to upload it to an AI but uh obviously it said that the file is too large. I cannot analyze it. Oh my god. I guess you should try some new models. But yeah guys, it is available in these. We can upload a zip and it does the good job actually. Okay, I will definitely try it. H yes yes. Oh yes, thanks. It was a really nice talk. Along with that
if you usually we don't want to analyze each and every aspect of the JavaScript. There are there are there might be billions of things in JavaScript. We just are more we just have a more concentrated approach that if we are finding some custom function if you are finding some critical logic that you might think might not be on the client side then you can you can focus on that parts and you can definitely you know throw those parts into uh AI and then you can analyze that as well. So it it works that way as well.
Hello. Uh thank you for the presentation. It was very nice. So my query regarding the one with the kulp show it was the overriding part. So could you could you move the slide to that part overriding? I have a couple of question on that part. Yeah, sure thing. Uh just tell me when you want to want me to stop. uh to the one where you edited the code and you mentioned the overriding
part. No. Yeah. This one. Yeah. Yeah. So the here you me here you like uh modified the JS file. Correct. So it is a server side where you modified or it is like after overriding you it is I modified it on the client side only because uh if you can modify on the server side it will be basically remote code execution. Correct. Correct. So basically like basically you edit it. I never came across this scenario. So basically you save the file you edit it and after like after that you uh so while like the server is taking the client side input not the server side. So basically you modified this part right and after you log you enter the
input right correct. So after that in the console you got this uh I am overridden right correct. So basically the client side where you have modified and it is reflected. So basically we are telling the browser that do not use this the JavaScript file that is provided by the server. Use the JavaScript that I will provide. I'm the one who knocks. That's good. That's good. And there are a couple of question as well. So have you come across the JSinder? The couple of scripts are available basically in order to find the sensor details in a Java JavaScript file. JS finder a couple of scripts are available. So you might have you have come across such script
automated script. Now is it are you asking like for BJS link finder or any other scripts? Uh it is random finder basically in order to find the sensory details in a javascript file. So is it a worth just wanted to ask. Yeah. Oh, there are many tools available but uh we mostly follow the manual approach. I mostly follow the manual approach. That's good. That's good. Yeah. Ah, thanks Vir. So, thanks Kulan team. Thank you. Yeah,
I have a same I mean doubt in the same page. Uh it might be a dumb one. I'm sorry. Uh but uh I mean this is a local you have made a local copy of the JS file and you have loaded it from the local storage right I have done a similar thing with the you know chrome dino game right I have automated the dyno to jump on its own detect the obstacles and all I do understand that but the thing is it is a local copy so it this version of the copy exists only in your laptop or PC or anything so what's the impact of this bug what's say impact like what happens
So we are overriding it on the local file system. But why are we doing it? We are doing this so that we don't need to see the JavaScript failure. The JavaScript file here knows how to encrypt and sign the requests. We have the AES keys, we have the hm, we have the nons. We can do it ourselves. We can send the whole request by ourself. But you can do it for maybe one request, maybe two requests, maybe 10 requests. But for if you want to do it repeatedly, you might want to use uh some sort of help. So this is the help that we are talking about. We are overriding the local JavaScript file so that we can
send HTTP request just directly from the console so that we don't have to do it manually. So uh if you want to do manually, you can just go to the console and call the function directly. Correct. That's what we did. Uh to make that process uh happen every time you want to do it, you edited the file. That's it. Correct. That's that's all. Okay. Got it. So, this is not the vulnerability. This is just a uh what do you say? A handy tool approaching the problem. Yes. Correct. Okay. Yeah. Got
it. I think that's it. So, we'll conclude. Thank you so much.