mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-16 00:48:54 +00:00
revise database.security section
remove bla-bla note that attack examples are not database server specific git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@68050 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
parent
69d2467b6a
commit
56fb691746
2 changed files with 276 additions and 242 deletions
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- $Revision: 1.40 $ -->
|
||||
<!-- $Revision: 1.41 $ -->
|
||||
<chapter id="security">
|
||||
<title>Security</title>
|
||||
|
||||
|
@ -117,7 +117,7 @@
|
|||
</simpara>
|
||||
<simpara>
|
||||
When invoked as a CGI binary, PHP refuses to interpret the
|
||||
command line arguments.
|
||||
command line arguments.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
|
@ -184,7 +184,7 @@
|
|||
Action directives (see below).
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="security.cgi-bin.force-redirect">
|
||||
<title>Case 2: using --enable-force-cgi-redirect</title>
|
||||
<simpara>
|
||||
|
@ -214,7 +214,7 @@ AddHandler php-script .php
|
|||
here.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="security.cgi-bin.doc-root">
|
||||
<title>Case 3: setting doc_root or user_dir</title>
|
||||
<simpara>
|
||||
|
@ -256,7 +256,7 @@ AddHandler php-script .php
|
|||
called <filename role="uri">~user/doc.php</filename> under
|
||||
doc_root (yes, a directory name starting with a tilde
|
||||
[<literal>~</literal>]).
|
||||
</simpara>
|
||||
</simpara>
|
||||
<simpara>
|
||||
If user_dir is set to for example <filename
|
||||
role="dir">public_php</filename>, a request like <filename
|
||||
|
@ -274,7 +274,7 @@ AddHandler php-script .php
|
|||
separately.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="security.cgi-bin.shell">
|
||||
<title>Case 4: PHP parser outside of web tree</title>
|
||||
<para>
|
||||
|
@ -305,7 +305,7 @@ AddHandler php-script .php
|
|||
configure option.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="security.apache">
|
||||
|
@ -344,7 +344,7 @@ AddHandler php-script .php
|
|||
those who are not security professionals.
|
||||
</simpara>
|
||||
<simpara>
|
||||
There are some simpler solutions. By using
|
||||
There are some simpler solutions. By using
|
||||
<link linkend="ini.open-basedir">open_basedir</link> you can control and restrict what
|
||||
directories are allowed to be used for PHP. You can also set up
|
||||
apache-only areas, to restrict all web based activity to non-user,
|
||||
|
@ -413,7 +413,7 @@ echo "/home/../etc/passwd has been deleted!";
|
|||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
There are two important measures you should take to prevent these
|
||||
issues.
|
||||
<itemizedlist>
|
||||
|
@ -435,7 +435,7 @@ echo "/home/../etc/passwd has been deleted!";
|
|||
<![CDATA[
|
||||
<?php
|
||||
// removes a file from the hard drive that
|
||||
// the PHP user has access to.
|
||||
// the PHP user has access to.
|
||||
$username = $HTTP_SERVER_VARS['REMOTE_USER']; // using an authentication mechanisim
|
||||
|
||||
$homedir = "/home/$username";
|
||||
|
@ -467,14 +467,14 @@ $homedir = "/home/$username";
|
|||
|
||||
if (!ereg('^[^./][^/]*$', $userfile))
|
||||
die('bad filename'); //die, do not process
|
||||
|
||||
|
||||
if (!ereg('^[^./][^/]*$', $username))
|
||||
die('bad username'); //die, do not process
|
||||
die('bad username'); //die, do not process
|
||||
//etc...
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
Depending on your operating system, there are a wide variety of files
|
||||
|
@ -483,7 +483,7 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
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>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="security.database">
|
||||
|
@ -495,13 +495,6 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
or secret informations can be stored in such database, you should strongly
|
||||
consider to protect them somehow.
|
||||
</simpara>
|
||||
<simpara>
|
||||
PHP can be treated as a bridge between the database and client. Your script
|
||||
processes the client's request, and propagates it in such manner that the
|
||||
database can provide the appropriate response. After that, the script
|
||||
generates its output from the supplied data, probably based on customizeable
|
||||
user preferences stored in database, too.
|
||||
</simpara>
|
||||
<simpara>
|
||||
To retrieve or to store any information you need to connect to the database,
|
||||
send a legitimate query, fetch the result, and close the connecion.
|
||||
|
@ -583,10 +576,10 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
</simpara>
|
||||
<simpara>
|
||||
Once an attacker gains access to your database directly (bypassing the
|
||||
webserver), the sensitive data stored in it may be exposed or misused,
|
||||
unless the information is protected by the database itself. Encrypting
|
||||
the data is a good way to mitigate this threat, but very few databases
|
||||
offer this type of data encryption.
|
||||
webserver), the stored sensitive data may be exposed or misused unless,
|
||||
the information is protected by the database itself. Encrypting the data
|
||||
is a good way to mitigate this threat, but very few databases offer this
|
||||
type of data encryption.
|
||||
</simpara>
|
||||
<simpara>
|
||||
The easiest way to work around this problem is to first create your own
|
||||
|
@ -594,15 +587,15 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
can assist you in this case with its several extensions, such as <link
|
||||
linkend="ref.mcrypt">Mcrypt</link> and <link
|
||||
linkend="ref.mhash">Mhash</link>, covering a wide variety of encryption
|
||||
algorithms. The script encrypts the data be stored first, and decrypts
|
||||
it when retrieving. See the references for further examples how
|
||||
algorithms. The script encrypts the data be stored first, and decrypts
|
||||
it when retrieving. See the references for further examples how
|
||||
encryption works.
|
||||
</simpara>
|
||||
<simpara>
|
||||
In case of truly hidden data, if its raw representation is not needed
|
||||
In case of truly hidden data, if its raw representation is not needed
|
||||
(i.e. not be displayed), hashing may be also taken into consideration.
|
||||
The well-known example for the hashing is storing the MD5 hash of a
|
||||
password in a database, instead of the password itself. See also
|
||||
The well-known example for the hashing is storing the MD5 hash of a
|
||||
password in a database, instead of the password itself. See also
|
||||
<function>crypt</function> and <function>md5</function>.
|
||||
</simpara>
|
||||
<example>
|
||||
|
@ -621,7 +614,7 @@ $result = pg_exec($connection, $query);
|
|||
|
||||
if (pg_numrows($result) > 0) {
|
||||
echo "Wellcome, $username!";
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo "Authentication failed for $username.";
|
||||
}
|
||||
|
@ -633,7 +626,7 @@ else {
|
|||
<sect2 id="security.database.sql-injection">
|
||||
<title>SQL Injection</title>
|
||||
<simpara>
|
||||
Many web applications are unaware of how SQL queries can be tampered with,
|
||||
Many web developers are unaware of how SQL queries can be tampered with,
|
||||
and assume that an SQL query is a trusted command. It means that SQL
|
||||
queries are able to circumvent access controls, thereby bypassing standard
|
||||
authentication and authorization checks, and sometimes SQL queries even
|
||||
|
@ -655,7 +648,10 @@ else {
|
|||
behalf of a superuser or the owner who can create users, the attacker
|
||||
may create a superuser in your database.
|
||||
<example>
|
||||
<title>Splitting the result set into pages - and making superusers</title>
|
||||
<title>
|
||||
Splitting the result set into pages ... and making superusers
|
||||
(PostgreSQL and MySQL)
|
||||
</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$offset = argv[0]; // beware, no input validation!
|
||||
|
@ -664,11 +660,11 @@ $result = pg_exec($conn, $query);
|
|||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
Normal users click on the 'next', 'prev' links where the offset is
|
||||
appended to the URL. The script expects that the incoming
|
||||
<varname>$offset</varname> is numeric. However, if someone tries to
|
||||
Normal users click on the 'next', 'prev' links where the <varname>$offset</varname>
|
||||
is encoded into the URL. The script expects that the incoming
|
||||
<varname>$offset</varname> is decimal number. However, someone tries to
|
||||
break in with appending <function>urlencode</function>'d form of the
|
||||
following to the URL:
|
||||
following to the URL (PostgreSQL):
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
|
@ -679,7 +675,7 @@ insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
|
|||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
or
|
||||
or more precisely:
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
|
@ -691,9 +687,19 @@ insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
|
|||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
then the script will present a superuser access to him. Note that
|
||||
<literal>0;</literal> is to supply a valid offset to the original
|
||||
query and to terminate it.
|
||||
or in case of using MySQL:
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
0;
|
||||
UPDATE user SET Password=PASSWORD('crack') WHERE user='root';
|
||||
FLUSH PRIVILEGES;
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
If it happened, then the script would present a superuser access to him.
|
||||
Note that <literal>0;</literal> is to supply a valid offset to the
|
||||
original query and to terminate it.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
|
@ -705,7 +711,9 @@ insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
|
|||
<para>
|
||||
A feasible way to gain passwords:
|
||||
<example>
|
||||
<title>Listing out articles - and some passwords</title>
|
||||
<title>
|
||||
Listing out articles ... and some passwords (any database server)
|
||||
</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "SELECT id, name, inserted, size FROM products WHERE size = '$size';";
|
||||
|
@ -725,9 +733,11 @@ union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from use
|
|||
<literal>'</literal>), the query beast awakened.
|
||||
</para>
|
||||
<para>
|
||||
SQL updates are also subject to attacking your database.
|
||||
SQL UPDATEs are also subject to attacking your database.
|
||||
<example>
|
||||
<title>From resetting a password to gaining more privileges</title>
|
||||
<title>
|
||||
From resetting a password ... to gaining more privileges (any database server)
|
||||
</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
|
||||
|
@ -760,7 +770,7 @@ $query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE ...;
|
|||
A frightening example how operating system level commands can be accessed
|
||||
on some database hosts.
|
||||
<example>
|
||||
<title>Attacking the database host's operating system</title>
|
||||
<title>Attacking the database host's operating system (MSSQL Server)</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
|
||||
|
@ -769,12 +779,12 @@ $result = mssql_query($query);
|
|||
</programlisting>
|
||||
</example>
|
||||
If attacker submits the value
|
||||
<literal>%' exec master..xp_cmdshell 'net user test testpass /ADD' --</literal>
|
||||
<literal>a%' exec master..xp_cmdshell 'net user test testpass /ADD' --</literal>
|
||||
to <varname>$prod</varname>, then the <varname>$query</varname> will be:
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "SELECT * FROM products WHERE id LIKE '%%' exec master..xp_cmdshell 'net user test testpass /ADD'--";
|
||||
$query = "SELECT * FROM products WHERE id LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--";
|
||||
$result = mssql_query($query);
|
||||
]]>
|
||||
</programlisting>
|
||||
|
@ -785,6 +795,13 @@ $result = mssql_query($query);
|
|||
running with sufficient privileges, the attacker would now have an
|
||||
account with which to access this machine.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Some of the examples above is tied to a specific database server. This
|
||||
does not mean that a similar attack is impossible against other products.
|
||||
Your database server may be so vulnerable in other manner.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<sect3 id="security.database.avoiding">
|
||||
<title>Avoiding techniques</title>
|
||||
|
@ -806,26 +823,26 @@ $result = mssql_query($query);
|
|||
</simpara>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
First, check if the given input has the expected data type. PHP has
|
||||
a wide range of input validating functions, from the simplest ones
|
||||
found in <link linkend="ref.variables">Variable Functions</link> and
|
||||
in <link linkend="ref.ctype">Character Type Functions</link>
|
||||
sections, (e.g. <function>is_numeric</function>,
|
||||
<function>ctype_digit</function> respectively) onwards the
|
||||
<link linkend="ref.pcre">Perl compatible Regular Expressions</link>
|
||||
support.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
If the application waits for numeric input, consider to verify data
|
||||
with <function>is_numeric</function>, or silently change its type
|
||||
using <function>settype</function> or <function>sprintf()</function>.
|
||||
<example>
|
||||
<title>A more secure way to compose a query for paging</title>
|
||||
<programlisting role="php">
|
||||
<listitem>
|
||||
<simpara>
|
||||
First, check if the given input has the expected data type. PHP has
|
||||
a wide range of input validating functions, from the simplest ones
|
||||
found in <link linkend="ref.variables">Variable Functions</link> and
|
||||
in <link linkend="ref.ctype">Character Type Functions</link>
|
||||
sections, (e.g. <function>is_numeric</function>,
|
||||
<function>ctype_digit</function> respectively) onwards the
|
||||
<link linkend="ref.pcre">Perl compatible Regular Expressions</link>
|
||||
support.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
If the application waits for numeric input, consider to verify data
|
||||
with <function>is_numeric</function>, or silently change its type
|
||||
using <function>settype</function> or <function>sprintf()</function>.
|
||||
<example>
|
||||
<title>A more secure way to compose a query for paging</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
settype($order, 'integer');
|
||||
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
|
||||
|
@ -833,43 +850,43 @@ $query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"
|
|||
// please note %d in the format string, using %s would be meaningless
|
||||
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;", $offset);
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Quote user input which is passed to the database with
|
||||
<function>addslashes</function> or <function>addcslashes</function>.
|
||||
See <link linkend="security.database.storage">this example</link>.
|
||||
As the examples shows, quotes burnt into the static part of the query
|
||||
is not enough, and can be easily hacked.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Do not print out any database specific information, especially
|
||||
about the schema, no matter what happens. See also <link
|
||||
linkend="security.errors">Error Reporting</link> and <link
|
||||
linkend="ref.errorfunc">Error Handling and Logging Functions</link>.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
You may use stored procedures and previously defined cursors to abstract
|
||||
data access so that users do not directly access tables or views, but
|
||||
this solution has another impacts.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Quote user input which is passed to the database with
|
||||
<function>addslashes</function> or <function>addcslashes</function>.
|
||||
See <link linkend="security.database.storage">this example</link>.
|
||||
As the examples shows, quotes burnt into the static part of the query
|
||||
is not enough, and can be easily hacked.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Do not print out any database specific information, especially
|
||||
about the schema, no matter what happens. See also <link
|
||||
linkend="security.errors">Error Reporting</link> and <link
|
||||
linkend="ref.errorfunc">Error Handling and Logging Functions</link>.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
You may use stored procedures and previously defined cursors to abstract
|
||||
data access so that users do not directly access tables or views, but
|
||||
this solution has another impacts.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<simpara>
|
||||
Besides these, you benefit from logging queries either within your script
|
||||
or by the database itself, if it supports. Obviously, the logging is unable
|
||||
to prevent any harmful attempt, but it can be helpful to trace back which
|
||||
application has been circumvented. The log is not useful by itself, but
|
||||
through the information it contains. The more detail is generally better.
|
||||
</simpara>
|
||||
<simpara>
|
||||
Besides these, you benefit from logging queries either within your script
|
||||
or by the database itself, if it supports. Obviously, the logging is unable
|
||||
to prevent any harmful attempt, but it can be helpful to trace back which
|
||||
application has been circumvented. The log is not useful by itself, but
|
||||
through the information it contains. The more detail is generally better.
|
||||
</simpara>
|
||||
</sect3>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
@ -898,7 +915,7 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
</form>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
The PHP errors which are normally returned can be quite helpful to a
|
||||
|
@ -906,10 +923,10 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
as the function or file that failed, the PHP file it failed in,
|
||||
and the line number which the failure occured in. This is all
|
||||
information that can be exploited. It is not uncommon for a php
|
||||
developer to use <function>show_source</function>,
|
||||
<function>highlight_string</function>, or
|
||||
<function>highlight_file</function> as a debugging measure, but in
|
||||
a live site, this can expose hidden variables, unchecked syntax,
|
||||
developer to use <function>show_source</function>,
|
||||
<function>highlight_string</function>, or
|
||||
<function>highlight_file</function> as a debugging measure, but in
|
||||
a live site, this can expose hidden variables, unchecked syntax,
|
||||
and other dangerous information. Especially dangerous is running
|
||||
code from known sources with built-in debugging handlers, or using
|
||||
common debugging techniques. If the attacker can determine what
|
||||
|
@ -926,7 +943,7 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
</form>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
Regardless of the method of error handling, the ability to probe a
|
||||
|
@ -980,7 +997,7 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
<![CDATA[
|
||||
<?php
|
||||
if ($username) { // Not initialized or checked before usage
|
||||
$good_login = 1;
|
||||
$good_login = 1;
|
||||
}
|
||||
if ($good_login == 1) { // If above test fails, not initialized or checked before usage
|
||||
fpassthru ("/highly/sensitive/data/index.html");
|
||||
|
@ -995,9 +1012,9 @@ if ($good_login == 1) { // If above test fails, not initialized or checked befor
|
|||
<sect1 id="security.registerglobals">
|
||||
<title>Using Register Globals</title>
|
||||
<para>
|
||||
One feature of PHP that can be used to enhance security is configuring PHP with
|
||||
<link linkend="ini.register-globals">register_globals</link> = off.
|
||||
By turning off the ability for any user-submitted variable to be injected
|
||||
One feature of PHP that can be used to enhance security is configuring PHP with
|
||||
<link linkend="ini.register-globals">register_globals</link> = off.
|
||||
By turning off the ability for any user-submitted variable to be injected
|
||||
into PHP code, you can reduce the amount of variable
|
||||
poisoning a potential attacker may inflict. They will have
|
||||
to take the additional time to forge submissions, and your
|
||||
|
@ -1014,7 +1031,7 @@ if ($good_login == 1) { // If above test fails, not initialized or checked befor
|
|||
<![CDATA[
|
||||
<?php
|
||||
if ($username) { // can be forged by a user in get/post/cookies
|
||||
$good_login = 1;
|
||||
$good_login = 1;
|
||||
}
|
||||
|
||||
if ($good_login == 1) { // can be forged by a user in get/post/cookies,
|
||||
|
@ -1029,7 +1046,7 @@ if ($good_login == 1) { // can be forged by a user in get/post/cookies,
|
|||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
if($HTTP_COOKIE_VARS['username']){
|
||||
if($HTTP_COOKIE_VARS['username']){
|
||||
// can only come from a cookie, forged or otherwise
|
||||
$good_login = 1;
|
||||
fpassthru ("/highly/sensitive/data/index.html");
|
||||
|
@ -1052,7 +1069,7 @@ if($HTTP_COOKIE_VARS['username']){
|
|||
<?php
|
||||
if ($HTTP_COOKIE_VARS['username'] &&
|
||||
!$HTTP_POST_VARS['username'] &&
|
||||
!$HTTP_GET_VARS['username'] ) {
|
||||
!$HTTP_GET_VARS['username'] ) {
|
||||
// Perform other checks to validate the user name...
|
||||
$good_login = 1;
|
||||
fpassthru ("/highly/sensitive/data/index.html");
|
||||
|
@ -1071,7 +1088,7 @@ if ($HTTP_COOKIE_VARS['username'] &&
|
|||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
|
||||
<sect1 id="security.variables">
|
||||
<title>User Submitted Data</title>
|
||||
<para>
|
||||
|
@ -1124,7 +1141,7 @@ exec ($evil_var);
|
|||
Can this be used in conjunction with other scripts in a negative
|
||||
manner?
|
||||
</simpara>
|
||||
</listitem>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Will any transactions be adequately logged?
|
||||
|
@ -1147,7 +1164,7 @@ exec ($evil_var);
|
|||
operated upon).
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="security.hiding">
|
||||
<title>Hiding PHP</title>
|
||||
<para>
|
||||
|
@ -1162,7 +1179,7 @@ exec ($evil_var);
|
|||
</para>
|
||||
<para>
|
||||
Another tactic is to configure web servers such as apache to
|
||||
parse different filetypes through PHP, either with an .htaccess
|
||||
parse different filetypes through PHP, either with an .htaccess
|
||||
directive, or in the apache configuration file itself. You can
|
||||
then use misleading file extensions:
|
||||
<example>
|
||||
|
@ -1200,7 +1217,7 @@ AddType application/x-httpd-php .htm .html
|
|||
obscurity, it's a minor preventative measure with few drawbacks.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="security.current">
|
||||
<title>Keeping Current</title>
|
||||
<simpara>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- $Revision: 1.40 $ -->
|
||||
<!-- $Revision: 1.41 $ -->
|
||||
<chapter id="security">
|
||||
<title>Security</title>
|
||||
|
||||
|
@ -117,7 +117,7 @@
|
|||
</simpara>
|
||||
<simpara>
|
||||
When invoked as a CGI binary, PHP refuses to interpret the
|
||||
command line arguments.
|
||||
command line arguments.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
|
@ -184,7 +184,7 @@
|
|||
Action directives (see below).
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="security.cgi-bin.force-redirect">
|
||||
<title>Case 2: using --enable-force-cgi-redirect</title>
|
||||
<simpara>
|
||||
|
@ -214,7 +214,7 @@ AddHandler php-script .php
|
|||
here.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="security.cgi-bin.doc-root">
|
||||
<title>Case 3: setting doc_root or user_dir</title>
|
||||
<simpara>
|
||||
|
@ -256,7 +256,7 @@ AddHandler php-script .php
|
|||
called <filename role="uri">~user/doc.php</filename> under
|
||||
doc_root (yes, a directory name starting with a tilde
|
||||
[<literal>~</literal>]).
|
||||
</simpara>
|
||||
</simpara>
|
||||
<simpara>
|
||||
If user_dir is set to for example <filename
|
||||
role="dir">public_php</filename>, a request like <filename
|
||||
|
@ -274,7 +274,7 @@ AddHandler php-script .php
|
|||
separately.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="security.cgi-bin.shell">
|
||||
<title>Case 4: PHP parser outside of web tree</title>
|
||||
<para>
|
||||
|
@ -305,7 +305,7 @@ AddHandler php-script .php
|
|||
configure option.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="security.apache">
|
||||
|
@ -344,7 +344,7 @@ AddHandler php-script .php
|
|||
those who are not security professionals.
|
||||
</simpara>
|
||||
<simpara>
|
||||
There are some simpler solutions. By using
|
||||
There are some simpler solutions. By using
|
||||
<link linkend="ini.open-basedir">open_basedir</link> you can control and restrict what
|
||||
directories are allowed to be used for PHP. You can also set up
|
||||
apache-only areas, to restrict all web based activity to non-user,
|
||||
|
@ -413,7 +413,7 @@ echo "/home/../etc/passwd has been deleted!";
|
|||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
There are two important measures you should take to prevent these
|
||||
issues.
|
||||
<itemizedlist>
|
||||
|
@ -435,7 +435,7 @@ echo "/home/../etc/passwd has been deleted!";
|
|||
<![CDATA[
|
||||
<?php
|
||||
// removes a file from the hard drive that
|
||||
// the PHP user has access to.
|
||||
// the PHP user has access to.
|
||||
$username = $HTTP_SERVER_VARS['REMOTE_USER']; // using an authentication mechanisim
|
||||
|
||||
$homedir = "/home/$username";
|
||||
|
@ -467,14 +467,14 @@ $homedir = "/home/$username";
|
|||
|
||||
if (!ereg('^[^./][^/]*$', $userfile))
|
||||
die('bad filename'); //die, do not process
|
||||
|
||||
|
||||
if (!ereg('^[^./][^/]*$', $username))
|
||||
die('bad username'); //die, do not process
|
||||
die('bad username'); //die, do not process
|
||||
//etc...
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
Depending on your operating system, there are a wide variety of files
|
||||
|
@ -483,7 +483,7 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
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>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="security.database">
|
||||
|
@ -495,13 +495,6 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
or secret informations can be stored in such database, you should strongly
|
||||
consider to protect them somehow.
|
||||
</simpara>
|
||||
<simpara>
|
||||
PHP can be treated as a bridge between the database and client. Your script
|
||||
processes the client's request, and propagates it in such manner that the
|
||||
database can provide the appropriate response. After that, the script
|
||||
generates its output from the supplied data, probably based on customizeable
|
||||
user preferences stored in database, too.
|
||||
</simpara>
|
||||
<simpara>
|
||||
To retrieve or to store any information you need to connect to the database,
|
||||
send a legitimate query, fetch the result, and close the connecion.
|
||||
|
@ -583,10 +576,10 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
</simpara>
|
||||
<simpara>
|
||||
Once an attacker gains access to your database directly (bypassing the
|
||||
webserver), the sensitive data stored in it may be exposed or misused,
|
||||
unless the information is protected by the database itself. Encrypting
|
||||
the data is a good way to mitigate this threat, but very few databases
|
||||
offer this type of data encryption.
|
||||
webserver), the stored sensitive data may be exposed or misused unless,
|
||||
the information is protected by the database itself. Encrypting the data
|
||||
is a good way to mitigate this threat, but very few databases offer this
|
||||
type of data encryption.
|
||||
</simpara>
|
||||
<simpara>
|
||||
The easiest way to work around this problem is to first create your own
|
||||
|
@ -594,15 +587,15 @@ if (!ereg('^[^./][^/]*$', $username))
|
|||
can assist you in this case with its several extensions, such as <link
|
||||
linkend="ref.mcrypt">Mcrypt</link> and <link
|
||||
linkend="ref.mhash">Mhash</link>, covering a wide variety of encryption
|
||||
algorithms. The script encrypts the data be stored first, and decrypts
|
||||
it when retrieving. See the references for further examples how
|
||||
algorithms. The script encrypts the data be stored first, and decrypts
|
||||
it when retrieving. See the references for further examples how
|
||||
encryption works.
|
||||
</simpara>
|
||||
<simpara>
|
||||
In case of truly hidden data, if its raw representation is not needed
|
||||
In case of truly hidden data, if its raw representation is not needed
|
||||
(i.e. not be displayed), hashing may be also taken into consideration.
|
||||
The well-known example for the hashing is storing the MD5 hash of a
|
||||
password in a database, instead of the password itself. See also
|
||||
The well-known example for the hashing is storing the MD5 hash of a
|
||||
password in a database, instead of the password itself. See also
|
||||
<function>crypt</function> and <function>md5</function>.
|
||||
</simpara>
|
||||
<example>
|
||||
|
@ -621,7 +614,7 @@ $result = pg_exec($connection, $query);
|
|||
|
||||
if (pg_numrows($result) > 0) {
|
||||
echo "Wellcome, $username!";
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo "Authentication failed for $username.";
|
||||
}
|
||||
|
@ -633,7 +626,7 @@ else {
|
|||
<sect2 id="security.database.sql-injection">
|
||||
<title>SQL Injection</title>
|
||||
<simpara>
|
||||
Many web applications are unaware of how SQL queries can be tampered with,
|
||||
Many web developers are unaware of how SQL queries can be tampered with,
|
||||
and assume that an SQL query is a trusted command. It means that SQL
|
||||
queries are able to circumvent access controls, thereby bypassing standard
|
||||
authentication and authorization checks, and sometimes SQL queries even
|
||||
|
@ -655,7 +648,10 @@ else {
|
|||
behalf of a superuser or the owner who can create users, the attacker
|
||||
may create a superuser in your database.
|
||||
<example>
|
||||
<title>Splitting the result set into pages - and making superusers</title>
|
||||
<title>
|
||||
Splitting the result set into pages ... and making superusers
|
||||
(PostgreSQL and MySQL)
|
||||
</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$offset = argv[0]; // beware, no input validation!
|
||||
|
@ -664,11 +660,11 @@ $result = pg_exec($conn, $query);
|
|||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
Normal users click on the 'next', 'prev' links where the offset is
|
||||
appended to the URL. The script expects that the incoming
|
||||
<varname>$offset</varname> is numeric. However, if someone tries to
|
||||
Normal users click on the 'next', 'prev' links where the <varname>$offset</varname>
|
||||
is encoded into the URL. The script expects that the incoming
|
||||
<varname>$offset</varname> is decimal number. However, someone tries to
|
||||
break in with appending <function>urlencode</function>'d form of the
|
||||
following to the URL:
|
||||
following to the URL (PostgreSQL):
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
|
@ -679,7 +675,7 @@ insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
|
|||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
or
|
||||
or more precisely:
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
|
@ -691,9 +687,19 @@ insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
|
|||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
then the script will present a superuser access to him. Note that
|
||||
<literal>0;</literal> is to supply a valid offset to the original
|
||||
query and to terminate it.
|
||||
or in case of using MySQL:
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
0;
|
||||
UPDATE user SET Password=PASSWORD('crack') WHERE user='root';
|
||||
FLUSH PRIVILEGES;
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
If it happened, then the script would present a superuser access to him.
|
||||
Note that <literal>0;</literal> is to supply a valid offset to the
|
||||
original query and to terminate it.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
|
@ -705,7 +711,9 @@ insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
|
|||
<para>
|
||||
A feasible way to gain passwords:
|
||||
<example>
|
||||
<title>Listing out articles - and some passwords</title>
|
||||
<title>
|
||||
Listing out articles ... and some passwords (any database server)
|
||||
</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "SELECT id, name, inserted, size FROM products WHERE size = '$size';";
|
||||
|
@ -725,9 +733,11 @@ union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from use
|
|||
<literal>'</literal>), the query beast awakened.
|
||||
</para>
|
||||
<para>
|
||||
SQL updates are also subject to attacking your database.
|
||||
SQL UPDATEs are also subject to attacking your database.
|
||||
<example>
|
||||
<title>From resetting a password to gaining more privileges</title>
|
||||
<title>
|
||||
From resetting a password ... to gaining more privileges (any database server)
|
||||
</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
|
||||
|
@ -760,7 +770,7 @@ $query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE ...;
|
|||
A frightening example how operating system level commands can be accessed
|
||||
on some database hosts.
|
||||
<example>
|
||||
<title>Attacking the database host's operating system</title>
|
||||
<title>Attacking the database host's operating system (MSSQL Server)</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
|
||||
|
@ -769,12 +779,12 @@ $result = mssql_query($query);
|
|||
</programlisting>
|
||||
</example>
|
||||
If attacker submits the value
|
||||
<literal>%' exec master..xp_cmdshell 'net user test testpass /ADD' --</literal>
|
||||
<literal>a%' exec master..xp_cmdshell 'net user test testpass /ADD' --</literal>
|
||||
to <varname>$prod</varname>, then the <varname>$query</varname> will be:
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
$query = "SELECT * FROM products WHERE id LIKE '%%' exec master..xp_cmdshell 'net user test testpass /ADD'--";
|
||||
$query = "SELECT * FROM products WHERE id LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--";
|
||||
$result = mssql_query($query);
|
||||
]]>
|
||||
</programlisting>
|
||||
|
@ -785,6 +795,13 @@ $result = mssql_query($query);
|
|||
running with sufficient privileges, the attacker would now have an
|
||||
account with which to access this machine.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Some of the examples above is tied to a specific database server. This
|
||||
does not mean that a similar attack is impossible against other products.
|
||||
Your database server may be so vulnerable in other manner.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<sect3 id="security.database.avoiding">
|
||||
<title>Avoiding techniques</title>
|
||||
|
@ -806,26 +823,26 @@ $result = mssql_query($query);
|
|||
</simpara>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
First, check if the given input has the expected data type. PHP has
|
||||
a wide range of input validating functions, from the simplest ones
|
||||
found in <link linkend="ref.variables">Variable Functions</link> and
|
||||
in <link linkend="ref.ctype">Character Type Functions</link>
|
||||
sections, (e.g. <function>is_numeric</function>,
|
||||
<function>ctype_digit</function> respectively) onwards the
|
||||
<link linkend="ref.pcre">Perl compatible Regular Expressions</link>
|
||||
support.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
If the application waits for numeric input, consider to verify data
|
||||
with <function>is_numeric</function>, or silently change its type
|
||||
using <function>settype</function> or <function>sprintf()</function>.
|
||||
<example>
|
||||
<title>A more secure way to compose a query for paging</title>
|
||||
<programlisting role="php">
|
||||
<listitem>
|
||||
<simpara>
|
||||
First, check if the given input has the expected data type. PHP has
|
||||
a wide range of input validating functions, from the simplest ones
|
||||
found in <link linkend="ref.variables">Variable Functions</link> and
|
||||
in <link linkend="ref.ctype">Character Type Functions</link>
|
||||
sections, (e.g. <function>is_numeric</function>,
|
||||
<function>ctype_digit</function> respectively) onwards the
|
||||
<link linkend="ref.pcre">Perl compatible Regular Expressions</link>
|
||||
support.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
If the application waits for numeric input, consider to verify data
|
||||
with <function>is_numeric</function>, or silently change its type
|
||||
using <function>settype</function> or <function>sprintf()</function>.
|
||||
<example>
|
||||
<title>A more secure way to compose a query for paging</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
settype($order, 'integer');
|
||||
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
|
||||
|
@ -833,43 +850,43 @@ $query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"
|
|||
// please note %d in the format string, using %s would be meaningless
|
||||
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;", $offset);
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Quote user input which is passed to the database with
|
||||
<function>addslashes</function> or <function>addcslashes</function>.
|
||||
See <link linkend="security.database.storage">this example</link>.
|
||||
As the examples shows, quotes burnt into the static part of the query
|
||||
is not enough, and can be easily hacked.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Do not print out any database specific information, especially
|
||||
about the schema, no matter what happens. See also <link
|
||||
linkend="security.errors">Error Reporting</link> and <link
|
||||
linkend="ref.errorfunc">Error Handling and Logging Functions</link>.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
You may use stored procedures and previously defined cursors to abstract
|
||||
data access so that users do not directly access tables or views, but
|
||||
this solution has another impacts.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Quote user input which is passed to the database with
|
||||
<function>addslashes</function> or <function>addcslashes</function>.
|
||||
See <link linkend="security.database.storage">this example</link>.
|
||||
As the examples shows, quotes burnt into the static part of the query
|
||||
is not enough, and can be easily hacked.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Do not print out any database specific information, especially
|
||||
about the schema, no matter what happens. See also <link
|
||||
linkend="security.errors">Error Reporting</link> and <link
|
||||
linkend="ref.errorfunc">Error Handling and Logging Functions</link>.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
You may use stored procedures and previously defined cursors to abstract
|
||||
data access so that users do not directly access tables or views, but
|
||||
this solution has another impacts.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<simpara>
|
||||
Besides these, you benefit from logging queries either within your script
|
||||
or by the database itself, if it supports. Obviously, the logging is unable
|
||||
to prevent any harmful attempt, but it can be helpful to trace back which
|
||||
application has been circumvented. The log is not useful by itself, but
|
||||
through the information it contains. The more detail is generally better.
|
||||
</simpara>
|
||||
<simpara>
|
||||
Besides these, you benefit from logging queries either within your script
|
||||
or by the database itself, if it supports. Obviously, the logging is unable
|
||||
to prevent any harmful attempt, but it can be helpful to trace back which
|
||||
application has been circumvented. The log is not useful by itself, but
|
||||
through the information it contains. The more detail is generally better.
|
||||
</simpara>
|
||||
</sect3>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
@ -898,7 +915,7 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
</form>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
The PHP errors which are normally returned can be quite helpful to a
|
||||
|
@ -906,10 +923,10 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
as the function or file that failed, the PHP file it failed in,
|
||||
and the line number which the failure occured in. This is all
|
||||
information that can be exploited. It is not uncommon for a php
|
||||
developer to use <function>show_source</function>,
|
||||
<function>highlight_string</function>, or
|
||||
<function>highlight_file</function> as a debugging measure, but in
|
||||
a live site, this can expose hidden variables, unchecked syntax,
|
||||
developer to use <function>show_source</function>,
|
||||
<function>highlight_string</function>, or
|
||||
<function>highlight_file</function> as a debugging measure, but in
|
||||
a live site, this can expose hidden variables, unchecked syntax,
|
||||
and other dangerous information. Especially dangerous is running
|
||||
code from known sources with built-in debugging handlers, or using
|
||||
common debugging techniques. If the attacker can determine what
|
||||
|
@ -926,7 +943,7 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
</form>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
Regardless of the method of error handling, the ability to probe a
|
||||
|
@ -980,7 +997,7 @@ $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %
|
|||
<![CDATA[
|
||||
<?php
|
||||
if ($username) { // Not initialized or checked before usage
|
||||
$good_login = 1;
|
||||
$good_login = 1;
|
||||
}
|
||||
if ($good_login == 1) { // If above test fails, not initialized or checked before usage
|
||||
fpassthru ("/highly/sensitive/data/index.html");
|
||||
|
@ -995,9 +1012,9 @@ if ($good_login == 1) { // If above test fails, not initialized or checked befor
|
|||
<sect1 id="security.registerglobals">
|
||||
<title>Using Register Globals</title>
|
||||
<para>
|
||||
One feature of PHP that can be used to enhance security is configuring PHP with
|
||||
<link linkend="ini.register-globals">register_globals</link> = off.
|
||||
By turning off the ability for any user-submitted variable to be injected
|
||||
One feature of PHP that can be used to enhance security is configuring PHP with
|
||||
<link linkend="ini.register-globals">register_globals</link> = off.
|
||||
By turning off the ability for any user-submitted variable to be injected
|
||||
into PHP code, you can reduce the amount of variable
|
||||
poisoning a potential attacker may inflict. They will have
|
||||
to take the additional time to forge submissions, and your
|
||||
|
@ -1014,7 +1031,7 @@ if ($good_login == 1) { // If above test fails, not initialized or checked befor
|
|||
<![CDATA[
|
||||
<?php
|
||||
if ($username) { // can be forged by a user in get/post/cookies
|
||||
$good_login = 1;
|
||||
$good_login = 1;
|
||||
}
|
||||
|
||||
if ($good_login == 1) { // can be forged by a user in get/post/cookies,
|
||||
|
@ -1029,7 +1046,7 @@ if ($good_login == 1) { // can be forged by a user in get/post/cookies,
|
|||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
if($HTTP_COOKIE_VARS['username']){
|
||||
if($HTTP_COOKIE_VARS['username']){
|
||||
// can only come from a cookie, forged or otherwise
|
||||
$good_login = 1;
|
||||
fpassthru ("/highly/sensitive/data/index.html");
|
||||
|
@ -1052,7 +1069,7 @@ if($HTTP_COOKIE_VARS['username']){
|
|||
<?php
|
||||
if ($HTTP_COOKIE_VARS['username'] &&
|
||||
!$HTTP_POST_VARS['username'] &&
|
||||
!$HTTP_GET_VARS['username'] ) {
|
||||
!$HTTP_GET_VARS['username'] ) {
|
||||
// Perform other checks to validate the user name...
|
||||
$good_login = 1;
|
||||
fpassthru ("/highly/sensitive/data/index.html");
|
||||
|
@ -1071,7 +1088,7 @@ if ($HTTP_COOKIE_VARS['username'] &&
|
|||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
|
||||
<sect1 id="security.variables">
|
||||
<title>User Submitted Data</title>
|
||||
<para>
|
||||
|
@ -1124,7 +1141,7 @@ exec ($evil_var);
|
|||
Can this be used in conjunction with other scripts in a negative
|
||||
manner?
|
||||
</simpara>
|
||||
</listitem>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Will any transactions be adequately logged?
|
||||
|
@ -1147,7 +1164,7 @@ exec ($evil_var);
|
|||
operated upon).
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="security.hiding">
|
||||
<title>Hiding PHP</title>
|
||||
<para>
|
||||
|
@ -1162,7 +1179,7 @@ exec ($evil_var);
|
|||
</para>
|
||||
<para>
|
||||
Another tactic is to configure web servers such as apache to
|
||||
parse different filetypes through PHP, either with an .htaccess
|
||||
parse different filetypes through PHP, either with an .htaccess
|
||||
directive, or in the apache configuration file itself. You can
|
||||
then use misleading file extensions:
|
||||
<example>
|
||||
|
@ -1200,7 +1217,7 @@ AddType application/x-httpd-php .htm .html
|
|||
obscurity, it's a minor preventative measure with few drawbacks.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="security.current">
|
||||
<title>Keeping Current</title>
|
||||
<simpara>
|
||||
|
|
Loading…
Reference in a new issue