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

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@233953 c90b9560-bf6c-de11-be94-00142212c4b1
168 lines
5.4 KiB
XML
168 lines
5.4 KiB
XML
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!-- $Revision: 1.4 $ -->
|
|
<!-- 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'];
|
|
$userfile = $_POST['user_submitted_filename'];
|
|
$homedir = "/home/$username";
|
|
|
|
unlink("$homedir/$userfile");
|
|
|
|
echo "The file has been deleted!";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Since the username and the filename are postable from a user form,
|
|
they can submit a username and a filename belonging to someone else,
|
|
and delete it even if they're not supposed to be allowed to do so.
|
|
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 = $_POST['user_submitted_name']; // "../etc"
|
|
$userfile = $_POST['user_submitted_filename']; // "passwd"
|
|
$homedir = "/home/$username"; // "/home/../etc"
|
|
|
|
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
|
|
|
|
echo "The file 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
|
|
$userfile = basename($_POST['user_submitted_filename']);
|
|
$homedir = "/home/$username";
|
|
|
|
$filepath = "$homedir/$userfile";
|
|
|
|
if (file_exists($filepath) && unlink($filepath)) {
|
|
$logstring = "Deleted $filepath\n";
|
|
} else {
|
|
$logstring = "Failed to delete $filepath\n";
|
|
}
|
|
$fp = fopen("/home/logging/filedelete.log", "a");
|
|
fwrite($fp, $lo gstring);
|
|
fclose($fp);
|
|
|
|
echo htmlentities($logstring, ENT_QUOTES);
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
However, even this is not without its 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
|
|
$userfile = $_POST['user_submitted_filename'];
|
|
$homedir = "/home/$username";
|
|
|
|
$filepath = "$homedir/$userfile";
|
|
|
|
if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) {
|
|
die("Bad username/filename");
|
|
}
|
|
|
|
//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
|
|
-->
|