Incorrectly Specified Destination in a Communication Channel
Description
Incorrectly Specified Destination in a Communication Channel occurs when a product creates an outgoing communication channel but fails to correctly specify the intended destination. This can happen when attackers can control or influence the destination specification, or when the product incorrectly identifies where data should be sent. This vulnerability is particularly prevalent in protocols that use connectionless communication (like UDP) where the destination is specified per-packet, or in systems that determine destinations dynamically based on potentially spoofed input data.
Risk
This vulnerability can lead to various attacks. In network amplification attacks, responses are redirected to victim addresses, overwhelming them with traffic (DDoS). Sensitive data may be sent to attacker-controlled destinations instead of legitimate servers. DNS responses can be redirected to enable cache poisoning. Open redirects can send users to malicious sites. Email or message systems can be abused to spam unintended recipients. The severity depends on the type of data transmitted and the protocol's amplification factor when used in reflection attacks.
Solution
Validate destination addresses before sending data. Never derive response destinations solely from unauthenticated request fields. For UDP-based protocols, implement connection establishment or validation handshakes. Use rate limiting on response traffic. Implement BCP38/RFC2827 ingress filtering to prevent source address spoofing. Avoid protocols susceptible to amplification where possible. Authenticate senders before responding. Consider using TCP where connection-oriented semantics provide inherent destination verification. Log and monitor unusual traffic patterns that might indicate misuse.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Read Application Data - Data sent to wrong destination may be intercepted by attackers. |
| Availability | Scope: Availability DoS: Amplification - Responses redirected to victim addresses enable denial-of-service amplification attacks. |
| Access Control | Scope: Access Control Gain Privileges or Assume Identity - Attackers can receive data or access functionality intended for legitimate destinations. |
Example Code
Vulnerable Code
// Vulnerable: DNS server responding to spoofed source
#include <sys/socket.h>
#include <netinet/in.h>
void vulnerable_dns_server(int socket_fd) {
char buffer[512];
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
while (1) {
// Receive DNS query
ssize_t received = recvfrom(socket_fd, buffer, sizeof(buffer), 0,
(struct sockaddr*)&client_addr, &addr_len);
if (received > 0) {
DNSQuery *query = parse_dns_query(buffer, received);
DNSResponse *response = create_dns_response(query);
// Vulnerable: Sending response to source address
// UDP source can be spoofed!
sendto(socket_fd, response->data, response->length, 0,
(struct sockaddr*)&client_addr, addr_len);
// If source is spoofed, response goes to victim
// Amplification attack: small query -> large response
}
}
}
// Vulnerable: NTP server susceptible to amplification
void vulnerable_ntp_handler(int socket_fd, char *buffer, size_t len,
struct sockaddr_in *client) {
NTPPacket *request = (NTPPacket *)buffer;
// Vulnerable: Processing "monlist" command
if (request->mode == NTP_MODE_PRIVATE && request->code == REQ_MON_GETLIST) {
// Response can be 200x larger than request (amplification)
// Sending to potentially spoofed address
MonitorList *list = get_monitor_list();
for (int i = 0; i < list->count; i++) {
sendto(socket_fd, &list->entries[i], sizeof(MonitorEntry), 0,
(struct sockaddr*)client, sizeof(*client));
}
}
}
# Vulnerable: Email service with open relay characteristics
import smtplib
def vulnerable_send_notification(user_email, message):
# Vulnerable: Email address from unvalidated user input
# Attacker can specify any email address
sender = "[email protected]"
recipient = user_email # User-controlled!
smtp = smtplib.SMTP('localhost')
smtp.sendmail(sender, recipient, message)
smtp.quit()
# Attack: user_email = "[email protected]" + thousands of addresses
# Abused as spam relay
// Vulnerable: Open redirect
app.get('/redirect', (req, res) => {
// Vulnerable: Redirect destination from user input
const destination = req.query.url;
// Attacker: /redirect?url=https://malicious-site.com
res.redirect(destination);
});
# Vulnerable: Webhook calling user-specified URL
import requests
def vulnerable_send_webhook(url, data):
# Vulnerable: URL from user input
# Can be used for SSRF or to send data to attacker
response = requests.post(url, json=data)
return response.status_code
Fixed Code
// Fixed: DNS server with rate limiting and validation
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#define MAX_REQUESTS_PER_IP 10
#define RATE_LIMIT_WINDOW 1 // seconds
typedef struct {
struct in_addr addr;
int count;
time_t window_start;
} RateLimitEntry;
RateLimitEntry rate_limits[10000];
void fixed_dns_server(int socket_fd) {
char buffer[512];
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
while (1) {
ssize_t received = recvfrom(socket_fd, buffer, sizeof(buffer), 0,
(struct sockaddr*)&client_addr, &addr_len);
if (received > 0) {
// Fixed: Rate limiting per source IP
if (!check_rate_limit(&client_addr.sin_addr)) {
continue; // Drop request from rate-limited IP
}
// Fixed: Validate query before responding
DNSQuery *query = parse_dns_query(buffer, received);
if (!is_valid_query(query)) {
continue;
}
DNSResponse *response = create_dns_response(query);
// Fixed: Response Rate Limiting (RRL)
// Limit response size to reduce amplification
if (response->length > 512) {
// Set TC flag, require TCP for large responses
response = create_truncated_response(query);
}
sendto(socket_fd, response->data, response->length, 0,
(struct sockaddr*)&client_addr, addr_len);
}
}
}
bool check_rate_limit(struct in_addr *addr) {
time_t now = time(NULL);
RateLimitEntry *entry = find_or_create_entry(addr);
if (now - entry->window_start > RATE_LIMIT_WINDOW) {
// New window
entry->count = 1;
entry->window_start = now;
return true;
}
entry->count++;
return entry->count <= MAX_REQUESTS_PER_IP;
}
// Fixed: NTP server with disabled monlist and rate limiting
void fixed_ntp_handler(int socket_fd, char *buffer, size_t len,
struct sockaddr_in *client) {
NTPPacket *request = (NTPPacket *)buffer;
// Fixed: Disable or restrict dangerous commands
if (request->mode == NTP_MODE_PRIVATE) {
// Only allow from authorized management IPs
if (!is_authorized_management_ip(&client->sin_addr)) {
return;
}
// Disable monlist entirely or implement rate limiting
if (request->code == REQ_MON_GETLIST) {
// Disabled to prevent amplification
send_error_response(socket_fd, client, NTP_ERR_DISABLED);
return;
}
}
// Normal NTP time sync - limited response size
if (request->mode == NTP_MODE_CLIENT) {
// Rate limit responses
if (!check_ntp_rate_limit(&client->sin_addr)) {
return;
}
NTPPacket response = create_time_response(request);
sendto(socket_fd, &response, sizeof(response), 0,
(struct sockaddr*)client, sizeof(*client));
}
}
# Fixed: Email service with destination validation
import smtplib
import re
ALLOWED_DOMAINS = {'mycompany.com', 'partner-company.com'}
MAX_RECIPIENTS = 10
def fixed_send_notification(user_email, message):
# Fixed: Validate email address format
if not is_valid_email(user_email):
raise ValueError("Invalid email address")
# Fixed: Check allowed domains (prevent open relay)
domain = user_email.split('@')[1].lower()
if domain not in ALLOWED_DOMAINS:
raise ValueError("Email domain not allowed")
sender = "[email protected]"
smtp = smtplib.SMTP('localhost')
smtp.sendmail(sender, user_email, message)
smtp.quit()
def is_valid_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
# For bulk notifications, validate list
def fixed_send_bulk(recipients, message):
# Fixed: Limit recipients
if len(recipients) > MAX_RECIPIENTS:
raise ValueError("Too many recipients")
validated_recipients = []
for email in recipients:
if is_valid_email(email):
domain = email.split('@')[1].lower()
if domain in ALLOWED_DOMAINS:
validated_recipients.append(email)
# ... send to validated recipients only
// Fixed: Safe redirect with allowlist
const ALLOWED_REDIRECT_PATHS = [
'/dashboard',
'/profile',
'/settings',
'/home'
];
const ALLOWED_EXTERNAL_DOMAINS = [
'trusted-partner.com',
'auth.mycompany.com'
];
app.get('/redirect', (req, res) => {
const destination = req.query.url;
// Fixed: Validate redirect destination
if (isAllowedRedirect(destination)) {
res.redirect(destination);
} else {
res.status(400).send('Invalid redirect destination');
}
});
function isAllowedRedirect(url) {
// Allow relative paths from allowlist
if (ALLOWED_REDIRECT_PATHS.includes(url)) {
return true;
}
// Parse external URLs
try {
const parsed = new URL(url);
// Only allow HTTPS
if (parsed.protocol !== 'https:') {
return false;
}
// Check against allowed domains
return ALLOWED_EXTERNAL_DOMAINS.some(domain =>
parsed.host === domain || parsed.host.endsWith('.' + domain)
);
} catch {
// Relative path not in allowlist
return false;
}
}
# Fixed: Webhook with URL validation
import requests
from urllib.parse import urlparse
import ipaddress
ALLOWED_WEBHOOK_DOMAINS = {'hooks.slack.com', 'api.github.com'}
BLOCKED_IP_RANGES = [
ipaddress.ip_network('10.0.0.0/8'),
ipaddress.ip_network('172.16.0.0/12'),
ipaddress.ip_network('192.168.0.0/16'),
ipaddress.ip_network('127.0.0.0/8'),
]
def fixed_send_webhook(url, data):
# Fixed: Validate URL
if not is_allowed_webhook_url(url):
raise ValueError("Webhook URL not allowed")
# Fixed: Set timeout, follow limited redirects
response = requests.post(
url,
json=data,
timeout=10,
allow_redirects=False
)
return response.status_code
def is_allowed_webhook_url(url):
try:
parsed = urlparse(url)
# Must be HTTPS
if parsed.scheme != 'https':
return False
# Check allowed domains
if parsed.netloc not in ALLOWED_WEBHOOK_DOMAINS:
return False
# Resolve and check IP isn't internal (SSRF prevention)
import socket
ip = socket.gethostbyname(parsed.hostname)
ip_obj = ipaddress.ip_address(ip)
for blocked_range in BLOCKED_IP_RANGES:
if ip_obj in blocked_range:
return False
return True
except Exception:
return False
CVE Examples
- CVE-2013-5211: NTP monlist command enabled massive amplification attacks with spoofed source addresses.
- CVE-1999-0513: Classic "Smurf" attack using ICMP with spoofed source addresses.
- CVE-1999-1379: DNS query spoofing causing traffic amplification.
Related CWEs
- CWE-923: Improper Restriction of Communication Channel to Intended Endpoints (parent)
- CWE-406: Insufficient Control of Network Message Volume (can follow)
- CWE-601: URL Redirection to Untrusted Site ('Open Redirect') (related)
References
- MITRE Corporation. "CWE-941: Incorrectly Specified Destination in a Communication Channel." https://cwe.mitre.org/data/definitions/941.html
- US-CERT. "UDP-Based Amplification Attacks."
- BCP 38/RFC 2827. "Network Ingress Filtering."