JavaScript Enumeration for bug bounty hunters

JavaScript Enumeration is a critical skill to have if you want to level up your penetration testing or bug bounty hunting game. Yet, not everyone does it, partly because it is a boring exercise or it consumes most of your time, not to mention how intimidated you might feel reading someone else’s code. Today, we will explore this topic and understand why it matters, and how you can perform it.

Hopefully, this episode will help you overcome these hurdles and give you the tools you need to make JavaScript Enumeration less painful. We will first understand how it can lead to serious security bugs. Then, we will discover different ways to properly do it. So, stay with me until the end because you will definitely learn some hacking tricks along the way!

Why JavaScript enumeration matters?

If you don’t perform JavaScript enumeration during your hacking engagements, you are overlooking a vital portion of your target web application. In fact, JavaScript powers the client-side; meaning that all the logic that happens before hitting the back-end server is there. Think about it, you have half of the code that you can look through, and code never lies! If there is an error, the code will tell you, you just have to look through it.

Let’s first discover what you could find with JavaScript Enumeration.

JavaScript enumeration can give you easy wins

Because of bad coding practices, the developers can unintentionally introduce low hanging security bugs in the JavaScript code, ready to be exploited by entry-level hackers. Sloppy coding can include hard-coded credentials, hidden web page URLs with no authentication, or even back-end API endpoints with broken access control flaws.

For example, by simply enumerating the code for API endpoints, you can find some unprotected ones. If you want to learn a real-world example of how I found a serious account takeover flaw, make sure to read this article.

JavaScript enumeration helps you understand how the application works

While you are looking through the code for hard-coded credentials and API endpoints, you will naturally get a feel of the structure, the coding style and what the web application does. If you don’t get that, don’t worry, it comes with practice; the more you do it, the easier it becomes. We will explore shortly how you can start doing it.

JavaScript enumeration can give you deep and serious bugs

Besides the low hanging fruits which you can find using JavaScript enumeration, you can uncover hidden issues which fewer people are looking for. These are typically DOM XSS vulnerabilities that you can exploit through postMessage events or the usage of dangerous JavaScript sinks and sources. For example, a developer might use the path part of the URL to populate the DOM using the sink innerHTML. In this case, you can inject malicious JavaScript code that will be reflected in the DOM without proper encoding, leading to a DOM XSS.

If you want to learn and practice DOM XSS, you can visit Portswigger’s article.

JavaScript enumeration simplified with tools

JavaScript enumeration can be intimidating, hard or time-consuming. If that’s the case for you, maybe you are doing it the wrong way! If you jump onto random JavaScript files and look for low hanging fruits only, you might get lucky once, but you won’t find great and consistent bugs. At least you won’t cover the entire attack surface. Instead, I suggest you first extract all JavaScript files, then browse through them, and then you can focus on specific parts which seem interesting.

You can use various tools that will assist you during this exercise. These are the ones I found helpful, but if you prefer other tools, feel free to suggest others in the comments.

Step 1 in JavaScript enumeration: Extract JavaScript files

Sometimes all you have is the login page, that’s fine. Once you finish browsing all the accessible features, your web proxy should have recorded all the JavaScript files. I like to use BurpSuite Professional to extract them all at once, but you can use other alternatives, such as manually downloading all the JavaScript files from BurpSuite Community Edition (The free version of BurpSuite).

To do that, you right-click on your target root entry in the Sitemap, then choose the Find scripts option under the Engagement tools in the contextual menu.

JavaScript Enumeration using BurpSuite Find scripts feature
JavaScript Enumeration using BurpSuite Find scripts feature

From there, you click on Export scripts and choose a file to store them. I like to store them because I will be using the next tools to look for specific things, like endpoints, secrets, etc.

Saving all the scripts into one single file
Saving all the scripts into one single file

Extract JavaScript using free tools

If you have been following this blog, you know that the bug bounty community has published many awesome tools which you can combine to get the content of JavaScript files. I like to use waybackurls and the built-in bash commands xargs, curl and tee. You can find many more on this article. Here is a one-liner that will do the job:

waybackurls target.com | grep "\\.js" | xargs -n1 -I@ curl -k @ | tee -a content.txt

The above one-liner will collect all publicly available JavaScript files using waybackurls. Then, it filters only JavaScript files. From there, it grabs the content of each file using curl. Finally, it stores the result in one file.

Step 2: Beautify the JavaScript code

From my experience, most of the JavaScript files get obfuscated and packed into one single line. Therefore, it’s hard to deal with them as they are. Luckily, there are tools which help at least structure them into readable JavaScript code. The one I use is Jsbeautifier, a command-line tool that accepts a file as input and beautifies its content, unpacks it or deobfuscates it into a resulting file.

First, you install it using pip: pip install jsbeautifier. Then, you run it with js-beautify -o outfile.txt scripts.txt. This will output the file outfile.txt which you can easily browse through.

It’s time for the next step: finding the juicy data we are all looking for!

Step 3: JavaScript enumeration with Grep and the family

Now that we have a readable version of all the JavaScript code in one place, I like to start with Grep to get a feel of what I am expecting. The general command is grep --color -i term outfile.txt. You just change the word term with what you’re looking for. For example, try words like secret, admin, password or token to find hardcoded secrets. Alternatively, you can use a path prefix to look for endpoints. Say you noticed that all API endpoints start with /api/v1. In this case, you can substitute the word term in the grep command with /api/v1 to collect all the API endpoints.

Once you grab some endpoints, and hopefully some secrets, you can focus on areas of interest within the JavaScript files.

Javascript enumeration using Chrome Dev Tools

If you don’t have BurpSuite Pro or you don’t want to parse the entire JavaScript files, you can use your built-in Web Browser Developer tools. I like to use the Chrome Browser.

Look for keywords across the entire website

In Chrome, you can open the Developer Tools using the shortcut Command + option + I on Mac, and Ctrl + Shift + I on Windows. From there, choose the Sources Tab. Once inside, you will see the different files in a tree on the left. Hit Command + option + F on Mac, or Ctrl + Shift + F on Windows and a search menu will appear in the bottom. Type the keywords you found from the previous steps to locate where exactly they appear in the client-side source code.

JavaScript Enumeration using Chrome Developer Tools
JavaScript Enumeration using Chrome Developer Tools

From there, click on the one on the right of the results, which will load the JavaScript file in the main screen.

JavaScript enumeration within a file in Chrome Dev Tools

Once you choose a JavaScript file, it may appear obfuscated or minified. Don’t worry, Chrome can make it readable. You just have to click on the Prety-print button. Alternatively, there is a button named {} on the bottom of the screen, which you can click as well.

The Pretty-print feature in Chrome Developer Tools
The Pretty-print feature in Chrome Developer Tools

From there, hit Command + F on Mac or Ctrl + F on Windows and look for your keyword, such as api_key.

You can search for keywords inside the beautified JavaScript code
You can search for keywords inside the beautified JavaScript code

JavaScript Enumeration using breakpoints

Once you focus on a particular snippet within a JavaScript file which brings your attention, you might find it hard to understand what the code does. This can be due to random variable or function names, or simply because you can’t understand what the code does. In this case, you can set a break-point on one or multiple lines, then refresh the page.

Using breakpoints to pause the execution at areas of your interest
Using breakpoints to pause the execution at areas of your interest

Once the client-side code hits your break-point, you can debug it like you would do in any Code Editor using the controls you have on the menu in the right.

You can use the control buttons to debug the JavaScript code
You can use the control buttons to debug the JavaScript code

JavaScript enumeration examples

After mapping the application, collecting all JavaScript files, looking for interesting areas and debugging the JavaScript code, it really depends on your experience and creativity to find interesting bugs. However, without the prior steps, you wouldn’t be able to focus on the areas that matter. The following are examples which illustrate what hackers have found using JavaScript enumeration.

PostMessage DOM XSS vulnerabilities

In this great article, Mathias explains how he performed JavaScript Enumeration using the very steps you discovered earlier to find and exploit a DOM XSS vulnerability due to a misconfiguration in the PostMessage event handling.

Exploit a token leak to disclose your Paypal password

This blog post explains how Alex, a Security Researcher and bug bounty hunter, could exfiltrate your Paypal password through a token leak. He started with JavaScript enumeration and found an interesting endpoint that he was able to understand and exploit.

Conclusion

Hopefully, you now understand why you should perform JavaScript enumeration. But most importantly, you have a methodical approach and the tools to help during the process.