Improper Validation of Syntactic Correctness of Input
Description
Improper Validation of Syntactic Correctness of Input occurs when a product receives input expected to follow specific syntax but fails to validate or incorrectly validates conformance. Complex inputs often must follow particular syntax requirements—whether for data formats, markup languages, or programming languages. Without proper validation of untrusted input, attackers can trigger parsing failures, unexpected errors, or exploit latent vulnerabilities that wouldn't be accessible with properly formatted data.
Risk
Improper syntactic validation has severe security implications. Parsing errors may occur. Injection attacks become possible. XML/JSON parsing exploits enabled. Configuration file manipulation. Protocol-level attacks possible. Application crashes may happen. Security controls can be bypassed. Data corruption may result.
Solution
Implement "accept known good" validation—maintain strict lists of acceptable inputs conforming to specifications. Reject non-conforming data or transform it appropriately. Verify length, type, acceptable ranges, missing/extra inputs, syntax, and business rules. Use schema validation for structured formats. Employ parser generators for complex syntax.
Common Consequences
| Impact | Details |
|---|---|
| Other | Scope: Other Impact varies - from crashes to security bypasses. |
| Integrity | Scope: Integrity Injection attacks may modify data or behavior. |
| Availability | Scope: Availability Malformed input may crash parsers. |
Example Code
Vulnerable Code
// Vulnerable: XML parsing without validation
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
public class VulnerableXmlParser {
// VULNERABLE: No XML schema validation
public Document parseXml(File xmlFile) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// VULNERABLE: Validation disabled
factory.setValidating(false);
// VULNERABLE: No schema set
// factory.setSchema(...);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(xmlFile);
// Parses any well-formed XML, even if it doesn't match expected structure
// Attacker can inject unexpected elements or attributes
return doc;
}
// VULNERABLE: JSON parsing without schema validation
public void processJsonConfig(String jsonInput) {
// VULNERABLE: No validation against expected schema
JSONObject config = new JSONObject(jsonInput);
// Assumes specific structure without verification
String serverUrl = config.getString("serverUrl"); // May not exist
int port = config.getInt("port"); // May be string
// Attacker can provide malformed JSON or unexpected types
}
}
// Vulnerable: Protocol parsing without syntax validation
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// VULNERABLE: HTTP request parsing without proper validation
void vulnerable_parse_http_request(const char* request) {
char method[16];
char path[256];
char version[16];
// VULNERABLE: Simple sscanf without validation
int parsed = sscanf(request, "%s %s %s", method, path, version);
// VULNERABLE: No validation of HTTP version format
// version could be anything, not just "HTTP/1.0" or "HTTP/1.1"
// VULNERABLE: No validation of method
// method could contain invalid characters
// VULNERABLE: No validation of path
// path could contain malicious sequences
if (parsed == 3) {
process_request(method, path, version);
}
// Missing proper error handling
}
// VULNERABLE: IP address parsing without proper format validation
int vulnerable_parse_ip(const char* ip_string, uint32_t* ip_out) {
// VULNERABLE: inet_addr accepts octal/hex notation
// "0x7f.0.0.1" or "0177.0.0.1" could bypass filters
*ip_out = inet_addr(ip_string);
return (*ip_out != INADDR_NONE);
// Filter checking for "127.0.0.1" would miss "0x7f.0.0.1"
}
// VULNERABLE: Email validation with insufficient syntax check
int vulnerable_validate_email(const char* email) {
// VULNERABLE: Only checks for @ symbol
if (strchr(email, '@') != NULL) {
return 1; // "Valid"
}
return 0;
// Accepts: "not valid@", "@invalid", "a@b", etc.
// Many syntactically invalid emails pass this check
}
# Vulnerable: Input parsing without syntax validation
import re
import json
# VULNERABLE: URL parsing without proper validation
def vulnerable_parse_url(url):
# VULNERABLE: Simple regex doesn't validate full URL syntax
match = re.match(r'https?://(.+)', url)
if match:
return match.group(1) # Returns everything after protocol
return None
# Accepts malformed URLs like "http://invalid url with spaces"
# Doesn't validate hostname syntax, port numbers, etc.
# VULNERABLE: Date parsing without format validation
def vulnerable_parse_date(date_str):
# VULNERABLE: No format validation
parts = date_str.split('-')
if len(parts) == 3:
year, month, day = parts
return {
'year': int(year), # Could fail on non-numeric
'month': int(month), # Could be 13, -1, etc.
'day': int(day) # Could be 32, 0, etc.
}
return None
# Accepts: "2024-13-45", "0-0-0", "-1--2--3"
# VULNERABLE: SQL-like query parsing
def vulnerable_parse_query(query):
# VULNERABLE: No syntax validation
# Accepts any string as a "query"
if 'SELECT' in query.upper():
# Process as select query
pass
elif 'INSERT' in query.upper():
# Process as insert query
pass
# No real SQL syntax validation
# Attacker can inject malformed queries
Fixed Code
// Fixed: XML parsing with proper validation
import javax.xml.parsers.*;
import javax.xml.validation.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import java.io.*;
public class SecureXmlParser {
// FIXED: XML parsing with schema validation
public Document parseXml(File xmlFile, File schemaFile) throws Exception {
// Load schema
SchemaFactory schemaFactory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI
);
Schema schema = schemaFactory.newSchema(schemaFile);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// FIXED: Enable validation
factory.setValidating(true);
factory.setNamespaceAware(true);
factory.setSchema(schema);
// FIXED: Security hardening
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder builder = factory.newDocumentBuilder();
// FIXED: Error handler for validation errors
builder.setErrorHandler(new ErrorHandler() {
@Override
public void error(SAXParseException e) throws SAXException {
throw e; // Fail on validation error
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
throw e;
}
@Override
public void warning(SAXParseException e) {
System.err.println("Warning: " + e.getMessage());
}
});
return builder.parse(xmlFile);
}
// FIXED: JSON parsing with schema validation
public Config parseJsonConfig(String jsonInput) throws ValidationException {
// FIXED: Use JSON Schema validation
ObjectMapper mapper = new ObjectMapper();
// Parse JSON
JsonNode rootNode;
try {
rootNode = mapper.readTree(jsonInput);
} catch (JsonProcessingException e) {
throw new ValidationException("Invalid JSON syntax: " + e.getMessage());
}
// FIXED: Validate against schema
JsonSchema schema = loadConfigSchema();
Set<ValidationMessage> errors = schema.validate(rootNode);
if (!errors.isEmpty()) {
throw new ValidationException("JSON validation failed: " + errors);
}
// FIXED: Deserialize to typed object
return mapper.treeToValue(rootNode, Config.class);
}
}
// Fixed: Protocol parsing with proper syntax validation
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <arpa/inet.h>
// FIXED: HTTP request parsing with validation
bool secure_parse_http_request(const char* request,
char* method_out, size_t method_size,
char* path_out, size_t path_size,
char* version_out, size_t version_size) {
const char* p = request;
// FIXED: Parse and validate method
const char* valid_methods[] = {"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"};
bool method_valid = false;
size_t method_len = 0;
while (*p && *p != ' ' && method_len < method_size - 1) {
if (!isupper(*p)) {
return false; // Method must be uppercase
}
method_out[method_len++] = *p++;
}
method_out[method_len] = '\0';
// FIXED: Verify method is in allowed list
for (int i = 0; i < sizeof(valid_methods)/sizeof(valid_methods[0]); i++) {
if (strcmp(method_out, valid_methods[i]) == 0) {
method_valid = true;
break;
}
}
if (!method_valid) {
return false;
}
// Skip space
if (*p != ' ') return false;
p++;
// FIXED: Parse and validate path
size_t path_len = 0;
while (*p && *p != ' ' && path_len < path_size - 1) {
// FIXED: Validate path characters
if (!isprint(*p) || *p == '<' || *p == '>') {
return false; // Invalid path character
}
path_out[path_len++] = *p++;
}
path_out[path_len] = '\0';
// FIXED: Path must start with /
if (path_out[0] != '/') {
return false;
}
// Skip space
if (*p != ' ') return false;
p++;
// FIXED: Parse and validate HTTP version
if (strncmp(p, "HTTP/", 5) != 0) {
return false;
}
p += 5;
// FIXED: Only accept HTTP/1.0 or HTTP/1.1
if (strcmp(p, "1.0\r\n") != 0 && strcmp(p, "1.1\r\n") != 0) {
return false;
}
strncpy(version_out, p, version_size - 1);
version_out[version_size - 1] = '\0';
return true;
}
// FIXED: IP address parsing with strict format validation
bool secure_parse_ip(const char* ip_string, uint32_t* ip_out) {
// FIXED: Only accept standard decimal dotted notation
unsigned int octets[4];
char extra;
// FIXED: Strict format parsing
int parsed = sscanf(ip_string, "%u.%u.%u.%u%c",
&octets[0], &octets[1], &octets[2], &octets[3], &extra);
// Must parse exactly 4 octets, no trailing characters
if (parsed != 4) {
return false;
}
// FIXED: Validate octet ranges
for (int i = 0; i < 4; i++) {
if (octets[i] > 255) {
return false;
}
}
// FIXED: Verify no octal/hex notation (no leading zeros except for 0)
const char* p = ip_string;
for (int i = 0; i < 4; i++) {
if (*p == '0' && isdigit(*(p+1))) {
// Leading zero - could be octal, reject
return false;
}
while (*p && *p != '.') p++;
if (*p == '.') p++;
}
*ip_out = (octets[0] << 24) | (octets[1] << 16) | (octets[2] << 8) | octets[3];
return true;
}
// FIXED: Email validation with proper syntax checking
bool secure_validate_email(const char* email) {
// FIXED: Comprehensive email syntax validation
const char* at = strchr(email, '@');
if (at == NULL) return false;
// Check only one @
if (strchr(at + 1, '@') != NULL) return false;
// Local part validation (before @)
const char* p = email;
if (p == at) return false; // Empty local part
while (p < at) {
char c = *p++;
// FIXED: Validate allowed characters in local part
if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+') {
return false;
}
}
// Domain part validation (after @)
p = at + 1;
if (*p == '\0') return false; // Empty domain
int dot_count = 0;
while (*p) {
char c = *p++;
if (c == '.') {
dot_count++;
if (*(p-2) == '.' || *(p) == '\0') {
return false; // Consecutive dots or trailing dot
}
} else if (!isalnum(c) && c != '-') {
return false;
}
}
// Must have at least one dot in domain
if (dot_count == 0) return false;
return true;
}
# Fixed: Input parsing with proper syntax validation
import re
import json
from urllib.parse import urlparse
from datetime import datetime
from jsonschema import validate, ValidationError as JsonValidationError
# FIXED: URL parsing with proper validation
def secure_parse_url(url):
"""Parse and validate URL syntax."""
# FIXED: Use proper URL parser
try:
parsed = urlparse(url)
except Exception as e:
raise ValueError(f"Invalid URL: {e}")
# FIXED: Validate required components
if not parsed.scheme:
raise ValueError("URL missing scheme")
if parsed.scheme not in ('http', 'https'):
raise ValueError(f"Invalid scheme: {parsed.scheme}")
if not parsed.netloc:
raise ValueError("URL missing hostname")
# FIXED: Validate hostname syntax
hostname = parsed.hostname
if hostname is None:
raise ValueError("Invalid hostname")
# Check hostname characters
hostname_pattern = r'^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$'
if not re.match(hostname_pattern, hostname):
raise ValueError(f"Invalid hostname syntax: {hostname}")
# FIXED: Validate port if present
if parsed.port is not None:
if parsed.port < 1 or parsed.port > 65535:
raise ValueError(f"Invalid port: {parsed.port}")
return parsed
# FIXED: Date parsing with format validation
def secure_parse_date(date_str, expected_format='%Y-%m-%d'):
"""Parse date with strict format validation."""
# FIXED: Validate format pattern
if not isinstance(date_str, str):
raise TypeError(f"Date must be string, got {type(date_str)}")
# FIXED: Validate length matches expected format
if expected_format == '%Y-%m-%d' and len(date_str) != 10:
raise ValueError(f"Invalid date format: {date_str}")
# FIXED: Use strict datetime parsing
try:
parsed = datetime.strptime(date_str, expected_format)
except ValueError as e:
raise ValueError(f"Invalid date: {e}")
# FIXED: Additional validation
# Ensure the parsed date matches the input (catch issues like Feb 30)
if parsed.strftime(expected_format) != date_str:
raise ValueError(f"Invalid date values in: {date_str}")
return {
'year': parsed.year,
'month': parsed.month,
'day': parsed.day
}
# FIXED: JSON config validation with schema
CONFIG_SCHEMA = {
"type": "object",
"required": ["serverUrl", "port"],
"properties": {
"serverUrl": {
"type": "string",
"pattern": "^https?://[a-zA-Z0-9.-]+(/.*)?$"
},
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
},
"timeout": {
"type": "integer",
"minimum": 0,
"maximum": 300000
}
},
"additionalProperties": False
}
def secure_parse_json_config(json_input):
"""Parse JSON config with schema validation."""
# FIXED: Parse JSON
try:
config = json.loads(json_input)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON syntax: {e}")
# FIXED: Validate against schema
try:
validate(instance=config, schema=CONFIG_SCHEMA)
except JsonValidationError as e:
raise ValueError(f"Config validation failed: {e.message}")
return config
CVE Examples
- CVE-2016-4029: Incorrect IP address format validation enabled octal/hex parsing bypass - IP filters could be bypassed using alternative notations.
- CVE-2007-5893: Missing HTTP protocol version validation caused application crashes.
Related CWEs
- CWE-20: Improper Input Validation (parent)
- CWE-112: Missing XML Validation (child)
- CWE-1215: Data Validation Issues (category)
- CWE-91: XML Injection (related)
References
- MITRE Corporation. "CWE-1286: Improper Validation of Syntactic Correctness of Input." https://cwe.mitre.org/data/definitions/1286.html
- OWASP. "Input Validation Cheat Sheet"
- W3C. "XML Schema Validation"