Controlled and secure external site redirects
import UIKit
import SafariServices
class ViewController: UIViewController {
@IBOutlet weak var urlField: UITextField!
@IBAction func openURL(_ sender: Any) {
guard let urlString = urlField.text, let url = URL(string: urlString) else {
return
}
let vc = SFSafariViewController(url: url)
present(vc, animated: true)
}
}
The above Swift code represents a basic iOS application with a single view controller. The view controller has a text field
urlField
that allows users to enter a URL. When the user presses a button, the
openURL
function is triggered.
The
openURL
function takes the text from the
urlField
, attempts to construct a URL from it, and if successful, opens the URL in a Safari view controller.
The vulnerability lies in the fact that the URL is taken directly from user input without any validation or control. This means that an attacker can enter a malicious URL into the text field, which the application will then open. This is an example of an uncontrolled external site redirect, as the application does not control or restrict which URLs can be opened.
This vulnerability can be exploited in a variety of ways. For example, an attacker could redirect users to a phishing site that mimics a legitimate site, tricking them into entering sensitive information. Alternatively, they could redirect users to a site that serves malware, potentially leading to the compromise of their device.
import UIKit
import SafariServices
class ViewController: UIViewController {
@IBOutlet weak var urlField: UITextField!
// Define a list of trusted URLs
let trustedURLs = ["https://www.example.com", "https://www.example2.com"]
@IBAction func openURL(_ sender: Any) {
guard let urlString = urlField.text, let url = URL(string: urlString) else {
return
}
// Check if the URL is in the list of trusted URLs
if trustedURLs.contains(url.absoluteString) {
let vc = SFSafariViewController(url: url)
present(vc, animated: true)
} else {
// Show an error message if the URL is not trusted
let alert = UIAlertController(title: "Error", message: "The URL is not trusted.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
The updated code now includes a list of trusted URLs. When the
openURL
function is called, it first checks if the URL entered by the user is in the list of trusted URLs. If it is, the application will open the URL in the
SFSafariViewController
. If it is not, the application will present an alert to the user indicating that the URL is not trusted.
This approach mitigates the risk of uncontrolled external site redirects by ensuring that only URLs from a predefined list of trusted sources can be opened by the application. This prevents an attacker from manipulating the application to redirect to a malicious site.
In addition, the application now provides feedback to the user when a URL is not trusted. This can help educate users about the risks of untrusted URLs and discourage them from attempting to open such URLs in the application.
This solution, however, assumes that the list of trusted URLs can be predefined and is relatively static. If the application needs to support a wide range of URLs or if the list of trusted URLs changes frequently, a more dynamic solution may be needed. This could involve fetching the list of trusted URLs from a server, or implementing more complex logic to validate URLs based on certain criteria (e.g., the URL must use HTTPS, the domain must be a certain length, etc.).