filesystem.xml: amend file style, add the tags (#3569)

* filesystem.xml: amend file style, add the tags

* filesystem.xml: fix tag mismatching

* Update security/filesystem.xml

Remove redundant dots after 'etc'

Co-authored-by: Gina Peter Banyard <girgias@php.net>

* Update security/filesystem.xml

nits

Co-authored-by: Gina Peter Banyard <girgias@php.net>

---------

Co-authored-by: Gina Peter Banyard <girgias@php.net>
This commit is contained in:
Mikhail Alferov
2024-08-26 00:45:28 +03:00
committed by GitHub
parent f79fac8b3d
commit 91570644fb

View File

@@ -14,7 +14,7 @@
<simpara>
Since <acronym>PHP</acronym> was designed to allow user level access to the filesystem,
it's entirely possible to write a <acronym>PHP</acronym> script that will allow you
to read system files such as /etc/passwd, modify your ethernet
to read system files such as <filename>/etc/passwd</filename>, 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.
@@ -32,7 +32,8 @@
<programlisting role="php">
<![CDATA[
<?php
// remove a file from the user's home directory
// Remove a file from the user's home directory
$username = $_POST['user_submitted_name'];
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
@@ -40,6 +41,7 @@ $homedir = "/home/$username";
unlink("$homedir/$userfile");
echo "The file has been deleted!";
?>
]]>
</programlisting>
@@ -49,13 +51,15 @@ echo "The file has been deleted!";
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:
<literal>"../etc/"</literal> and <literal>"passwd"</literal>.
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
// 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"
@@ -64,6 +68,7 @@ $homedir = "/home/$username"; // "/home/../etc"
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
echo "The file has been deleted!";
?>
]]>
</programlisting>
@@ -88,7 +93,8 @@ echo "The file has been deleted!";
<programlisting role="php">
<![CDATA[
<?php
// removes a file from the hard drive that
// Removes a file from the hard drive that
// the PHP user has access to.
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanism
$userfile = basename($_POST['user_submitted_filename']);
@@ -101,6 +107,7 @@ if (file_exists($filepath) && unlink($filepath)) {
} else {
$logstring = "Failed to delete $filepath\n";
}
$fp = fopen("/home/logging/filedelete.log", "a");
fwrite($fp, $logstring);
fclose($fp);
@@ -113,13 +120,14 @@ echo htmlentities($logstring, ENT_QUOTES);
</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
chose the login <literal>"../etc/"</literal>, 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";
@@ -130,7 +138,8 @@ if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $us
die("Bad username/filename");
}
//etc...
// etc.
?>
]]>
</programlisting>
@@ -138,9 +147,10 @@ if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $us
</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
which you should be concerned about, including device entries (<filename>/dev/</filename>
or <filename>COM1</filename>), configuration files (<filename>/etc/</filename> files and
the <literal>.ini</literal> files), well known file storage areas (<filename>/home/</filename>,
<filename>My Documents</filename>), etc. For this
reason, it's usually easier to create a policy where you forbid
everything except for what you explicitly allow.
</para>
@@ -159,12 +169,16 @@ if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $us
<programlisting role="php">
<![CDATA[
<?php
$file = $_GET['file']; // "../../etc/passwd\0"
if (file_exists('/home/wwwrun/'.$file.'.php')) {
// file_exists will return true as the file /home/wwwrun/../../etc/passwd exists
include '/home/wwwrun/'.$file.'.php';
// the file /etc/passwd will be included
if (file_exists('/home/wwwrun/' . $file . '.php')) {
// File_exists will return true as the file /home/wwwrun/../../etc/passwd exists
include '/home/wwwrun/' . $file . '.php';
// The file /etc/passwd will be included
}
?>
]]>
</programlisting>
@@ -178,6 +192,7 @@ if (file_exists('/home/wwwrun/'.$file.'.php')) {
<programlisting role="php">
<![CDATA[
<?php
$file = $_GET['file'];
// Whitelisting possible values
@@ -185,11 +200,12 @@ switch ($file) {
case 'main':
case 'foo':
case 'bar':
include '/home/wwwrun/include/'.$file.'.php';
include '/home/wwwrun/include/' . $file . '.php';
break;
default:
include '/home/wwwrun/include/main.php';
}
?>
]]>
</programlisting>