Blogs / September 13, 2025 / by Admin

How I Discovered a Reflected XSS on the MOD UK Police Website (WAF Bypass)

How I Discovered a Reflected XSS on the MOD UK Police Website (WAF Bypass)

Assalamualaikum everyone, and welcome to my first write-up. In this post I describe a reflected XSS I discovered on the Ministry of Defence (UK) Police website that required bypassing a Web Application Firewall. I’ll walk through the payload design, the hurdles I faced, and the techniques that ultimately revealed the vulnerability.

How it begins:

I visited the Ministry of Defence website at “https://www.mod.police.uk/” and started looking around to see how the site handled user input. On the homepage I found a search box, so I typed “hassan” into it and submitted the query. The page returned search results and the URL changed to “https://www.mod.police.uk/search/?search=hassan“, which immediately caught my attention. I opened the page source code and looked for the search input markup there it is:

“<input id=”search-page-search” name=”search” placeholder=”hassan” type=”search” class=”w-full ps-3 pe-9 py-2 rounded border border-solid border-westar h-11″ />”

 

https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/
https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/

Seeing the my input “hassan” present in the input attributes confirmed that the application was reflecting input values back into the HTML. That reflection is a classic indicator of a potential reflected XSS vector, so I took note of the parameter name (search) and the exact context in which it was echoed. At this stage I didn’t attempt any destructive testing on the live site — instead I documented the behavior, captured the request/response, and planned controlled tests in a safe environment.

I typed a string of special characters into the search box “hassan'”><” and submitted the query. As soon as the results loaded I opened the browser’s View Source to see how the input was being reflected in the page. What I found was interesting: my exact characters weren’t visible as-is; instead they were returned as HTML entities:

“hassan&#x27;&quot;&gt;&lt;”

In other words, the characters ‘, “, >, and < had been HTML-encoded before being echoed back to the page. That observation told me two things at once. First, user input was definitely being reflected in the HTML response. Second, there was an encoding layer that was escaping special characters to prevent them from being interpreted as active HTML or script.

 

https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/
https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/

 

First I tried to inject the usual payload:

“hassan’\”<script>alert(‘XSS’)</script>”

But the problem that there is a WAF filtering input and refusing to pass request with “Attention Required! | Cloudflare” response.

https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/
https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/

 

After several iterations and careful testing, one of the more compact payloads finally bypassed the filtering and executed in the browser:

“<Img Src=OnXSS OnError=confirm(document.cookie)>”

When this payload was reflected and rendered by the page it triggered a confirmation dialog — proof of concept that arbitrary script can run in the victim’s browser via the search parameter. I used confirm() intentionally as a non-destructive, visible proof-of-concept.

https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/
https://0xhassan.com/reflected-xss-mod-police-website-waf-bypass/

 

I reported the issue to HackerOne on May 13, 2025 at 14:04 UTC. The report was triaged the next day — May 14, 2025 at 08:43 UTC — and the vulnerability was verified and fixed by the team. The issue was marked Resolved on July 2, 2025 at 06:28 UTC.

Tags:
1 Comment
Leave a comment