Console Wars Part 1: Hacks for Hackers

By |Published On: December 2nd, 2021|Tags: |

Fight JavaScript with JavaScript

For a hacker, using a proxy to bypass client side protections on a website is one of life’s simple pleasures. I don’t care if your HTML form does not allow special characters, my intercepting proxy does. Sadly though, I find this joy turning into frustration. Websites are not as simple as they used to be, and this complication can make testing even simple things more difficult. It’s easy to point fingers and blame JavaScript for all this, so I will. 

How do we go on though? How do we get the joy of pentesting back? 

As with most JavaScript problems, the answer is more JavaScript.

The Power of the Console

JavaScript is more powerful than the user interface. Anything a user can click, JavaScript can “.click()”. Plus, there are things hidden in the HTML that the user can’t click but JavaScript can. This is all done via the web console. You can usually open the web console with ctrl+shift+i. 

Let’s start out with a simple example.

Warning: Never type anything you don’t understand into the web console. The power of the console can be abused if someone tricks you into pasting something malicious there.

Adding Features Ourselves

We will start with my favorite console trick. It’s an innocent little one liner from @netspooky that has helped me get through more than one security training. If you are watching a video but you can feel your attention span tugging you elsewhere, you can try speeding up the video with this trick:

Copy to Clipboard

This uses querySelector to find the video in the page and update its playback to run 25% faster. You would be surprised how often this just works. This will work even if there is no explicit speed control on the video itself. JavaScript is more powerful than the user.

Bookmarklets PSA

The JavaScript schema can be used in bookmarks. Surround your favorite JavaScript one liner in the strings javascript: (() => {` and `})(); and save that as the URL of a bookmark. Then when you click the bookmark, the JavaScript one liner will execute in that current web page. This is called a “bookmarklet” and you can find various people who collect some good ones. For example, you can name a bookmark “>>” and set the URL to:

Copy to Clipboard

Now when you click the bookmark, the first video in the page will increase in speed by 25%. This, in theory, can be applied to any of the tricks found here.

Simplifying Reporting

Not everyone is willing to dish out big bucks for Burp and get it set up. Everyone does, however, have a web console. 

During a recent penetration test, I found an access control problem using Burp. I replaced an admin request with a low privileged user’s session token, and the back end server still accepted the request. Before I reported the finding with a bunch of ugly HTTP request junk and Burp screen shots, I checked the web page itself. The server does not prevent users making admin requests, so what in the client does? 

It turns out, the admin tools were right there in the page. The tools were just not visible. So, I sent the client the following JavaScript:

Copy to Clipboard

Imagine how much time this saved the client. No need to get a proxy or hand craft HTTP requests with valid authentication tokens from low privileged users. The client just logged in, pasted my code in the console, and then used the admin panel that magically appeared. It felt like I was sending the client cheat codes for a video game.

The First Pentester Restriction

Being a security guy is kinda funny sometimes. We yell about how security is more important than convenience, and then we are stuck with programers who actually listened. 

A few years ago, I was testing a website that logged you out if you are inactive for 5 minutes. If I remember right, this was all implemented with websockets. I wanted to use Burp to fuzz some things on this website, but if the scan lasted more than 5 minutes the scanner would have its session killed. Logging in was a multi-request pain (No MFA back then, but could you imagine?). My solution was just a single line of JavaScript.

Copy to Clipboard

This is a great example of using what the developer gives you. There was an obvious JavaScript function that got called on every click interaction. The function was even named something obvious (names changed here to protect the innocent). So, we just call that function and let the developers code work for us. What if the function was not so easy to find? Should we reverse code looking for it? No! What keeps the user authenticated? Just tell JavaScript to do that every 4 minutes:

Copy to Clipboard

No need to reverse engineer anything or check for a dead session and automate authentication. You don’t even have to do math or get a calculator, just let the console do the work. Just make sure you don’t “.click()” something that causes the page to refresh or the URL to change.

The Birth of Eval Villain

An easy way to get quick wins on testing code is to grep for dangerous functions. In C you might grep for “system”. In JavaScript you grep for “eval”. I consider eval to be a lot scarier than system because of its confusing scope

In theory, these dangerous functions should be used very little so that they can be easily audited. Usually I only see a couple of them in a code base. Many years ago, I was testing a web application that used eval for everything. It had stuff like var a = eval(“2 * x”);. More significantly, it used eval to parse all the responses from a JSON API. Most API responses were static or lacked any user input, but how could I find the ones that I could play with? Here is my initial solution:

Copy to Clipboard

This ends up printing way too much stuff. It was like searching for a needle in a haystack. So I started checking if the arguments to eval included my own defined needle. 

Pro tip: In the FireFox console, you can get a nicer area for scripting if you click the icon that looks like a book page. This will give you a side-by-side view of a text editor and console output. 

Here is the upgrade shown in the side by side view:

If you want to make this trick even more streamlined, check out the reflect and proxy JavaScript functions. I ended up using this trick so much that I started adding more and more features. I started hooking .innerHTML and document.write. Then, I added needle highlighting. Eventually I had a grease monkey script. I then turned it into its own FireFox extension.

I mention this for two reasons: 

Eval Villain is my first baby, so as a first time father I will take every opportunity to show off baby pictures. 

Secondly, I want to show the power of hooking and web extensions. It turns out web extensions are trivial to throw together. If you end up relying heavily on a JavaScript snippet in the console, consider throwing it in a content script. It can save you a lot of time pasting code, and you can configure it to load before any of the pages JavaScript has a chance to execute (run_at: document_start).

Obfuscated SQL Injection made Easy!

This is my biggest console win, but it will take a while to explain in full. I was auditing a very important application, and I was told this application had already been scanned by several fancy web scanners and no vulnerabilities were found. I should mention here that this test happened a while back, but SQL injection was already becoming more rare. Most web application frameworks had already tried to hide the raw SQL query API in favor of an API that prevented injection by default.

At the start of the test, I found the web application has a multi-request login process. After logging in, I reviewed the requests in my proxy. I couldn’t find the credentials I used in any of the requests. So, I log out and log in again but intercept the last request of the login process. There I see a giant base64 encoded blob being sent to the server. I base64 decode the blob (psst atob) expecting to see JSON or something. Instead, I get an ugly binary blob. It was starting to look like the credentials were being sent encrypted, serialized, obfuscated, or compressed. Later I learned what was going on, but for now let’s just call the request obfuscated.

Let’s take stock of the situation for a moment: 

  • The most important request for the security of this website is some ugly binary blob. 
  • There is no way an application scanner would have tested this request properly. 
  • There is no way a Web application firewall will be inspecting these obfuscated requests for malicious injections. 
  • Additionally, I highly doubt the web framework being used has a nice SQL API for this mess.

This is all shaping up to be a perfect footgun. I need to test this API but how do I make my own obfuscated requests efficiently?

Sending Requests with the Console

My first thought was to reverse the JavaScript in the page. From viewing the requests in the proxy, I knew it had to be the JavaScript in the page that was making the binary blob. Viewing the single JavaScript file in the browser, I clicked the “beautify” button. For the next 10 minutes, I watched as the ram usage of my computer slowly crept up and the CPU fans roared. I only had a week for this test, and I really didn’t want to reverse this JavaScript mess.

Can I just use the web form and inject content? Not exactly, there are events that prevent the adding of special characters to the form data. You can’t just paste “username’ or 1=1–” into the form. You can bypass this with the dev tools, but because it is a multi-step authentication process, it’s a giant pain.

The solution I came up with was to use the console. In short, I went through the login process with bad credentials. At the very last step, I used the web developer tools to inspect the login button. This revealed my invalid credentials in the nearby hidden form. So, with 3 lines of JavaScript I could change the hidden form values and send the request. I could have used the “inspector” page to change the form values, but since I am aiming at automation in JavaScript anyways, I used the console. 

Once I hit enter in the console, my proxy got a big base64 binary blob request and the server told me I was authenticated.

Further testing proved the login was trivially vulnerable to a SQL injection authentication bypass. I did something like this (note: this code is just made up, might not even work. This is just to show the idea):

Copy to Clipboard

The above could be pasted into the console and authentication would be bypassed. This means, again, I have a proof of concept I can send to the client that does not require a proxy or fooling around in the inspector. They could visit a link, paste code in the console and be logged in as Admin.

Now SQL injection is not done until I have hashes–so next time on part two of “Console Wars,” I will write a binary search algorithm for blind SQL injection all in the console.

Moral of the Story

The JavaScript console is amazing. It can save you a ton of time and frustration auditing websites. Its unique position often makes it the most efficient way to bypass some restrictions. So, next time a website is sucking the joy out of pentesting, consider using the console to fight back. 

Stay tuned for part 2 of Console Wars where I’ll walk through how to write a SQL injection script in the web console.

Share with your network!
Get monthly updates from Hurricane Labs
* indicates required

About Hurricane Labs

Hurricane Labs is a dynamic Managed Services Provider that unlocks the potential of Splunk and security for diverse enterprises across the United States. With a dedicated, Splunk-focused team and an emphasis on humanity and collaboration, we provide the skills, resources, and results to help make our customers’ lives easier.

For more information, visit and follow us on Twitter @hurricanelabs.