Changelog:
September 21, 2010 - changed one more $wb->add_slashes()
August 25, 2010 – changed many $wb->add_slashes() to $wb->strip_slashes() – makes much more sense.
April 19, 2010 – Extended example for strip-tags().
April 14, 2010 - $wb->add_slashes() added to most examples.
April 07, 2010 - Inserted ENT_QUOTES (which I forgot) into example htmlspecialchars().
April 05, 2010 – Extended comment in example preg_quote.
April 05, 2010 - Completed
Hello,
third part:
Treatement of GET/POST-data.
Usage of GET- or POST-data with out any means of precaution represents the main gateway for a series of hazards especially XSS and SQL-injjection. Therefor usage of values from the GET- or POST-array requires special precaution.
Insertion: $_REQUEST must never be used, since usage of $_REQUEST – depending on server configuration – includes the risk that an aggressor “overwrites” a $_POST value with a foisted $_GET value or vice versa. Examples for risks resulting from „uncontrolled“ usage of $_GET or $_POST:
$id = $_GET['user_id'];
$query_user = $database->query("SELECT permissions FROM table WHERE user_id='$id'");
If magic_quotes_gpc is deactivated on server
http://...php?user_id=-10' OR name='Admin'; --
results in
SELECT permissions FROM table WHERE user_id='-10' OR name='Admin'; --'
If magic_quotes_gpc is activated this hack is no longer working
SELECT permissions FROM table WHERE user_id='-10\' OR name=\'Admin\'; --'
(Insertion:This example is really nonsense! People using coding like this in frontend should immediately return their computer!)
But even magic_quotes_gpc does not protect against XSS attacks:
$class = $_GET['class'];
echo "<p class=\"".$class."\">".$text."</p>";
With activated magic_quotes_gpc
http://....php?class="><script>alert(String.fromCharCode(39)%2BString.fromCharCode(33)%2BString.fromCharCode(39));</script>
results in
<p class="\"><script>alert(String.fromCharCode(39)+String.fromCharCode(33)+String.fromCharCode(39));</script>">TEXT</p>
Functions for to be used with mySQL queriesThe following methods are available in class wb as well as in class admin.
In backend they are called via
$admin->, in frontend via
$wb->$wb->add_slashes($string) – Masks certein characters in $string, i.e. adds a \ in front of the character(s) if magic_quotes_gpc
deactivated on the server. If magic_quotes_gpc is activated, PHP will perform this masking by itself.
The following characters will be masked:
' " \ \x00 (zero-byte)
This function serves to obtain correctly masked strings for all strings from
$_GET or
$_POST regardless of the server configuration.
As seen above, this masking is only important for database operations. For HTML output see htmlspecialchars()/strip_slashes().Input: http://...php?name=o'Reilly<?php
$name = $_GET['name']; // possibly "o'Reilly" oder "o\'Reilly"
$name = addslashes($_GET['name']); // ERROR: submits "o\'Reilly" or "o\\\'Reilly"
$name = $wb->add_slashes($_GET['name']); // CORRECT: in any case "o\'Reilly"
$wb->strip_slashes($string) - Removes (leading) \ from $string,
if magic_quotes_gpc is activated on server.
This function enables to keep the original string for all
$_GET or
$_POST strings regardless of the server configuration.
Input: http://...php?name=o'Reilly \text<?php
$name = $_GET['name']; // possibl< "o'Reilly \text" or "o\'Reilly \\text"
$name = stripslashes($_GET['name']); // ERROR: submits "o'Reilly text" or "o'Reilly \text"
$name = $wb->stip-slashes($_GET['name']); // CORRECT: in any case "o'Reilly \text"
$wb->get_post_escaped($field) – corresponds to
$wb->add_slashes($_POST[$field])Other important functions of PHP:addslashes($string) - masks $string.
addslashes() is commonly used to mask values to be used in database queries:
<?php
$name = $wb->strip_slashes($_GET['name']); // creates original string
echo "The name is: ".htmlspecialchars($name, ENT_QUOTES);
$name = addslashes($name); // maskieren
$query = $database->query("SELECT * FROM table WHERE name='$name'");
Usage of addslashes() for this purpose has gained a bad name, however, since an exploit became known.
This exploit requires mySQLs default-charset to be set to Simplified Chinese, but nevertheless one should use mysql_real_escape_string() instead.mysql_real_escape_s tring($string) – masks certain characters in $string for usage in mySQL-Query. It requires an open connection to mySQL.
This function is supposed to be more secure than addslashes(), since it masks more characters (\x00, \n, \r, \, ', " und \x1a) than addslashes() and it is, in contrast to addslashes(), not vulnerable for multy-byte-character-exploit.
The function is used in the same way as addslashes():
<?php
$name = $wb->strip_slashes($_GET['name']); // create original string
echo "Der Name ist: ".htmlspecialchars($name, ENT_QUOTES);
$name = mysql_real_escape_string($name); // masking
$query = $database->query("SELECT * FROM table WHERE name='$name'");
is_numeric($string), intval($string), casting, ...A series of functions by means of which values can be checked for their data type or they can be converted into a defined data type.
<?php
// $user_id must be integer:
if(is_numeric($_GET['user_id'])) {
$user_id = $_GET['user_id'];
} else {
$user_id = 0;
}
$query = $database->query("SELECT * FROM table WHERE id=$user_id");
Short version:
<?php
// $user_id must be integer:
$user_id = intval($_GET['user_id']);
$query = $database->query("SELECT * FROM table WHERE id=$user_id");
| Function | Result |
| is_numeric("10") | TRUE |
| is_numeric(" 10 ") | FALSE |
| is_numeric("10 text") | FALSE |
| is_numeric("text 10") | FALSE |
| is_numeric("") | FALSE |
| intval("10") | 10 |
| intval(" 10 ") | 10 |
| intval("10 text") | 10 |
| intval("text 10") | 0 |
| intval("") | 0 |
Here you can see why the value 0 for ID’s in a database must never be used.
addcslashes($string, $charlist) – masks all characters listed in $charlist within a $string.
A very rarely used function which, however, is very useful for a certain situation: for SQL-Queries using LIKE.
The following query is supposed to create a list of all persons, the name of which starts with $name:
<?php
$name = mysql_real_escape_string($wb->strip_slashes($_GET['name']));
$query = $database->query("SELECT * FROM table WHERE name LIKE '".$name."%');
If the field name is indexed, this query is sufficiently performant.
An aggressor could now start a DOS-attack (Denial of Service) by sending a big number of search requests in the form
http://...php?name=%_a to the server. This would create:
SELECT * FROM table WHERE name LIKE '%_a%'
(Select all names which start with any character, followed by any character, followed ba an a and then end in any form). This would result in a terrible table scan orgy.
How to avoid this:
<?php
$name = mysql_real_escape_string($wb->strip_slashes($_GET['name']));
$name = addcslashes($name, '_%'); // mask % and _
$query = $database->query("SELECT * FROM table WHERE name LIKE '".$name."%');
This creates
SELECT * FROM table WHERE name LIKE '\%\_a%'
(Select all names starting with %, followed by _, followed by an a and then end in any form). The atttack is prevented.
Functions for usage with HTML-outputhtmlspecialchars($string, ENT_QUOTES) – converts all & < > ' " into HTML-Entities (&, <, ...).
<?php
$name = $wb->strip_slashes($_GET['name']);
$name = htmlspecialchars($name, ENT_QUOTES);
echo "Name: <strong>$name</strong>";
Input: Hans<script>alert('Hallo!');</script>Output: Hans<script>alert('Hallo!');</script>Not nice but safe!
strip_tags($string, $allowed_tags) – removes all HTML-Tags from $string. Tags listed in $allowed_tags will not be removed.
Code:
<?php
$name = $wb->strip_slashes($_GET['name']);
$name = strip_tags($name);
echo "Name: <strong>$name</strong>";
Input: Hans<script>alert('Hallo!');</script>Output: Hansalert('Hallo!');Also not nice but safe.
Usage of
$allowed_tags, however, is not recommended:
<?php
$name = $wb->strip_slashes($_GET['name']);
$name = strip_tags($name, "<b><strong><i>");
echo "Name: <strong>$name</strong>";
Input: Hans <b onmouseover="alert('Hello!')">Hans</b> Mustermann<script>alert('Hallo!');</script>Output: Hans <b onmouseover="alert('Hello!')">Hans</b> Mustermannalert('Hallo!');Generally strip_tags() removes everything between < and the next > (or up to the end of the string):
Code:
<?php
echo strip_tags($wb->strip_slashes($_GET['name']);
Input: This is still valid 1<2. Anything else would be a desaster!Output: This is still valid 1
Functions to be used in linksurlencode($string) - recodes $string to be usable in an URL.
Certain characters (like / ? &) have to be coded in an URL so they are not interpreted as „control characters“. This function performs the recoding.
Example: The string "R&B" is to be submitted as search value via URL:
http://www.example.org/wb/search/index.php?search=R&B
will not work properly since & will be interpreted as „control character“ (& marks the beginning of a new value). Instead of
search="R&B" this will create
search="R" and
B="".
This is the correct way:
<?php
$search = urlencode("R&B"); // creates "R%26B"
echo "http://www.example.org/wb/search/index.php?search=".$search;
Output:
http://www.example.org/wb/search/index.php?search=R%26B
Please note that this value will be decoded
automatically in the target site! Calling urldecode() is not requred.
<?php
$search = $wb->strip_slashes($_GET('search'));
echo $search; // Output: R&B
In order to transmit several values, use the individual values by &. & by itself would also be sufficient, it, however, implements the risk of creating HTML-entities:
<?php
echo '<a href="http://www.example.org/pages/page.php?row=4©=1">link</a>';
creates:
http://www.example.org/page/page.php?row=4©=1
In case it is sure that the value consist of a number only, urldecode()might be left off.
Complete example:
<?php
$link = WB_URL.'/modules/mod/file.php';
$url_query = '?';
$url_query .= 'page_id='.$page_id;
$url_query .= '&';
$url_query .= 'name='.urlencode($name);
echo '<a href="'.$link.$url_query.'">link</a>';
or more compact:
<?php
echo '<a href="'.WB_URL.'/modules/mod/file.php?page_id='.$page_id.'&name='.urlencode($name).'">link</a>';
Other functionspreg_quote($string, $limiter) – masks special characters in $string to be used in a regular expression. $limiter is the character to be used as limiter. It will also be masked.
In case a user’s entry or any unknown string is to be used in a regular expression, certain characters (like * and ?) have to be masked.
<?php
$str = $wb->strip_slashes($_POST['suchwort']);
$str = preg_quote($str, '~'); // masks all special character plus ~, which is used as limiter in the next line.
if(preg_match('~\b'.$str.'~i', $text)) {
// Hit
}
Otherwise an error might occur (e.g. searchword ="V8("), or it could even be used for a DOS-attack.
See also: Filter-Extension which may be used since PHP 5.2.
thorn.