File: filesystem.xml

package info (click to toggle)
php-doc 20061001-1
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 45,764 kB
  • ctags: 1,611
  • sloc: xml: 502,485; php: 7,645; cpp: 500; makefile: 297; perl: 161; sh: 141; awk: 28
file content (157 lines) | stat: -rw-r--r-- 5,167 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?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
-->