July 16, 2020

Forcing Vue.js Application to Load with Dev Tools Enabled

The developer’s console is perhaps one of the most underutilized tools by application security professionals. Yet, there is a great deal of information that can be learned about a web application by dynamically exploring its client-side code from the console. Depending on how front-end code is loaded in the browser, you may manipulate the application’s behavior by calling functions built-in by their developers. This can be extremely useful when testing authentication and authorization issues in a web application. However, this is not always possible. In cases where the application relies on a modern front-end framework, you’d need to use a set of debugging functions (made available by the framework for development purposes) to access the context for the framework in use. In these situations, you’d have to force the application to load in development mode.

I have written a bit about doing this with Angular here where I discuss some advantages to loading Angular in development when researching an application. I also wrote a plugin for goRE that automates the process for forcing AngularJS and Angular applications to load in development mode. Back then, I saw mostly Angular and React applications, and not as many Vue.js applications. Since Vue.js seems to be a lot more common nowadays, I figured it’d be a good idea to find a way to load Vue.js applications in development mode.

But why would we want to do that? By manipulating runtime Vue.js variables from the console, you could, for instance, make the application’s client think that you are an administrator by merely typing Vue.$auth.user.isAdmin = true, though the specifics would vary depending on how the developers choose to implement client-side controls. Additionally, you could leverage Vue.js functions to list routes and API endpoints without doing the manual work of navigating the application and reviewing all unique API calls in your Burp history. Moreover, loading Vue.js applications in development mode allows us to use the vue-devtools plugin. Lastly, once we load an app in development mode, we could explore the code dynamically from the console, rather than having to deal with minimized code.

The trick to loading Vue.js applications in development mode is to change the application’s Vue.js code before it is loaded in the browser so that all devtools are enabled. This happens in the https://github.com/vuejs/vue/blob/dev/dist/vue.runtime.js file of the Vue.js source code.

When the application loads in the browser it will first check whether devtools are enabled, and load devtools (set of functions that allow us to debug Vue.js from the console and use the vue-devtools pluging) in memory:

if (inBrowser) {
    setTimeout(function () {
      if (config.devtools) {
        if (devtools) {
          devtools.emit('init', Vue);
        } else {
          console[console.info ? 'info' : 'log'](
            'Download the Vue Devtools extension for a better development experience:\n' +
            'https://github.com/vuejs/vue-devtools'
          );
        }
      }
      if (config.productionTip !== false &&
        typeof console !== 'undefined'
      ) {
        console[console.info ? 'info' : 'log'](
          "You are running Vue in development mode.\n" +
          "Make sure to turn on production mode when deploying for production.\n" +
          "See more tips at https://vuejs.org/guide/deployment.html"
        );
      }
    }, 0);
  }

The key then is to set devtools to true before Vue.js is loaded in the browser. The code we need to manipulate is here:

 var config = ({
    //...ommited 
    /**
     * Whether to enable devtools
     */
    devtools: "development" !== 'production',
    // ...ommiteed
 }

Now, because most likely the application code will be minimized, the above will actually look like this:

devtools:!1

We need to use a proxy with a find and replace feature such as Burp Suite to make the change before the code is loaded. In Burp, this is a match/replace rule you’d need to add for responses:

burp rule

All you need to do now is open the developer’s console and do a hard reload for the application (hold shift while pressing the reload button in Firefox), and you should see a message like this:

vue detected

Now you can obtain a Vue.js reference by typing the following in the console:

var vue = __VUE_DEVTOOLS_GLOBAL_HOOK__.Vue;

You can also select the root component for the Vue.js application in the browser inspector and type the following:

var vue = $0.__vue__;

At this point, you should also be able to explore the application using the vue-devtools plugin:

vue devtools

All there is left to do is manipulating the application from the console. For instance, depending on how the front end controls are coded, you may add additional roles to your account by typing something like this:

vue.$auth.user.roles = ["basic", "admin"];

Which may enable additional admin menus that you wouldn’t have been able to discover as quickly before. You can then test backend authorization controls by using admin features from the UI.

© hex0punk 2023