mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 16:38:54 +00:00

by elevating the containers one level up. Yes, I know this breaks all translations with a translated security section and I am working on solving their problems git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@165754 c90b9560-bf6c-de11-be94-00142212c4b1
157 lines
5 KiB
XML
157 lines
5 KiB
XML
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!-- $Revision: 1.3 $ -->
|
|
<!-- splitted from ./index.xml, last change in rev 1.66 -->
|
|
<chapter id="security.filesystem">
|
|
<title>Filesystem Security</title>
|
|
<simpara>
|
|
PHP is subject to the security built into most server systems with
|
|
respect to permissions on a file and directory basis. This allows
|
|
you to control which files in the filesystem may be read. Care
|
|
should be taken with any files which are world readable to ensure
|
|
that they are safe for reading by all users who have access to that
|
|
filesystem.
|
|
</simpara>
|
|
<simpara>
|
|
Since PHP was designed to allow user level access to the filesystem,
|
|
it's entirely possible to write a PHP script that will allow you
|
|
to read system files such as /etc/passwd, modify your ethernet
|
|
connections, send massive printer jobs out, etc. This has some
|
|
obvious implications, in that you need to ensure that the files
|
|
that you read from and write to are the appropriate ones.
|
|
</simpara>
|
|
<simpara>
|
|
Consider the following script, where a user indicates that they'd
|
|
like to delete a file in their home directory. This assumes a
|
|
situation where a PHP web interface is regularly used for file
|
|
management, so the Apache user is allowed to delete files in
|
|
the user home directories.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Poor variable checking leads to....</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// remove a file from the user's home directory
|
|
$username = $_POST['user_submitted_name'];
|
|
$homedir = "/home/$username";
|
|
$file_to_delete = "$userfile";
|
|
unlink ("$homedir/$userfile");
|
|
echo "$file_to_delete has been deleted!";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Since the username is postable from a user form, they can submit
|
|
a username and file belonging to someone else, and delete files.
|
|
In this case, you'd want to use some other form of authentication.
|
|
Consider what could happen if the variables submitted were
|
|
"../etc/" and "passwd". The code would then effectively read:
|
|
<example>
|
|
<title>... A filesystem attack</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// removes a file from anywhere on the hard drive that
|
|
// the PHP user has access to. If PHP has root access:
|
|
$username = "../etc/";
|
|
$homedir = "/home/../etc/";
|
|
$file_to_delete = "passwd";
|
|
unlink ("/home/../etc/passwd");
|
|
echo "/home/../etc/passwd has been deleted!";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
There are two important measures you should take to prevent these
|
|
issues.
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Only allow limited permissions to the PHP web user binary.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Check all variables which are submitted.
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
Here is an improved script:
|
|
<example>
|
|
<title>More secure file name checking</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// removes a file from the hard drive that
|
|
// the PHP user has access to.
|
|
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanisim
|
|
|
|
$homedir = "/home/$username";
|
|
|
|
$file_to_delete = basename("$userfile"); // strip paths
|
|
unlink ($homedir/$file_to_delete);
|
|
|
|
$fp = fopen("/home/logging/filedelete.log","+a"); //log the deletion
|
|
$logstring = "$username $homedir $file_to_delete";
|
|
fwrite ($fp, $logstring);
|
|
fclose($fp);
|
|
|
|
echo "$file_to_delete has been deleted!";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
However, even this is not without it's flaws. If your authentication
|
|
system allowed users to create their own user logins, and a user
|
|
chose the login "../etc/", the system is once again exposed. For
|
|
this reason, you may prefer to write a more customized check:
|
|
<example>
|
|
<title>More secure file name checking</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanisim
|
|
$homedir = "/home/$username";
|
|
|
|
if (!ereg('^[^./][^/]*$', $userfile))
|
|
die('bad filename'); //die, do not process
|
|
|
|
if (!ereg('^[^./][^/]*$', $username))
|
|
die('bad username'); //die, do not process
|
|
//etc...
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Depending on your operating system, there are a wide variety of files
|
|
which you should be concerned about, including device entries (/dev/
|
|
or COM1), configuration files (/etc/ files and the .ini files),
|
|
well known file storage areas (/home/, My Documents), etc. For this
|
|
reason, it's usually easier to create a policy where you forbid
|
|
everything except for what you explicitly allow.
|
|
</para>
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"../../manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|