php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42492 FTP functions apparently use wrong IP address for PORT in PASV mode
Submitted: 2007-08-31 11:15 UTC Modified: 2008-04-02 01:00 UTC
Votes:4
Avg. Score:4.8 ± 0.4
Reproduced:4 of 4 (100.0%)
Same Version:2 (50.0%)
Same OS:3 (75.0%)
From: php at stock-consulting dot com Assigned: fb-req-jani (profile)
Status: No Feedback Package: FTP related
PHP Version: 5.2.4 OS: Windows 2000
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: php at stock-consulting dot com
New email:
PHP Version: OS:

 

 [2007-08-31 11:15 UTC] php at stock-consulting dot com
Description:
------------
Situation: the local machine, which executes the PHP script via the command line, sits behind a NAT firefall and needs to retrieve directory listings and files from an FTP server sitting somewhere on the Internet. Passive FTP is required to traverse the firewall. The local machine has the IP address 10.0.0.1 (subnet configured as Class C). The external (WAN) IP of the router/firewall is 80.x.x.x (address partially concealed to protect the, erm, innocent).

Now the problem: the script correctly connects to the FTP server and begins to retrieve directory listings (recursively) and files. At some RANDOM point, the following warning appears:

Warning: ftp_chdir(): PORT command only accepts client IP address (80.x.x.x
!=10.0.0.1). in my_script.php on line 40

This warning then appears both at all further attempts to retrieve directory listings and files. The transfers are not successful.

Note that directory and file retrieval works perfectly UNTIL the warning occurs for the first time, at some random time. When the script is restarted, it will again work for some listings and files, until, at some different point, the warning will appear again.

Reproduce code:
---------------
// Short version, stripped from anything which appeared not so useful for this bug report
function remote_scan($path) {
global $ftp;

	ftp_chdir($ftp, $path);
	$raw_entries = ftp_rawlist($ftp, $path);
	foreach ($raw_entries AS $line) {
		$entry = preg_split('@\s+@', $line, 9);
		if ($entry[4] == 0) {
			remote_scan($path . $entry[8] . '/');
		} else {
			ftp_get($ftp, 'x:/local_path' . $path . $entry[8], $path . $entry[8], FTP_BINARY);
		}
	}
}


$ftp = ftp_connect('ftp.url', 47624); // server uses non-standard port
$login_result = ftp_login($ftp, 'user', 'password'); 
ftp_pasv($ftp, true);
remote_scan('/');
ftp_close($ftp);


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-08-31 11:27 UTC] jani@php.net
And you're really using PHP 5.2.4?
 [2007-08-31 13:07 UTC] php at stock-consulting dot com
Yes, defnitely, I just downloaded it...yesterday? F***! ***! *** ** * ****!!!!! Just checked it (php.exe -v). It's PHP 5.2.3. Okay. Sorry.

Upgraded to 5.2.4 now, checked (php.exe -v), yup, now I'm at 5.2.4!

Yup. I can confirm the bug in 5.2.4 as well. The warning is now:

Warning: ftp_get(): PORT command only accepts client IP address (80.x.x.x!=
10.0.0.1). in my_script.php on line 71

Best regards, Klaus
 [2007-09-01 11:12 UTC] php at stock-consulting dot com
Further thoughts.

It appears to me that the message "PORT command only accepts..." originates from the FTP server.

"PORT command"? What "PORT command"? I thought I was using PASV?

Exactly. I can confim that I use ftp_pasv($ftp, true) once, and that I never turn passive mode off. So apparently the FTP functions somehow seem to "forget" (at some random point) that they should use PASV mode.

Always suspicious as I am, this smells like something like buffer overflow to me. Let's have a look at ftp.h:

typedef struct ftpbuf
{
	php_socket_t		fd;			/* control connection */
	php_sockaddr_storage	localaddr;	/* local address */
	int		resp;			/* last response code */
	char		inbuf[FTP_BUFSIZE];	/* last response text */
	char		*extra;			/* extra characters */
	int		extralen;		/* number of extra chars */
	char		outbuf[FTP_BUFSIZE];	/* command output buffer */
	char		*pwd;			/* cached pwd */
	char		*syst;			/* cached system type */
	ftptype_t	type;			/* current transfer type */
	int		pasv;			/* 0=off; 1=pasv; 2=ready */
<snip>

Hm, candiates might be inbuf and outbuf. However, a look at the code pieces which might be primary candidates for a buffer overflow revealed nothing suspicious to me.

However, I stumbled across a piece a code which looked kinda fishy to me, beginning at line 1140 in ftp.c:

/* shift the extra to the front */
size = FTP_BUFSIZE;
rcvd = 0;
if (ftp->extra) {
	memmove(ftp->inbuf, ftp->extra, ftp->extralen);
	rcvd = ftp->extralen;
}

ftp->extra, together with ftp->textralen, appear to be essentiall unbounded. Yuk! Now, I don't see any place where ftp->extra or ftp->extralen gets set. I should have a look at the initilization code,  to find out if it gets at least initialized correctly.

As soon as time permits - currently I have no time and so I've to leave this scene of investivation :-(

Best regards, Klaus
 [2008-04-02 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 17:01:58 2024 UTC