Phpworks Security
Phpworks Security
Security
By: Ilia Alshanetsky
What is Security?
Security is a measurement, not a characteristic.
It’s is also an growing problem that requires an
continually evolving solution.
A good measure of secure application is it’s ability to
predict and prevent future security problems, before
someone devises an exploit.
As far as application design goes, security must
be considered at all times; initial spec,
implementation, testing and even maintenance.
Security 2
PHP & Security
PHP keeps on growing as a language, making
headway into enterprise and corporate markets.
Security 3
Input Validation
One of the key concepts you must accept is that
user input is unreliable and not to be trusted.
Partially lost in transmission between server & client.
Corrupted by some in-between process.
Modified by the user in an unexpected manner.
Intentional attempt to gain unauthorized access or to crash
the application.
Which is why it is absolutely essential to validate
any user input before use.
Security 4
Accessing Input Data
As of PHP 4.1, there are a series of super-globals that
offer very simple access to the input data.
$_GET – data from get requests.
$_POST – post request data.
$_COOKIE – cookie information.
$_FILES – uploaded file data.
$_SERVER – server data
$_ENV – environment variables
$_REQUEST – combination of GET/POST/COOKIE
Security 5
Register Globals
Arguably the most common source of
vulnerabilities in PHP applications.
Any input parameters are translated to variables.
?foo=bar >> $foo = “bar”;
No way to determine the input source.
Prioritized sources like cookies can overwrite GET values.
Un-initialized variables can be “injected” via user
inputs.
Security 6
Register Globals
if (authenticated_user()) {
$authorized = true;
}
if ($authorized) {
include '/highly/sensitive/data.php';
}
Because $authorized is left un-initialized if user
authentication fails, an attacker could access privileged
data by simply passing the value via GET.
http://example.com/script.php?authorized=1
Security 7
Solutions To Register Globals
Disable register_globals in PHP.ini.
Already done by default as of PHP 4.2.0
Code with error_reporting set to E_ALL.
Allows you to see warnings about the use of
un-initialized variables.
Type sensitive validation conditions.
Because input is always a string, type sensitive
compare to a Boolean or an integer will always fail.
if ($authorized === TRUE) {
Security 8
Hidden Register Globals Problems
$var[] = “123”;
foreach ($var as $entry) {
make_admin($entry);
}
script.php?var[]=1&var[]=2
Security 9
$_REQUEST
The $_REQUEST super-global merges data from
different input methods, like register_globals it
is vulnerable to value collisions.
echo $_GET['id']; // 1
echo $_COOKIE['id']; // 2
echo $_REQUEST['id']; // 2
Security 10
$_SERVER
Even though the $_SERVER super-global is
populated based on data supplied by the web-
server it should not be trusted.
User may inject data via headers
Host: <script> ...
Some parameters contain data based on user input
REQUEST_URI, PATH_INFO, QUERY_STRING
Can be fakes
Spoofed IP address via the use of anonymous proxies.
Security 11
Numeric Value Validation
All data passed to PHP (GET/POST/COOKIE) ends
up being a string. Using strings where integers are
needed is not only inefficient but also dangerous.
// integer validation
if (!empty($_GET['id'])) { Casting is a simple and
$id = (int) $_GET['id'];
very efficient way to
} else
$id = 0; ensure variables do in
// floating point number validation fact contain numeric
if (!empty($_GET['price'])) {
$price = (float) $_GET['price'];
values.
} else
$price = 0;
Security 12
Validating Strings
PHP comes with a ctype, extension that offers a very
quick mechanism for validating string content.
if (!ctype_alnum($_GET['login'])) {
echo "Only A-Za-z0-9 are allowed.";
}
if (!ctype_alpha($_GET['captcha'])) {
echo "Only A-Za-z are allowed.";
}
if (!ctype_xdigit($_GET['color'])) {
echo "Only hexadecimal values are allowed";
}
Security 13
Path Validation
Values passed to PHP applications are often used to
specify what file to open. This too needs to be validated
to prevent arbitrary file access.
http://example.com/script.php?path=../../etc/passwd
<?php
$fp = fopen(“/home/dir/{$_GET[‘path’]}”, “r”);
?>
Security 14
Path Validation
PHP includes a basename() function that will
process a path and remove everything other then the
last component of the path, usually a file name.
<?php
$_GET[‘path’] = basename($_GET[‘path’]);
Security 15
Better Path Validation
An even better solution would hide file names from the
user all together and work with a white-list of
acceptable values.
// make white-list of templates
$tmpl = array();
foreach(glob("templates/*.tmpl") as $v) {
$tmpl[md5($v)] = $v;
}
if (isset($tmpl[$_GET['path']]))
$fp = fopen($tmpl[$_GET['path']], "r");
http://example.com/script.php?path=57fb06d7...
Security 16
magic_quotes_gpc
PHP tries to protect you from attacks, by
automatically escaping all special characters
inside user input. ( ‘, “, \, \0 (NULL) )
Slows down input processing.
We can do better using casting for integers.
Requires 2x memory for each input element.
Security 17
Magic Quotes Normalization
if (get_magic_quotes_gpc()) { // check magic_quotes_gpc state
function strip_quotes(&$var) {
if (is_array($var)
array_walk($var, 'strip_quotes');
else
$var = stripslashes($var);
}
// Handle GPC
foreach (array('GET','POST','COOKIE') as $v)
if (!empty(${"_".$v}))
array_walk(${"_".$v}, 'strip_quotes');
Security 18
Exploiting Code in Previous Slide
While the code on the previous slide works, it
can be trivially exploited, due to its usage of
recursive functions!
<?php
$qry = str_repeat(“[]”, 1024);
$url = “http://site.com/script.php?a{$qry}=1”;
file_get_contents($url);
Password theft.
Security 21
Preventing XSS
Prevention of XSS is as simple as filtering input
data via one of the following:
htmlspecialchars()
Encodes ‘, “, <, >, &
htmlentities()
Convert anything that there is HTML entity for.
strip_tags()
Strips anything that resembles HTML tag.
Security 22
Preventing XSS
$str = strip_tags($_POST['message']);
// encode any foreign & special chars
$str = htmlentities($str);
// maintain new lines, by converting them to <br />
echo nl2br($str);
Security 23
Tag Allowance Problems
<b style="font-size: 500px">
TAKE UP ENTIRE SCREEN
</b>
Security 24
SQL Injection
SQL injection is similar to XSS, in the fact that
not validated data is being used. But in this case
this data is passed to the database.
Arbitrary query execution
Removal of data.
Modification of existing values.
Denial of service.
Security 25
SQL Escaping
If database interface extension offers dedicated
escaping functions, USE THEM!
MySQL
mysql_escape_string()
mysql_real_escape_string()
PostgreSQL
pg_escape_string()
pg_escape_bytea()
SQLite
sqlite_escape_string()
Security 26
SQL Escaping in Practice
// undo magic_quotes_gpc to avoid double escaping
if (get_magic_quotes_gpc()) {
$_GET['name'] = stripslashes($_GET['name'];
$_POST['binary'] = stripslashes($_GET['binary']);
}
$name = pg_escape_string($_GET['name']);
$binary = pg_escape_bytea($_POST['binary']);
Security 27
Escaping Shortfall
When un-quoted integers are passed to SQL queries,
escaping functions won’t save you, since there are no
special chars to escape.
http://example.com/db.php?id=0;DELETE%20FROM%20users
<?php
$id = sqlite_escape_string($_GET['id']);
// $id is still 0;DELETE FROM users
sqlite_query($db,
"SELECT * FROM users WHERE id={$id}");
// Bye Bye user data...
?>
Security 28
Prepared Statements
Prepared statements are a mechanism to secure and
optimize execution of repeated queries.
Works by making SQL “compile” the query and then
substitute in the changing values for each execution.
Increased performance, 1 compile vs 1 per query.
Better security, data is “type set” will never be evaluated as
separate query.
Supported by most database systems.
MySQL users will need to use version 4.1 or higher.
SQLite extension does not support this either.
Security 29
Prepared Statements
<?php
$data = "Here is some text to index";
Security 30
Error Reporting
By default PHP will print all errors to screen,
startling your users and in some cases disclosing
privileged information.
File paths.
Un-initialized variables.
Security 31
Solution?
This problem can be solved by disabling
displaying of error messages to screen
ini_set(“display_errors”, FALSE);
And enabling logging of errors
ini_set(“log_errors”, TRUE);
to a file
ini_set(“error_log”, “/var/log/php.log”);
or to system central error tracking facility
ini_set(“error_log”, “syslog”);
Security 32
File Security
Many PHP applications often require various
utility and configuration files to operate.
Security 35
Solution #1
If the configuration file only stores database connection
settings, you can set them via ini directives that will
then be loaded by httpd.conf via Include directive.
mysql.cnf httpd.conf
Security 37
Session Security
Sessions are a common tool for user tracking
across a web site.
Security 39
Session Validation
Another session security technique is to compare the
browser signature headers.
session_start();
$chk = @md5(
$_SERVER['HTTP_ACCEPT_CHARSET'] .
$_SERVER['HTTP_ACCEPT_ENCODING'] .
$_SERVER['HTTP_ACCEPT_LANGUAGE'] .
$_SERVER['HTTP_USER_AGENT']);
if (empty($_SESSION))
$_SESSION['key'] = $chk;
else if ($_SESSION['key'] != $chk)
session_destroy(); Security 40
Safer Session Storage
By default PHP sessions are stored as files inside the common /
tmp directory.
This often means any user on the system could see active
sessions and “acquire” them or even modify their content.
Solutions?
Separate session storage directory via
session.save_path
Database storage mechanism, mysql, pgsql, oci, sqlite.
Shared memory “mm” session storage.
Custom session handler allowing data storage anywhere.
Security 41
Shared Hosting
Most PHP applications run in shared
environments where all users “share” the same
web server instances.
This means that all files that are involved in
serving content must be accessible to the web
server (world readable).
Consequently it means that any user could read
the content of files of all other users.
Security 42
The PHP Solution
PHP’s solution to this problem are 2 INI
directives.
open_basedir – limits file access to one or more
specified directories.
Relatively Efficient.
Uncomplicated.
Security 43
Security Through Obscurity
While by itself is not a good approach to
security, as an addition to existing measures,
obscurity can be a powerful tool.
Disable PHP identification header
expose_php=off
Disable Apache identification header
ServerSignature=off
Avoid obvious names for restricted control panels.
Security 44
<?php include “/book/plug.inc”; ?>
Security 45
Questions
Security 46