Vulnerability Title: Stack-Based Buffer Overflow in TR-111 Vendor-Specific DHCP Option Parsing of D-Link DIR-822A

Discovered by: tzh00203

Contact Information[email protected]

Affected Version: D-Link DIR-822A firmware builds based on the provided GPL source package that include TR-111 support; the exact public firmware version string should be confirmed on the test image before submission

Componentudhcpcd DHCP server, valid_tr111_cpe_parse() in serverpacket.c


1. Vulnerability Overview

A stack-based buffer overflow vulnerability exists in the udhcpcd DHCP server of D-Link DIR-822A. The issue is located in the TR-111 parsing routine for DHCP vendor-specific option 125, where attacker-controlled suboption data is copied into fixed-size stack buffers using strcpy() even though the source data is length-delimited DHCP option content rather than a NUL-terminated C string.

Because the vulnerable path is reachable from unauthenticated DHCP client traffic on the local network, a remote attacker on the LAN can trigger memory corruption by sending a crafted DHCP message containing a malicious option 125 payload.


2. Detailed Description

The vulnerability is present in valid_tr111_cpe_parse(struct dhcpMessage *oldpacket, char *devOUI, char *devSN, char *devPC) in udhcpcd/serverpacket.c.

The function retrieves DHCP vendor-specific option 125:

ptr = get_option(oldpacket, DHCP_VENDOR_SPECIFIC);

It then parses TR-111 suboptions and copies their data into fixed-size stack buffers:

if(*(ptr+OPT_CODE) == 1 && sub_data_len) {
    if(devOUI) strcpy(devOUI,(char*)(ptr+OPT_DATA));
}
else if(*(ptr+OPT_CODE) == 2 && sub_data_len){
    if(devSN) strcpy(devSN,(char*)(ptr+OPT_DATA));
}
else if(*(ptr+OPT_CODE) == 3 && sub_data_len){
    if(devPC) strcpy(devPC,(char*)(ptr+OPT_DATA));
}

However, DHCP option subfields are length-prefixed binary data, not guaranteed NUL-terminated strings. As a result, strcpy() will continue reading past the declared suboption boundary until a zero byte is encountered in subsequent memory, writing beyond the destination buffer.

The destination buffers are stack arrays:

char devOUI[256]={0},devSN[256]={0},devPC[256]={0};

The parser is invoked from both sendOffer() and sendACK():