Skip to content

PORT command: signed integer overflow in port number parsing (CWE-190) #216

Description

@xhy-520

Description

A signed integer overflow (CWE-190) was discovered in the PORT command
handler when parsing the port number portion of the h1,h2,h3,h4,p1,p2
format. The val variable (type int) can overflow during repeated
val *= 10 operations with no overflow check.

Affected Code

source/ftpSession.cpp, function FtpSession::PORT()`, lines 2941-2962:

int val = 0; // line 2941
for (auto p = portString; *p; ++p)
{
// ...
val *= 10; // line 2959 - NO overflow check
val += *p - '0'; // line 2960
}

// Check comes AFTER overflow already occurred:
if (val > 0xFF || port > 0xFF) // line 2964

Proof of Concept
Compiled with UBSAN (-fsanitize=signed-integer-overflow):
$ echo 'PORT 1,2,3,4,5,99999999999999' | nc

UBSAN output:
ftpSession.cpp:2959:21: runtime error: signed integer overflow:
1666666666 * 10 cannot be represented in type 'int'

Impact
• Signed integer overflow is undefined behavior per the C++ standard
• While the subsequent > 0xFF check catches most overflowed values, compiler optimizations may eliminate that check under UB assumptions
• Requires authentication (USER/PASS) before PORT is available
• CVSS 3.1 estimate: 2.3 (Low) — AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L
Proposed Fix
Add an overflow check before the multiplication:

if (val > INT_MAX / 10) // prevent overflow
{
sendResponse("501 %s\r\n", std::strerror(EINVAL));
return;
}
val *= 10;
Environment
• mtheall/ftpd v3.2.1
• Discovered via AFL++ 4.32a fuzzing with UBSAN
• Clang 15, Ubuntu 24.04

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions