August 20, 2026
Hunting Open Redirects: My Practical Methodology for Web Application Testing
Introduction
By chalampalem Neeraja
8 min read
Introduction
During web application security testing, I often pay attention to parameters that control navigation and redirection.
An Open Redirect occurs when a web application accepts a user-controlled URL or redirect destination and sends the user to an external website without properly validating whether that destination is trusted.
A simple example is:
https://target.example/redirect?url=https://example.comhttps://target.example/redirect?url=https://example.comIf the application allows an attacker to change the destination to an external domain:
https://target.example/redirect?url=https://example-attacker.comhttps://target.example/redirect?url=https://example-attacker.comand the browser is redirected there, the application may be vulnerable to Open Redirect.
Although Open Redirect is often considered a lower-impact vulnerability when found by itself, it can become more interesting when it is involved in authentication flows, OAuth redirects, phishing scenarios, or the transmission of sensitive information.
In this article, I will explain the methodology I use to identify potential Open Redirects at scale, starting from URL discovery and ending with manual validation.
Disclaimer:_ The techniques described here should only be used against applications you own or are explicitly authorized to test, including bug bounty targets within scope, CTF environments, penetration tests, and personal applications._
Understanding Open Redirect
A redirect is a normal feature of modern web applications.
For example, an application might redirect a user after login:
/login?next=/dashboard/login?next=/dashboardor redirect a user after completing an action:
/redirect?url=/account/redirect?url=/accountThese features become security issues when the application trusts user-controlled redirect destinations without enforcing appropriate restrictions.
For example:
/redirect?url=https://trusted.example/redirect?url=https://trusted.examplecould potentially become:
/redirect?url=https://example-attacker.com/redirect?url=https://example-attacker.comIf the server accepts the second value and redirects the user externally, the application has an Open Redirect condition.
The important thing to remember is that the presence of a parameter named url, redirect, or next does not itself prove a vulnerability.
Those parameters are simply useful indicators for finding functionality that deserves further testing.
Why I Start With URL Discovery
One of the biggest challenges during bug hunting is discovering the application's attack surface.
A large web application can contain thousands of URLs, APIs, JavaScript-discovered endpoints, legacy routes, and parameters.
Manually checking every URL is inefficient.
Instead, I collect URLs from multiple sources and then filter the results.
For my Open Redirect hunting methodology, I use:
- GAU,Katana,URLFinder,Hakrawler,URO,grep,QSReplace,HTTPX Toolkit,Burp Suite for manual validation
Each tool has a different purpose, and combining their output gives me a broader set of URLs to investigate.
Tools and Installation
Before starting the methodology, these are the open-source tools I use.
GAU
GAU is used for gathering known URLs associated with a target.
Official repository: https://github.com/lc/gau
Installation:
go install github.com/lc/gau/v2/cmd/gau@latestgo install github.com/lc/gau/v2/cmd/gau@latestKatana
Katana is a web crawling framework from ProjectDiscovery.
Official repository: https://github.com/projectdiscovery/katana
Installation:
go install github.com/projectdiscovery/katana/cmd/katana@latestgo install github.com/projectdiscovery/katana/cmd/katana@latestURLFinder
URLFinder is a passive URL discovery tool from ProjectDiscovery.
Official repository: https://github.com/projectdiscovery/urlfinder
Installation:
go install -v github.com/projectdiscovery/urlfinder/cmd/urlfinder@latestgo install -v github.com/projectdiscovery/urlfinder/cmd/urlfinder@latestHakrawler
Hakrawler is a lightweight web crawler useful for discovering URLs and assets.
Official repository: https://github.com/hakluke/hakrawler
Installation:
go install github.com/hakluke/hakrawler@latestgo install github.com/hakluke/hakrawler@latestURO
URO helps clean and reduce large URL lists by removing duplicates and less useful URLs.
Official repository: https://github.com/s0md3v/uro
Installation:
pipx install uropipx install uroQSReplace
QSReplace replaces query-string parameter values, which makes it useful for automated parameter testing.
Official repository: https://github.com/tomnomnom/qsreplace
Installation:
go install github.com/tomnomnom/qsreplace@latestgo install github.com/tomnomnom/qsreplace@latestHTTPX
For this methodology, I use ProjectDiscovery's HTTPX for HTTP probing and response validation.
Official repository: https://github.com/projectdiscovery/httpx
Installation:
go install -v github.com/projectdiscovery/httpx/cmd/httpx@latestgo install -v github.com/projectdiscovery/httpx/cmd/httpx@latestNote: The ProjectDiscovery tool is
httpx. If your local setup uses the binary namehttpx-toolkit, keep using the command available in your environment.
URL Discovery With GAU
I start by collecting URLs from public sources using GAU:
echo target.com | gau --o urls1.txtecho target.com | gau --o urls1.txtGAU is useful because it can provide historical and publicly known URLs associated with a domain.
This can sometimes expose older endpoints that aren't immediately visible during normal application browsing.
Those older endpoints are worth investigating because applications may retain legacy functionality even after newer features are introduced.
Crawling With Katana
Next, I use Katana for active crawling:
echo target.com | katana -d 2 -o urls2.txtecho target.com | katana -d 2 -o urls2.txtThe crawl depth can be adjusted depending on the size of the target and the permitted scope.
The purpose of using both passive URL collection and active crawling is to increase endpoint coverage.
GAU may discover URLs that are publicly known, while a crawler can discover links and resources available through the application's current structure.
Additional URL Discovery With URLFinder
I also use URLFinder:
echo target.com | urlfinder -o urls3.txtecho target.com | urlfinder -o urls3.txtUsing another discovery source helps reduce dependency on a single tool.
Different tools can produce different results, so I prefer combining their output rather than assuming one source contains the entire attack surface.
Crawling With Hakrawler
Another source I use is Hakrawler:
echo "https://target.com" | hakrawler > urls4.txtecho "https://target.com" | hakrawler > urls4.txtThe objective is again to collect additional URLs that may contain parameters or redirect functionality.
At this stage, I have multiple URL files.
Combining and Normalizing URLs
The next step is to combine the results and remove duplicates.
I use:
cat urls1.txt urls2.txt urls3.txt urls4.txt | uro | sort -u | tee final.txtcat urls1.txt urls2.txt urls3.txt urls4.txt | uro | sort -u | tee final.txtThis gives me a cleaner dataset to work with.
Removing duplicates is particularly useful when performing automated testing because the same endpoint can be discovered by multiple tools.
Without normalization, the same URL may be tested repeatedly, increasing unnecessary requests and noise.
Identifying Potential Redirect Parameters
Now I focus on URLs containing parameters that commonly control navigation.
Some examples include:
redirect
redirect_url
redirect_uri
redirect_to
return
returnUrl
return_url
returnTo
next
next_page
continue
destination
dest
target
url
uri
goto
go
forward
jump
locationredirect
redirect_url
redirect_uri
redirect_to
return
returnUrl
return_url
returnTo
next
next_page
continue
destination
dest
target
url
uri
goto
go
forward
jump
locationI use these names as search indicators.
For example:
https://target.example/login?next=/dashboardhttps://target.example/login?next=/dashboardis interesting because next may determine the destination after login.
Similarly:
https://target.example/redirect?url=/homehttps://target.example/redirect?url=/homeis interesting because url appears to influence the destination.
I filter my collected URLs using:
cat final.txt | grep -Pi "returnUrl=|continue=|dest=|destination=|forward=|go=|goto=|next=|next_page=|out=|redir=|redirect=|redirect_to=|redirect_uri=|redirect_url=|return=|returnTo=|return_path=|return_to=|return_url=|rurl=|target=|to=|uri=|url=|qurl=|jump=|jump_url=|originUrl=|origin=|location=|destination_url=|jump_to=|go_to=|goto_url=|target_url=|redirect_link=" | tee redirect_params.txtcat final.txt | grep -Pi "returnUrl=|continue=|dest=|destination=|forward=|go=|goto=|next=|next_page=|out=|redir=|redirect=|redirect_to=|redirect_uri=|redirect_url=|return=|returnTo=|return_path=|return_to=|return_url=|rurl=|target=|to=|uri=|url=|qurl=|jump=|jump_url=|originUrl=|origin=|location=|destination_url=|jump_to=|go_to=|goto_url=|target_url=|redirect_link=" | tee redirect_params.txtThe resulting file contains URLs that are more relevant to Open Redirect testing.
Why Parameter Filtering Is Useful
Without filtering, I might have thousands of URLs.
Most of them will have nothing to do with redirects.
For example:
/api/users?id=123
/products?id=45
/search?q=test
/static/app.js/api/users?id=123
/products?id=45
/search?q=test
/static/app.jsThese aren't necessarily relevant to Open Redirect testing.
Filtering allows me to focus on URLs containing parameters that are more likely to influence navigation.
However, parameter filtering should never be considered vulnerability confirmation.
A parameter called redirect may be completely secure.
A parameter called id could theoretically participate in a redirect through application logic.
Therefore, this stage is only candidate identification.
Testing the Redirect Parameter
After obtaining candidate URLs, I want to determine whether the redirect parameter actually accepts an external destination.
I use QSReplace to replace the existing parameter value with a controlled test domain:
cat redirect_params.txt | qsreplace "https://example-attacker.com"cat redirect_params.txt | qsreplace "https://example-attacker.com"For example, an original URL such as:
https://target.example/redirect?url=/dashboardhttps://target.example/redirect?url=/dashboardmay become:
https://target.example/redirect?url=https://example-attacker.comhttps://target.example/redirect?url=https://example-attacker.comThe important point is that I use a domain specifically for testing and verification.
I don't need to use a real malicious website.
Automated Validation With HTTPX
After replacing the parameters, I use HTTPX Toolkit to identify responses associated with my test domain:
cat redirect_params.txt | qsreplace "https://example-attacker.com" | httpx-toolkit -silent -fr -mr "example-attacker.com"cat redirect_params.txt | qsreplace "https://example-attacker.com" | httpx-toolkit -silent -fr -mr "example-attacker.com"The idea is to identify candidates where the application appears to redirect toward the domain supplied during testing.
This significantly reduces the number of URLs that require manual investigation.
Why Automated Results Are Not Enough
One mistake I try to avoid is treating an automated match as a confirmed vulnerability.
A URL appearing in the output does not automatically mean that an Open Redirect exists.
There can be false positives caused by:
- A URL being reflected in the response
- An external link being present on the page
- Redirect chains
- Client-side JavaScript behavior
- Authentication requirements
- URL normalization
- Proxy/CDN behavior
- Application-specific redirect logic
Therefore, I treat automated output as a list of potential findings.
The final confirmation is performed manually.
Manual Validation With Burp Suite
Once I identify an interesting URL, I inspect it using Burp Suite.
I look at the HTTP request and response, paying particular attention to:
Location:Location:and HTTP redirect status codes such as:
301
302
303
307
308301
302
303
307
308For example:
HTTP/1.1 302 Found
Location: https://example-attacker.comHTTP/1.1 302 Found
Location: https://example-attacker.comA response like this provides strong evidence that the server is instructing the browser to navigate to the external destination.
I then reproduce the behavior in a browser to confirm the actual redirect.
Investigating the Full Behavior
After confirming the redirect, I don't immediately stop testing.
I investigate what else happens during the redirect.
For example, I check whether the application adds additional parameters to the destination:
https://example-attacker.com/?parameter=valuehttps://example-attacker.com/?parameter=valueThe parameters may contain information that should not be sent to an external domain.
Depending on the application, I may look for:
- Authentication-related values
- Session-related information
- OAuth parameters
- User identifiers
- Account identifiers
- Application-specific sensitive information
If sensitive information is discovered during authorized testing, I do not publish the actual value.
Instead, I use:
<REDACTED><REDACTED>in screenshots and examples.
Open Redirect and Authentication Flows
Open Redirects can become more significant when they are connected to authentication or authorization workflows.
For example, applications commonly use redirect parameters during:
- Login
- Logout
- OAuth authentication
- Account linking
- Password recovery
- SSO
- Checkout flows
If a redirect endpoint is involved in one of these workflows, I investigate whether the redirect can influence security-sensitive information.
However, I do not assume that an Open Redirect automatically results in account takeover or token theft.
The actual impact must be demonstrated based on the application's behavior.
What I Learned From This Methodology
The biggest lesson for me was that effective bug hunting is not just about knowing payloads.
It is about building a repeatable process.
Instead of manually opening thousands of URLs, I first reduce the dataset.
I collect URLs from multiple sources, normalize them, identify interesting parameters, test potential redirect behavior, and finally manually validate the interesting results.
Each step has a specific purpose.
The tools help with scale, but the final security assessment still requires human analysis.
Improvements I Would Make
This methodology can be improved further over time.
For example, instead of maintaining a large manually written parameter list, redirect-related GF patterns can be used to make filtering easier.
A workflow can look like:
cat final.txt | gf redirect | uro | sort -u | tee redirect_params.txtcat final.txt | gf redirect | uro | sort -u | tee redirect_params.txtThis can make the filtering stage more maintainable if the pattern is properly configured.
I also recommend keeping the reconnaissance and validation stages separate.
The objective of reconnaissance is to find candidates.
The objective of validation is to determine whether those candidates are actually vulnerable.
Keeping these stages separate makes the process easier to troubleshoot and reduces false positives.
My Open Redirect Hunting Workflow
The methodology I currently use can be summarized through the following commands.
URL discovery
echo target.com | gau --o urls1.txt
echo target.com | katana -d 2 -o urls2.txt
echo target.com | urlfinder -o urls3.txt
echo "https://target.com" | hakrawler > urls4.txtecho target.com | gau --o urls1.txt
echo target.com | katana -d 2 -o urls2.txt
echo target.com | urlfinder -o urls3.txt
echo "https://target.com" | hakrawler > urls4.txtCombine and normalize
cat urls1.txt urls2.txt urls3.txt urls4.txt | uro | sort -u | tee final.txtcat urls1.txt urls2.txt urls3.txt urls4.txt | uro | sort -u | tee final.txtIdentify potential redirect parameters
cat final.txt | grep -Pi "returnUrl=|continue=|dest=|destination=|forward=|go=|goto=|next=|redir=|redirect=|redirect_to=|redirect_uri=|redirect_url=|return=|returnTo=|return_to=|return_url=|target=|to=|uri=|url=|jump=|jump_url=|location=|destination_url=|target_url=|redirect_link=" | tee redirect_params.txtcat final.txt | grep -Pi "returnUrl=|continue=|dest=|destination=|forward=|go=|goto=|next=|redir=|redirect=|redirect_to=|redirect_uri=|redirect_url=|return=|returnTo=|return_to=|return_url=|target=|to=|uri=|url=|jump=|jump_url=|location=|destination_url=|target_url=|redirect_link=" | tee redirect_params.txtReplace the parameter value
cat redirect_params.txt | qsreplace "https://example-attacker.com"cat redirect_params.txt | qsreplace "https://example-attacker.com"Identify potential redirects
cat redirect_params.txt | qsreplace "https://example-attacker.com" | httpx-toolkit -silent -fr -mr "example-attacker.com"cat redirect_params.txt | qsreplace "https://example-attacker.com" | httpx-toolkit -silent -fr -mr "example-attacker.com"Manual verification
Finally, I take the interesting results to Burp Suite and manually verify:
- Whether the redirect actually occurs
- Whether the destination is attacker-controlled
- Whether authentication is required
- Whether additional information is transmitted
- Whether the behavior is reproducible
- What the realistic security impact is
Conclusion
Open Redirect hunting is not simply about finding a parameter named redirect.
The more important challenge is developing a methodology that can efficiently identify potentially vulnerable functionality across a large web application.
My approach combines several reconnaissance tools with URL normalization, parameter filtering, automated testing, and manual validation.
The main tools in my workflow are:
GAU → Katana → URLFinder → Hakrawler → URO → QSReplace → HTTPX Toolkit → Burp Suite
Automation helps me find potential candidates at scale, while manual testing allows me to understand the actual behavior and security impact.
Most importantly, I learned to look beyond the initial redirect.
When a redirect is discovered, the next question should be:
What else happens when the application redirects the user?
That question can sometimes turn a seemingly simple finding into a much more meaningful security issue.
Responsible Disclosure
Security testing should only be performed against systems where you have explicit authorization.
Always respect the scope and rules of the relevant bug bounty program, penetration test, CTF, or security assessment.
Never access another user's account or data, and never publish authentication tokens, session information, personal data, or other sensitive information discovered during testing.