
Welcome! Today we will examine the first task in the JavaScript for Pentesters course by Pentester Academy.
Pentester Academy is an excellent resource for information security training, jam-packed with a plethora of courses that are sure to aid in taking your infosec skills to the next level!
Pentester Academy is a subscription based service, so to perform these excercises yourself, you’ll need a membership. Obtaining a membership grants you access to over 40+ courses, 1500+ videos, as well as unlimited access to Pentester Academy’s very own AttackDefense labs, containing over 1600+ online labs!
This series will focus on their JavaScript for Pentesters course, which is excellent for any ethical hackers out there that are interested in buffing their web application hacking skills. So without further ado, let’s hop right into solving the first challenge in the course: Modifying HTML With JavaScript.
Task Objectives

Objectives:
1. Modify the text “Modify me” to “Modified you“
2. Modify the text “Find me” to “Found you“
Mapping The Web Application
To begin tackling our challenge, we must first begin to map out the web application functionality. Any seasoned web application penetration tester will tell you that reconnaissance is the first, and certainly, one of the most important steps in attacking a web application.
The more information we can gather about the web application, the better. This includes observing all HTTP traffic, server-side components, client-side components, URLs, application logic, and much, much more!
Now hold on, you may be asking yourself:
“I thought this was just a basic challenge? Why would we need to do all of this extra work?”
Well, in this instance, it is a fairly basic challenge! So don’t start to feel overwhelmed!
The emphasis on performing comprehensive reconnaissance and application mapping will make its importance self-evident as you progress towards targeting more complex web applications in the future. Therefore, these are good concepts to keep in mind!
With that out of the way, let’s start mapping the challenge application!
Identifying Potential Attack Vectors & The Core Security Issue With All Web Applications
The core security issue facing all web applications, is that user input can be submitted arbitrarily.
Given that a client utilizing the application remains outside of the application’s control, users can submit arbitrary input to the server-side application. In fact, the majority of web application attacks involve sending input that is crafted to achieve some action or event that was not expected or desired by the application’s designer.
Equipped with the understanding of this fundamental security problem, how can we use this information to identify a potential attack vector in the web application presented by our challenge?

We can see in the image above, that the application presents us with an HTML form containing an input field.
As part of our application mapping process, let’s attempt to see what occurs when we submit input into this field:

We submit the input string “test” to the application and receive the following response from the server:

We can see that the application returns the string that we submitted into the input field, rendering it into the HTML page we are presented.
As an attacker, this is a very interesting functionality that seems to indicate that the application may be vulnerable!
Let’s dive deeper into how the application processed and responded to our test input, to understand both why and how, this may present a vulnerability.
Peeling Back The Curtain: Taking a Look Behind The Scenes
We’ll begin to examine how the application processed our input by comparing two noticeable differences: The URL of our initial request and the source code of the original file served to us, to that of the URL and HTML source code served following the submission of our input.
Comparing The URL
Original URL:
pentesteracademylab.appspot.com/lab/webapp/jfp/1
URL Following Input Submission:
pentesteracademylab.appspot.com/lab/webapp/jfp/1?url=test
Our comparison reveals that the value of the string we submitted is passed to a parameter titled ‘url‘ in the subsequent request to the server.
Comparing The HTML Source Code
Original HTML Source Code:

HTML Source Code Following Input Submission:

Analyzing the variations between the original HTML source code, and that which is served to us following our input submission, reveals a vital piece of information.
When a client submits data to the web application via the input field, the submitted string is stored within an ‘h2‘ HTML header tag.
This is a crucial revelation to us as an attacker, let’s discuss why.
Piecing Together The Puzzle
Based on our analysis of the application so far, we can deduce several key components of the application’s functionality that we may be able to leverage for exploitation:
- The application allows for clients to submit arbitrary input via a form field
- The user supplied data is stored within a parameter titled ‘url‘ following the submission of input
- The application utilizes this input to render new HTML containing the arbitrary input
This functionality within the web application makes itself vulnerable to an injection attack.
In the context of our challenge, this is a JavaScript code injection attack.
Another closely related injection attack, is HTML injection.
In order to avoid confusion, let’s take a quick look at the difference between the two.
While our challenge does involve modifying the HTML of the page, the method in which we are using to modify the HTML contents is what differentiates the two attacks.
In our challenge, we will utilize injected JavaScript code to modify the HTML of the page being served. While in the case of an HTML injection attack, we would utilize HTML tags/code to perform a malicious action.
Both attacks essentially leverage the same vulnerability: Insufficient handling/validation of user supplied data
The difference resides in the method of attack used to exploit the vulnerability.
JavaScript injection is generally utilized to perform what is known as cross-site scripting, otherwise referred to as XSS.
Cross-site scripting allows for an attacker to execute malicious JavaScript within another user’s browser. The attack does not target the victim directly, instead it exploits a vulnerability within the website that the victim visits. When the victim navigates to the compromised page, the victim’s browser loads and executes the resources on the page, as is it’s normal function. Given that the browser does not inherently know that the JavaScript it is executing to provide the normal functionality of the web application, may also contain a malicious JavaScript payload embedded by an attacker, it executes the attacker’s malicious JavaScript as well.
There are several types of cross-site scripting vulnerabilities:
- Persistent XSS: Where the malicious string originates from the website’s database/stored on the website permanently
- Reflected XSS: Where the malicious string originates from the victim’s request
- DOM-based XSS: Where the vulnerability is in the client-side code rather than the server-side code
There are a vast number of ways that attackers can make use of XSS vulnerabilities to achieve malicious actions.
In addition, some browsers DO have built in mechanisms to prevent XSS if it potentially identifies an XSS payload or attack. A main example would be the Google Chrome browser.
The majority of this is beyond the scope of what this article is intended to cover. However, I plan on making posts in the future describing XSS in more detail.
With that cleared up, let’s see how we can confirm arbitrary JavaScript code injection within our challenge, and subsequently leverage this to modify the HTML of the page!
Exploiting The Application To Modify HTML
To begin the process of exploitation, we will first need to confirm that the web application will process injected JavaScript code supplied by the user.
We will utilize a simple JavaScript payload as our input in order to achieve this:
<script>alert("Injection")</script>
We insert the payload into the input form field and submit it:


Excellent, we have now confirmed that JavaScript code injection is possible via user input.
Observing the URL of the challenge after our input submission confirms that the value of our input is stored in the ‘url‘ parameter as noted earlier:

Examining this URL also displays that the value of our user supplied data is URL encoded. This will be of importance when delivering our exploit payload.
Crafting Our Payload
Now that we have confirmed the ability to inject arbitrary JavaScript code, it’s time to craft our payload!
Let’s begin by taking a look at the HTML source code again:

As stated, the objective of the challenge is to modify the text “Modify me” to “Modified you“.
As well as modify the text “Find me” to “Found you“.
Within the HTML code pictured above, we can see that the text “Find me!” is stored within an HTML ‘h1‘ header tag.
The “Modify me!” text appears to be stored within an ‘h2‘ header tag.
In order to modify this text with JavaScript, we can make use of the getElementsByTagName() method, appended with the .innerHTML property.
The getElementsByTagName() method gets all the elements within a document with the specified tag name.
The .innerHTML HTML DOM element object property, sets or returns the HTML content of an element.
Reviewing the entirety of the source code of the page, reveals that there are a total of four ‘h2‘ header tags, and only one ‘h1‘ header tag.
As previously noted, the “Find me!” text is located within the ‘h1‘ header tag.
The “Modify me!” text is stored within the third ‘h2‘ tag of the HTML.
With this information, we can now write our JavaScript payload:
<script>
document.getElementsByTagName('h2')[2].innerHTML = "Modified you";
document.getElementsByTagName('h1')[0].innerHTML = "Found you";
</script>
Let’s take a quick moment to break down the anatomy of our payload:
Firstly, we utilize the HTML script tag to declare that the contents embedded within the tag is code to be executed
- Next, we make use of the getElementsByTagName() method, passing it the respected tag names of the elements we are attempting to modify
- We then specify which tag to modify by numerical order, using an array to achieve this
- Pay attention to the fact that we have passed a value of ‘2‘ within the array that specifies the third ‘h2‘ header in the document, this is because we are counting in order from 0 and not from 1
- We utilize the .innerHTML property to modify the text and set the value to be those that the challenge specified
Excellent, we now have a complete payload!
However, before we simply take this payload and attempt to submit it via the input form field, let’s revisit a simple detail we noticed earlier.
After submitting our initial JavaScript payload to test if code injection was possible, we noticed that the value of our user supplied data was URL encoded within the ‘url‘ parameter.
Therefore, we should proceed to URL encode our payload before attempting to submit it. In fact, this is generally considered a good practice when attempting to insert any data within an HTTP request while attacking a web application.
Luckily, the challenge already presents us with a URL encoder and decoder:


Now, that we have properly URL encoded our payload, we will proceed to execute our attack by taking the encoded payload and passing it as the value for the ‘url‘ parameter on our target:

Now, all that’s left to do is hit enter and…

Ta-dah!
Our JavaScript code executes, modifying the HTML content of the page!
Challenge Complete!
Conclusion
That concludes our examination of the first challenge in the JavaScript for Pentesters course by Pentester Academy!
This is a great course for any hackers who are interested in leveling up their web application hacking skills. So, if you feel like taking on the challenges yourself, head over to Pentester Academy and give it a shot!
I will be releasing more writeups covering the course challenges in the future, so stay tuned for more JavaScript mischief!
Until next time,
Happy Hacking!