This lab teaches security engineers and Salesforce developers how to identify, exploit, and remediate open redirect flaws in Visualforce and related navigation flows. The objective is to convert weak redirect logic into enforceable, policy-driven navigation controls.
An open redirect vulnerability occurs when an application accepts a user-controlled destination and issues a redirect without strict validation. While often treated as low severity in isolation, open redirects become high-impact when chained with phishing, OAuth abuse, token leakage, or session theft workflows.
In Salesforce ecosystems, the risk is commonly introduced in Visualforce controllers, custom login handlers, post-authentication return flows, and generic "continue" parameters.
Prioritize review of all endpoints that accept destination, return, next, continue, or callback style parameters.
ApexPages.currentPage().getParameters() for navigation decisionsTypical vulnerable pattern:
// Insecure pattern: user-controlled redirect target
String nextUrl = ApexPages.currentPage().getParameters().get('next');
return new PageReference(nextUrl);
Use the PoC suite to validate multiple exploit classes, not just one external URL test.
javascript:, data:, and malformed schemesRepresentative vulnerable flow:
<apex:page controller="RedirectController">
<script>
window.location = '{!redirectUrl}';
</script>
</apex:page>
// Example payload
// /apex/Redirect?redirectUrl=https://attacker.example/phish
Apply a repeatable methodology to avoid false confidence:
Recommended approach: route by server-managed identifiers, not by raw URLs from user input.
// Preferred: map key to trusted internal route
private static final Map<String, String> ALLOWED_ROUTES = new Map<String, String>{
'dashboard' => '/lightning/page/home',
'cases' => '/lightning/o/Case/list'
};
public PageReference secureRedirect() {
String target = ApexPages.currentPage().getParameters().get('target');
String safePath = ALLOWED_ROUTES.get(target);
if (String.isBlank(safePath)) {
safePath = '/home/home.jsp';
}
PageReference pr = new PageReference(safePath);
pr.setRedirect(true);
return pr;
}
Work through the sequence below to complete this lab in a production-relevant format: