Skip to content

ext/standard: reject control characters in the from address#170

Closed
iliaal wants to merge 1 commit into
PHP-8.4from
std-ss006-ftp-from-pass-ctl
Closed

ext/standard: reject control characters in the from address#170
iliaal wants to merge 1 commit into
PHP-8.4from
std-ss006-ftp-from-pass-ctl

Conversation

@iliaal

@iliaal iliaal commented Jul 16, 2026

Copy link
Copy Markdown
Owner

The ftp and http wrappers both build protocol data out of FG(from_address) without the control-character check they already apply to a URL-supplied password (ftp_fopen_wrapper.c:243, :260). A from address carrying CRLF injects a command into the FTP control channel after PASS, and a header into the HTTP request after From:

ini_set('from', "evil@example.com\r\nX-Injected: yes");
file_get_contents('http://example.com/');
// From: evil@example.com
// X-Injected: yes          <- injected

Both sinks now validate. The ftp wrapper fails the connection the way it already does for a bad URL password; the http wrapper drops the optional From header and warns, matching how it handles a User-agent it cannot construct.

Framing: from is PHP_INI_ALL, so setting it needs php.ini/.htaccess or ini_set(), and either already grants more than the injection buys. This is consistency with the checks at :243 and :260, not a trust boundary. user_agent sits at the same INI level and reaches the same request builder unvalidated, so it has the same shape.

The ftp and http wrappers build protocol data out of FG(from_address) without
the control-character check they already apply to a URL-supplied password, so a
from address carrying CRLF injects a command after PASS and a header after
From. Validate at both sinks. The from ini setting is PHP_INI_ALL, so this is
consistency with the existing checks rather than a trust boundary.
@iliaal
iliaal force-pushed the std-ss006-ftp-from-pass-ctl branch from fd3ed58 to f28947c Compare July 16, 2026 15:02
@iliaal iliaal changed the title ext/standard: reject control chars in FTP PASS from from address ext/standard: reject control characters in the from address Jul 16, 2026
@iliaal

iliaal commented Jul 16, 2026

Copy link
Copy Markdown
Owner Author

Superseded. The HTTP From: half of this duplicates phpGH-17976 (php#21658, merged to master 2026-06-24), which fixed from and user_agent together via a shared header-emit helper, and this only covered from, so it would have diverged from master on the forward-merge.

The FTP PASS half was the part that was genuinely missing (21658 deferred FTP/SOAP): php#22770, on master, reusing the existing PHP_FTP_CNTRL_CHK macro.

@iliaal iliaal closed this Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant