Insecure hostname validation check
Insecure hostname validation check
Description
The application performs insecure hostname validation using easy to bypass methods like startsWith
or endsWith
. An
attacker can easily bypass this check by registering a domain that matches the check pattern.
Composite checks with both startsWith
and endsWith
are equally insecure as the attack can still create domain with
random middle input that matches the checked pattern.
Recommendation
To ensure a safe validation of the hostname, consider the implementations below.
-
Implement Regular Expression (Regex) Validation: Instead of using simple methods like
startsWith
orendsWith
, opt for regular expressions to perform thorough hostname validation. Regex patterns can allow for precise matching criteria. -
Consider Standardized Validation Libraries: Utilize established libraries or frameworks that offer robust hostname validation functionalities. These libraries are often well-maintained and regularly updated to address potential security flaws.
-
Implement Whitelisting: If you have a limited number of whitelisted hosts, consider implementing a whitelist approach where only known and trusted hostnames are accepted by the application.
import java.util.regex.*;
public class SubdomainValidator {
public static void main(String[] args) {
String userInput = "sub.example.com"; // replace this with user input
// Regular expression pattern to match subdomains of example.com
String pattern = "^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+example\\.com$";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Create Matcher object
Matcher m = r.matcher(userInput);
// Check if input matches the pattern
if (m.find()) {
System.out.println("Valid subdomain of example.com");
} else {
System.out.println("Invalid subdomain of example.com");
}
}
}
import Foundation
func isValidSubdomain(_ userInput: String) -> Bool {
let pattern = #"^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+example\.com$"# // Regular expression pattern
let regex = try! NSRegularExpression(pattern: pattern)
let range = NSRange(location: 0, length: userInput.utf16.count)
return regex.firstMatch(in: userInput, options: [], range: range) != nil
}
let userInput = "sub.example.com" // replace this with user input
if isValidSubdomain(userInput) {
print("Valid subdomain of example.com")
} else {
print("Invalid subdomain of example.com")
}
import 'package:flutter/material.dart';
bool isValidSubdomain(String userInput) {
RegExp regex = RegExp(r'^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+example\.com$');
return regex.hasMatch(userInput);
}
void main() {
String userInput = "sub.example.com"; // replace this with user input
if (isValidSubdomain(userInput)) {
print("Valid subdomain of example.com");
} else {
print("Invalid subdomain of example.com");
}
}
Links
Standards
- OWASP_MASVS_L1:
- MSTG_PLATFORM_2
- OWASP_MASVS_L2:
- MSTG_PLATFORM_2
- CWE_TOP_25:
- CWE_20
- PCI_STANDARDS:
- REQ_6_2
- REQ_6_3
- REQ_11_3
- OWASP_MASVS_v2_1:
- MASVS_CODE_4
- SOC2_CONTROLS:
- CC_2_1
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5