Project

General

Profile

Actions

Bug #18623

closed

class.t3lib_exec.php prevents extension to work under PHP hardening

Added by Xavier Perseguers over 16 years ago. Updated about 6 years ago.

Status:
Closed
Priority:
Should have
Category:
-
Target version:
-
Start date:
2008-04-16
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
4.1
PHP Version:
5.2
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

When trying to use dam_index with index services using external tools such as pdftotext or exiftags, the BE reported that these tools were not available although some of them were used with indexed_search without any problem.

The problem relies in t3lib/class.t3lib_exec.php when checking if an external tool is executable or not. My server configuration is as follows:

PHP: open_basedir /var/www/somedir:/var/www/bin

in /var/www/bin, I have for instance a symbolic link

pdftotext -> /usr/bin/pdftotext

Now a call to is_executable('/usr/bin/pdftotext') always returns false when dealing with a symbolic link inside a directory found in the open_basedir list of directories.

As such, the t3lib_exec class assumes that the external tool pdftotext is not available.

The only solution I found was to list all executables as "openbase_dir":

php_admin_value open_basedir /var/www/somedir:/var/www/bin/pdftotext
(issue imported from #M8130)


Files

t3lib_exec.patch (917 Bytes) t3lib_exec.patch Administrator Admin, 2008-04-16 20:14
Actions #1

Updated by Xavier Perseguers over 16 years ago

The patch takes care of finding out if open_basedir is used and if so, assumes that the administrator knows what he did and returns true for any external tool located as a direct child of a directory listed in open_basedir PHP configuration's property.

Actions #2

Updated by Xavier Perseguers over 16 years ago

According to the description of how open_basedir behaves (http://ch2.php.net/manual/en/features.safe-mode.php#ini.open-basedir), all symbolic links are resolved before methods such as is_link() or is_executable() are called. That is PHP hardening as I did it prevents TYPO3 core's method addService() to work properly although no problem exists.

Actions #3

Updated by Michiel Roos over 16 years ago

I have also found the is_executable to return false in case of links. Since that day I use hard links to all the executables and relink all of them when I update packages on the server.

This works. But still, a code change may be sensible as a lot of users will want to just symlink stuff into the open_basedir.

What about a
if (@is_executable($path.$cmd) || @is_link($path.$cmd)) {

?

Actions #4

Updated by Xavier Perseguers over 16 years ago

I tried the is_link but I figured out that it did not work either. At least with the version of PHP I indcated (which is the stable version on Deban Etch), the is_link function tries to resolve the symbolic link prior to returning True. This leads to a openbase_dir error, just as with is_executable() and as such this method cannot be used either.

Actions #5

Updated by Michiel Roos over 16 years ago

also . . .

open_basedir may be involved. It does not count if you link to files outside of open_basedir

Actions #6

Updated by Xavier Perseguers over 16 years ago

Could you please explain a bit more? I do not understand well your note :-/

What I found is that symbolic links are resolved prior to the execution of the function. That is a link that points outside a directory listed in open_basedir leads to an error although it is just fine to execute a link to an executable outside open_basedir. This is why I think we should allow something in the addService method to either bypass this check or to circumvent it.

Actions #7

Updated by Michiel Roos over 16 years ago

Ok,

Looks like I was not paying attention to the first couple of comments you made on open_basedir.

I made a small test script to test the workings of the functions is_file, is_link and is_executable:

------------------------------------------------------------------------------

function check($cmd, $safeModeExecDir) {
echo '<br/><br/>checking '.$safeModeExecDir.$cmd.'<br/>';
if (is_file($safeModeExecDir.$cmd)) {
echo $cmd.' is a file<br/>';
} else {
echo $cmd.' is not a file<br/>';
}
if (is_executable($safeModeExecDir.$cmd)) {
echo $cmd.' is executable<br/>';
} else {
echo $cmd.' is not executable<br/>';
}
if (is_link($safeModeExecDir.$cmd)) {
echo $cmd.' is a link<br/>';
} else {
echo $cmd.' is not a link<br/>';
}
system($safeModeExecDir.$cmd.' '.$safeModeExecDir.'test.pdf');
}

$safeModeExecDir = '/var/www/php/exec/';

check('ls', $safeModeExecDir);
check('pdfinfo', $safeModeExecDir);

?>
------------------------------------------------------------------------------

My /var/www/php/exec looks as follows:
rwxr-xr-x 2 root root 85536 2007-01-30 21:38 ls
lrwxrwxrwx 1 root root 16 2008-05-16 08:03 pdfinfo -> /usr/bin/pdfinfo
-rw-r--r-
1 root root 88773 2008-05-16 09:18 test.pdf

So I have ls as a hard link (copy) and pdfinfo as a symlink

My php.ini looks as follows:
safe_mode = On
safe_mode_gid = On
open_basedir = "/var/www/:.:/var/www/php/exec"

The output of the script is:
------------------------------------------------------------------------------
checking /var/www/php/exec/ls
ls is not a file
ls is not executable
ls is not a link
/var/www/php/exec/test.pdf

checking /var/www/php/exec/pdfinfo

Warning: is_file() [function.is-file]: open_basedir restriction in effect. File(/var/www/php/exec/pdfinfo) is not within the allowed path(s): (/var/www/:.:/var/www/php/exec) in /var/www/dam/fileadmin/test.php on line 5
pdfinfo is not a file

Warning: is_executable() [function.is-executable]: open_basedir restriction in effect. File(/var/www/php/exec/pdfinfo) is not within the allowed path(s): (/var/www/:.:/var/www/php/exec) in /var/www/dam/fileadmin/test.php on line 10
pdfinfo is not executable

Warning: is_link() [function.is-link]: open_basedir restriction in effect. File(/var/www/php/exec/pdfinfo) is not within the allowed path(s): (/var/www/:.:/var/www/php/exec) in /var/www/dam/fileadmin/test.php on line 15
pdfinfo is not a link
Title: Author: XXX: Acrobat PDFMaker 8.1 voor Word Producer: Acrobat Distiller 8.1.0 (Zinloos) CreationDate: Sun Feb 17 22:52:34 2008 ModDate: Mon Feb 18 12:28:38 2008 Tagged: yes Pages: 4 Encrypted: no Page size: 595.22 x 842 pts (A4) File size: 88773 bytes Optimized: yes PDF version: 1.4
------------------------------------------------------------------------------

When I disable open_basedir:
------------------------------------------------------------------------------
checking /var/www/php/exec/ls
ls is not a file
ls is not executable
ls is not a link
/var/www/php/exec/test.pdf

checking /var/www/php/exec/pdfinfo
pdfinfo is not a file
pdfinfo is not executable
pdfinfo is not a link
Title: Author: XXX: Acrobat PDFMaker 8.1 voor Word Producer: Acrobat Distiller 8.1.0 (Zinloos) CreationDate: Sun Feb 17 22:52:34 2008 ModDate: Mon Feb 18 12:28:38 2008 Tagged: yes Pages: 4 Encrypted: no Page size: 595.22 x 842 pts (A4) File size: 88773 bytes Optimized: yes PDF version: 1.4
------------------------------------------------------------------------------

When safe mode and open_Basedir are both off:
------------------------------------------------------------------------------
checking /var/www/php/exec/ls
ls is a file
ls is executable
ls is not a link
/var/www/php/exec/test.pdf

checking /var/www/php/exec/pdfinfo
pdfinfo is a file
pdfinfo is executable
pdfinfo is a link
Title: Author: XXX: Acrobat PDFMaker 8.1 voor Word Producer: Acrobat Distiller 8.1.0 (Zinloos) CreationDate: Sun Feb 17 22:52:34 2008 ModDate: Mon Feb 18 12:28:38 2008 Tagged: yes Pages: 4 Encrypted: no Page size: 595.22 x 842 pts (A4) File size: 88773 bytes Optimized: yes PDF version: 1.4
------------------------------------------------------------------------------

So the conclusion is that PHP basically totally denies all existence of the executables when safe_mode is enabled (with or without open_basedir).

:-)

It still happily executes the programs!

Strange behavior indeed.

Actions #8

Updated by Xavier Perseguers over 16 years ago

Could someone of the core take a look at it? Bug's still here...

Actions #9

Updated by Michiel Roos over 16 years ago

. . . . since it's bugfixing day and all . . .

;-)

Actions #10

Updated by Dmitry Dulepov about 16 years ago

Wouldn't realpath() solve the problem? I.e.

$realpath = realpath($file);
$executable = $realpath && is_executable($realpath);

realpath() is supposed to resolve links:
<q>
realpath
(PHP 4, PHP 5)

realpath — Returns canonicalized absolute pathname

Description

string realpath ( string $path )

realpath() expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the input path. and return the canonicalized absolute pathname.
</q>

Actions #11

Updated by Xavier Perseguers about 16 years ago

Yes but as explained in comment 0022032 by Michiel, is_executable still always return FALSE when given a symbolic link as parameter that points out of the open_basedir list.

Actions #12

Updated by Christian Kuhn over 15 years ago

Set to resolved, "not fixable"

Quote from Xavier:
I agreed to reject this bug (with proper comment) as we'll not agree
on a solution for this weird situation.

Dig into core list discussion for better explanation.

Please reopen if I messed something up.

Actions #13

Updated by Benni Mack about 6 years ago

  • Status changed from Resolved to Closed
Actions

Also available in: Atom PDF