Hard 0
Hard 0
Platform: spbctf | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-03-15 | Status: Solved Techniques: filter_bypass, script_tag_escape, semicolonless_html_entities, svg_xml_entity_decoding
Summary
XSS challenge with regex filter blocking () and ; characters. Bypass using SVG script context with semicolon-less HTML entities (( instead of () to call prompt('sibears') with exact string argument.
Hard 0 - spbctf (SiBears CTF)
Description
Attack our bot to get the flag! Solve the SiBears XSS level and submit your payload. The challenge is hosted on the SiBears XSS School platform. The goal is to craft an XSS payload that calls prompt("sibears") with the exact string argument, bypassing a filter function.
Analysis
The escape function filters dangerous characters using regex:
javascript read-only • copy allowedfunction escape(s) { s = s.replace(/[\(\)\+\-\[\]\.\={}\;\:]/g, '_'); return '<script> var foo = "' + s + '"; </scr' + 'ipt>'; }
Filtered characters: ( ) + - [ ] . = { } ; :
Key observations:
- Input is placed inside a double-quoted JS string within
<script>tag - The sandbox requires
prompt("sibears")with exact string (strict equality===) - Template literals won't work because they pass arrays, not strings
- HTML entities with semicolons fail because
;is filtered
Critical insight: HTML numeric entities work WITHOUT trailing semicolons (( instead of (), and SVG <script> tags decode HTML entities before JavaScript execution.
Solution
Winning Payload
</script><svg><script>prompt("sibears")</script></svg>
Step-by-step breakdown:
</script>- Closes the original script tag, escaping the JS string context<svg><script>- Opens SVG context where XML entity decoding applies to script content(and)- Semicolon-less HTML entities for(and)- bypass the filter completely- Browser decodes to
prompt("sibears")- exact string argument passes strict equality check
Why filter bypass works:
- No literal
(or)characters in payload - No semicolons in the HTML entities
- Only safe characters:
&,#, digits, letters, quotes
Failed attempts:
- Template literals:
prompt\sibears`passes["sibears"]array, fails=== "sibears"` check - Entities with semicolons:
(becomes(_due to;being filtered
javascript read-only • copy allowed// Final decoded result in browser: prompt("sibears") // Returns flag