Skip to main content

Penetration Testing: JavaScript Prototype Pollution

Firesand: End-to-End Security for your Business

Introduction

This is our second article, this will not directly follow on from the first - though this is laying some ground material, and we will loop back later! This article then, will focus on an interesting security issue in JavaScript. 

JavaScript is a widespread programming language, used in both client-side (especially via frameworks such as REACT or Angular) and server-side (e.g. Node.js) frameworks. With the sheer amount of platforms dependent upon JavaScript security issues can lead to widespread risks. 

To better understand this article, it is useful to have an understanding of Object Orientation and how it has been implemented in JavaScript. As such, we have two primer articles on these topics on our website:

  1. Primer on Object Orientation.
  2. Primer on Object Orientation and Prototypes in JavaScript.

 


Audience

Who is this article for?

Understanding application layer security threats is important for a wide-range of professions, including:

  • Security Architects and Solution Architects, as they need to understand the potential risks and mitigations to take appropriate design decisions, such as access control.

  • Software Engineers / Developers, because they need to understand how to build their applications in a secure manner and avoid critical mistakes.

  • Security Consultants of various types as they need to understand the risks of what they may be reviewing or consulting on.

  • Penetration Testers who need to understand how to attack these systems!

 


Primer Recap

As discussed in the primer on Object Orientation and Prototypes in JavaScript, it is possible to modify prototypes dynamically. Prototypes are part of the mechanism by which inheritance (an Object Orientation concept) functions in JavaScript, and are defined at runtime, hence why they can be modified.

In the primer article, it was shown how it was possible to add a new method, or function, to an existing prototype within JavaScript. From a security perspective, so what?

 

So What?!

If we can add a new function, what else can we do? What happens if we try to reassign an existing function to a new value? Perhaps with code like the following:

Date.prototype.getYear = function() { console.log("Function Overwritten!"); };

The following screenshot, from the Mozilla Firefox browser console, shows the before and after effect of such an action:

JavaScript Function Overwriting

As shown in the screenshot, the behaviour of the inbuilt JavaScript Date type has been modified. From code that returns a numerical representation of the current year, to code that logs the message "Function Overwritten" to the console.

So far, this should demonstrate, that if an attacker can execute some JavaScript, they could certainly cause some disruption. Modifying inbuilt types to log messages would certainly causes some problems.

What else can be done?

Well, we can also grab a reference to an existing function, as the following code demonstrates:

d1 = new Date();
d1.getYear();

Date.prototype.getYearCopy = Date.prototype.getYear;

d1.getYearCopy(); // returns the same result as d1.getYear, as it is the same function

The following screenshot demonstrates this behaviour:

Copying prototype functions

An interesting thing to note with this example is that the effect is applies to all existing instances, not only new ones!

So, if we can both take a copy of an existing function and overwrite an existing function, what can we do with this?

 

A Man-in-the-Middle Attack on the Heap!

JavaScript stores its function data in memory, in the heap. (For reference, memory is typically organised into two main parts: the stack, usually for primitive variable types, and the heap, for more complex structures, including functions).

Earlier, we showed how you can overwrite the behaviour of existing functions, this certainly has some destructive capabilities. However, as can both take a copy of existing behaviour (functions) and then overwrite existing behaviour, we are able to add in, or extend, existing functionality with our own code.  

Lets continue with the Date class to demonstrate:

Date.prototype.getYearOriginal = Date.prototype.getYear;
Date.prototype.getYear = function() { 

  console.log("I've added extra behaviour before the standard implementation!");

  console.log(this.getYearOriginal());

  console.log("I've added extra behaviour after the standard implementation!");

}

d1 = new Date();
d1.getYear();

The behaviour is shown in the following screenshot:

Date getYear 'Man-in-the-Middle'

A Man-in-the-Middle (MitM) attack is typically focused on communications flows over networks, however, this attack allows us to MitM the functions on the call stack! A particularly neat feature of this is, this attack can be executed without end-users noticing, as the core behaviour of the function can be preserved, thus, not affecting the behaviour of the application from an end-user's perspective!

Obviously, this specific example is of potentially limited use, given the example function that we have selected. However, what other standard inbuilt functions can we apply this to? Well, any and all!

The next question is, would there be any particularly interesting functions? What about XMLHttpRequest.open and XMLHttpRequest.send?

These two methods are used, in conjunction, to enable a lot of modern websites to communicate between the browser and the back-end server/API. This starts to sound interesting, what if credentials are being sent via this method? What if credit card details are being sent? Other personal data? 

There are some barriers to this attack, most notably:

  1. How do we get the attack to a victim?
  2. How can we exfiltrate date, due to browser same origin policy controls and restrictions?
  3. What about Web Application Firewalls (WAF)? (Which will become more relevant as we discuss #1)

These will be discussed in subsequent articles!

 

Conclusion

Prototype Pollution is a very powerful technique, whereby existing JavaScript types can be modified in destructive ways, as well as more subtle, insidious ways. The latter, perhaps being far more interesting.

At Firesand, we see this as a particularly dangerous attack given the prevalence of JavaScript, and the ability to execute arbitrary code.

Chris Blake

About the author

https://www.linkedin.com/in/chrisblake/

Chris Blake has over 20 years of experience in the information and cyber security field, and is a passionate and qualified Enterprise Security Architect and Privacy Professional who leads and delivers innovative solutions at Firesand Limited, a company he co-founded in 2016. His specialities include application security, enterprise security architecture, and privacy, with a strong track record of building and implementing ISO 27001 compliant and certified information security practices, application security programmes, and enterprise security architectures. He has a thirst for continual learning and a commitment to excellence, as demonstrated by his academic and professional credentials from prestigious institutions such as the University of Oxford, (ISC)², IAPP, SABSA, The Open Group, and ISACA.

Chris holds an MSc in Software and Systems Security at the University of Oxford, and an array of professional certifications: CISSP, ISSAP, CSSLP, CCSP, SSP.NET, SSP.JAVA, CISA, CISM, CIPP/E, CIPM, CIPT, FIP, SCF, TOGAF, CPSA, and CEH.

Chris' experience spans multiple sectors: Retail & eCommerce; Financial Services, Banking, & Payments; i-Gaming; Energy (Oil & Gas); Property Management & PropTech; and Data Science; as well as Defence. 

His areas of interests include: penetration testing; regulation & privacy, including the impact on society; access control in software; security automation in development; application of cryptography; security architecture; risk modelling & analysis; HTTP architecture & web security; IoT Security.

Cookie Notice

We use cookies to ensure that we give you the best experience on our website. Please confirm you are happy to continue.

Back to top