If your scripts need permission to write to files, make a directory outside the Web tree for this purpose.. In order to encrypt and decrypt data, you will need a program to encrypt data,
Trang 1FIGURE 15.4
SSL breaks up, compresses, hashes, and encrypts data before sending it.
One thing you might notice from the diagram is that the TCP header is added after the data is
encrypted This means that routing information could still potentially be tampered with, and
although snoopers cannot tell what information we are exchanging, they can see who is
exchanging it
The reason that SSL includes compression before encryption is that although most network
traffic can be (and often is) compressed before being transmitted across a network, encrypted
data does not compress well
Compression schemes rely on identifying repetition or patterns within data Trying to apply a
compression algorithm after data has been turned into an effectively random arrangement of
bits via encryption is usually pointless It would be unfortunate if SSL, which was designed to
increase network security, had the side effect of dramatically increasing network traffic
Although SSL is relatively complex, users and developers are shielded from most of what
occurs, as its external interfaces mimic existing protocols
In the relatively near future, SSL 3.0 is likely to be replaced by TLS 1.0 (Transport Layer
Security), but at the time of writing, TLS is a draft standard and not supported by any servers
or browsers TLS is intended to be a truly open standard, rather than a standard defined by one
organization but made available for others It is based directly on SSL 3.0, but contains
improvements intended to overcome weaknesses of SSL
15
Compress
Calculate MAC
Encrypt
Packetize
<html><head><title><My Page</title>…
Our data
d><title> M
<html><hea y Page</ti Data Packets
Compressed data
Message Authentication Code
Encrypted Packets
TCP Packets headerTCP
Trang 2Screening User Input
One of the principles of building a safe Web application is that you should never trust user input Always screen user data before putting it in a file or database or passing it through a sys-tem execution command
We’ve talked in several places throughout this book of techniques you can use to screen user input We’ll list these briefly here as a reference
• The addslashes()function should be used to filter user data before it is passed to a database This function will escape out characters which might be troublesome to a data-base You can use the stripslashes()function to return the data to its original form
• Magic quotes You can switch on the magic_quotes_gpcand magic_quotes_runtime directives in your php.ini file These directives will automatically add and strip slashes for you The magic_quotes_gpcwill apply this formatting to incoming GET, POST, and cookie variables, and the magic_quote_runtimewill apply it to data going to and from databases
• The escapeshellcmd()function should be used when you are passing user data to a system()or exec()call or to backticks This will escape out any metacharacters that can
be used to force your system to run arbitrary commands entered by a malicious user
• You can use the strip_tags()function to strip out HTML and PHP tags from a string This will avoid users planting malicious scripts in user data that you might echo back to the browser
• You can use the htmlspecialchars()function, which will convert characters to their HTML entity equivalents For example,<will be converted to < This will convert any script tags to harmless characters
Providing Secure Storage
The three different types of stored data (HTML or PHP files, script related data, and MySQL data) will often be stored in different areas of the same disk, but are shown separately in Figure 15.1 Each type of storage requires different precautions and will be examined separately The most dangerous type of data we store is executable content On a Web site, this usually means scripts You need to be very careful that your file permissions are set correctly within your Web hierarchy By this we mean the directory tree starting from htdocs on an Apache server or inetpub on an IIS server Others need to have permission to read your scripts in order
to see their output, but they should not be able to write over or edit them
The same proviso applies to directories within the Web hierarchy Only we should be able to write to these directories Other users, including the user who the Web server runs as, should
Trang 3not have permission to write or create new files in directories that can be loaded from the Web
server If you allow others to write files here, they could write a malicious script and execute it
by loading it through the Web server
If your scripts need permission to write to files, make a directory outside the Web tree for this
purpose This is particularly true for file upload scripts Scripts and the data that they write
should not mix
When writing sensitive data, you might be tempted to encrypt it first There is usually little
value in this approach though
We’ll put it this way: If you have a file called creditcardnumbers.txton your Web server
and a cracker obtains access to your server and can read it, what else can he read? In order to
encrypt and decrypt data, you will need a program to encrypt data, a program to decrypt data,
and one or more key files If the cracker can read your data, probably nothing is stopping him
from reading your key and other files
Encrypting data could be valuable on a Web server, but only if the software and key to decrypt
the data was not stored on the Web server, but only existed on another machine One way of
securely dealing with sensitive data would be to encrypt it on the server, and then transmit it to
another machine, perhaps via email
Database data is similar to data files If you set up MySQL correctly, only MySQL can write to
its data files This means that we need only worry about accesses from users within MySQL
We have already discussed MySQL’s own permission system, which assigns particular rights to
particular usernames at particular hosts
One thing that needs special mention is that you will often need to write a MySQL password
in a PHP script Your PHP scripts are generally publicly loadable This is not as much of a
dis-aster as it might seem at first Unless your Web server configuration is broken, your PHP
source will not be visible from outside
If your Web server is configured to parse files with the extension php using the PHP
inter-preter, outsiders will not be able to view the uninterpreted source However, you should be
careful when using other extensions If you place inc files in your Web directories, anybody
requesting them will receive the unparsed source You need to either place include files outside
the Web tree, configure your server not to deliver files with this extension, or use php as the
extension on these as well
If you are sharing a Web server with others, your MySQL password might be visible to other
users on the same machine who can also run scripts via the same Web server Depending on
how your system is set up, this might be unavoidable This can be avoided by having a Web
server set up to run scripts as individual users, or by having each user run her own instance of
15
Trang 4the Web server If you are not the administrator for your Web server (as is likely the case if you are sharing a server), it might be worth discussing this with your administrator and exploring security options
Why Are You Storing Credit Card Numbers?
Having discussed secure storage for sensitive data, one type of sensitive data deserves special mention Internet users are paranoid about their credit card numbers If you are going to store them, you need to be very careful You also need to ask yourself why you are doing it, and if it
is really necessary
What are you going to do with a card number? If you have a one-off transaction to process and real-time card processing, you will be better off accepting the card number from your customer and sending it straight to your transaction processing gateway without storing it at all
If you have periodic charges to make, such as the authority to charge a monthly fee to the same card for an ongoing subscription, this might not be an option In this case, you should think about storing the numbers somewhere other than the Web server
If you are going to store large numbers of your customers’ card details, make sure that you have a skilled and somewhat paranoid system administrator who has enough time to check up-to-date sources of security information for the operating system and other products you use
Using Encryption in PHP
A simple, but useful, task we can use to demonstrate encryption is sending encrypted email
The de facto standard for encrypted email has for many years been PGP, which stands for
Pretty Good Privacy Philip R Zimmermann wrote PGP specifically to add privacy to email Freeware versions of PGP are available, but you should note that this is not Free Software The freeware version can only legally be used for non-commercial use
If you are a U.S citizen in the United States, or a Canadian citizen in Canada, you can obtain the freeware version from
http://web.mit.edu/network/pgp.html
If you want to use PGP for commercial use and are in the United States or Canada, you can get
a commercial license from Network Associates See http://www.pgp.com
for details
Trang 5To obtain PGP for use outside the USA and Canada, see the list of international download sites
at the international PGP page:
http://www.pgpi.org
An Open Source alternative to PGP has recently become available GPG—Gnu Privacy
Guard—is a free (as in beer) and Free (as in speech) replacement for PGP It contains no
patented algorithms, and can be used commercially without restriction
The two products perform the same task in fairly similar ways If you intend to use the
com-mand line tools it might not matter, but PGP has other useful interfaces such as plug-ins for
popular email programs that will automatically decrypt email when it is received
GPG is available from
http://www.gnupg.org
You can use the two products together, creating an encrypted message using GPG for
some-body using PGP (as long as it is a recent version) to decrypt As it is the creation of messages
at the Web server we are interested in, we will provide an example here using GPG Using
PGP instead will not require many changes
As well as the usual requirements for examples in this book, you will need to have GPG
avail-able for this code to work GPG might already be installed on your system If it is not, do not
be concerned: The installation procedure is very straightforward, but the setup can be a bit
tricky
Installing GPG
To add GPG to our Linux machine, we downloaded the appropriate archive file from
To compile and install the program, use the same commands as for most Linux programs:
configure (or /configure depending on your system)
make
make install
If you are not the root user, you will need to run the configure script with the prefixoption
as follows:
./configure prefix=/path/to/your/directory
This is because a non-root user will not have access to the default directory for GPG
If all goes well, GPG will be compiled and the executable copied to /usr/local/bin/gpgor
the directory that you specified You can change many options See the GPG documentation for
details
15
Trang 6For a Windows server, the process is just as easy Download the zip file, unzip it and place gpg.exe somewhere in your PATH (C:\Windows\ or similar will be fine) Create a directory at C:\gnupg Open a command prompt and type gpg
You also need to install GPG or PGP and generate a key pair on the system that you plan to check mail from
On the Web server, there are very few differences between the command-line versions of GPG and PGP, so we might as well use GPG as it is free On the machine that you read mail from, you might prefer to buy a commercial version of PGP in order to have a nice graphical user interface plug-in to your mail reader
If you do not already have one, generate a key pair on your mail reading machine Recall that a key pair consists of a Public Key that other people (and your PHP script) use to encrypt mail before sending it to you, and a Private Key, which you use to either decrypt received messages
or sign outgoing mail
It is important that the key generation is done on your mail reading machine, rather than on your Web server, as your private key should not be stored on the Web server
If you are using the command-line version of GPG to generate your keys, enter the following command:
gpg gen-key You will be asked a number of questions Most of them have a default answer that can be accepted You will be asked for a name and email address, which will be used to name the key
My key is named ‘Luke Welling <luke@tangledweb.com.au>’ I am sure that you can see the pattern
To export the public key from your new key pair, you can use the command:
gpg export > filename
This will give you a binary file suitable for importing into the GPG or PGP keyring on another machine If you want to email this key to people, so they can import it into their key rings, you can instead create an ASCII version like this:
gpg export -a > filename
Having extracted the public key, you can upload the file to your account on the Web server You can do this with FTP
The following commands assume that you are using UNIX The steps are the same for Windows, but directory names and system commands will be different
Trang 7Log in to your account on the Web server and change the permissions on the file so that other
users will be able to read it Type
chmod 644 filename
You will need to create a keyring so that the user who your PHP scripts get executed as can
use GPG Which user this is depends on how your server is setup It is often the user
Change to being the Web server user You will need to have root access to the server to do this
On many systems, the Web server runs as nobody The following examples assume this (You
can change it to the appropriate user on your system.) If this is the case on your system, type
su root
su nobody
Create a directory for nobodyto store their key ring and other GPG configuration information
in This will need to be in nobody’s home directory
The home directory for each user is specified in /etc/passwd On many Linux systems,
many BSD systems, nobody’s home directory defaults to /nonexistent, which, as it doesn’t
exist, cannot be written to On our system, nobody has been assigned the home directory /tmp
You will need to make sure your Web server user has a home directory that they can write to
Type
cd ~
mkdir gnupg
The user nobodywill need a signing key of their own To create this, run this command again:
gpg gen-key
As your nobodyuser probably receives very little personal email, you can create a signing only
key for them This key’s only purpose is to allow us to trust the public key we extracted earlier
To import the pubic key we exported earlier, use the following:
gpg import filename
To tell GPG that we want to trust this key, we need to edit the key’s properties using
gpg edit-key ‘Luke Welling <luke@tangledweb.com.au>’
On this line, the text in quotes is the name of the key Obviously, the name of your key will not
and email address you provided when generating it
15
Trang 8Options within this program include help, which will describe the available commands— trust,sign, and save
Typetrustand tell GPG that you trust your key fully Type signto sign this public key using nobody’s private key Finally, type saveto exit this program, keeping your changes
Testing GPG
GPG should now be set up and ready to use
Creating a file containing some text and saving it as test.txt will allow us to test it
Typing the following command gpg -a recipient ‘Luke Welling <luke@tangledweb.com.au>’ encrypt test.txt (modified to use the name of your key) should give you the warning
gpg: Warning: using insecure memory!
and create a file named test.txt.asc If you open test.txt.ascyou should see an encrypted message like this:
-BEGIN PGP MESSAGE -Version: GnuPG v1.0.3 (GNU/Linux) Comment: For info see http://www.gnupg.org hQEOA0DU7hVGgdtnEAQAhr4HgR7xpIBsK9CiELQw85+k1QdQ+p/FzqL8tICrQ+B3 0GJTEehPUDErwqUw/uQLTds0r1oPSrIAZ7c6GVkh0YEVBj2MskT81IIBvdo95OyH K9PUCvg/rLxJ1kxe4Vp8QFET5E3FdII/ly8VP5gSTE7gAgm0SbFf3S91PqwMyTkD /2oJEvL6e3cP384s0i8lrBbDbOUAAhCjjXt2DX/uX9q6P18QW56UICUOn4DPaW1G /gnNZCkcVDgLcKfBjbkB/TCWWhpA7o7kX4CIcIh7KlIMHY4RKdnCWQf271oE+8i9 cJRSCMsFIoI6MMNRCQHY6p9bfxL2uE39IRJrQbe6xoEe0nkB0uTYxiL0TG+FrNrE tvBVMS0nsHu7HJey+oY4Z833pk5+MeVwYumJwlvHjdZxZmV6wz46GO2XGT17b28V wSBnWOoBHSZsPvkQXHTOq65EixP8y+YJvBN3z4pzdH0Xa+NpqbH7q3+xXmd30hDR +u7t6MxTLDbgC+NR
=gfQu -END PGP MESSAGE -You should be able to transfer this file to the system where you generated the key initially and run:
gpg -d test.txt.asc
to see your original text again
To place the text in a file, rather than output it to the screen, you can use the -oflag and spec-ify an output file like this:
gpg -do test.out test.txt.asc
Trang 9If you have GPG set up so that the user your PHP scripts run as can use it from the command
line, you are most of the way there If this is not working, see your system administrator or the
GPG documentation
Listings 15.1 and 15.2 enable people to send encrypted email by using PHP to call GPG
LISTING 15.1 private_mail.php—Our HTML Form to Send Encrypted Email
<html>
<body>
<h1>Send Me Private Mail</h1>
<?
// you might need to change this line, if you do not use
// the default ports, 80 for normal traffic and 443 for SSL
if($HTTP_SERVER_VARS[“SERVER_PORT”]!=443)
echo “<p><font color = red>
WARNING: you have not connected to this page using SSL.
Your message could be read by others.</font></p>”;
?>
<form method = post action = send_private_mail.php><br>
Your email address:<br>
<input type = text name = from size = 38><br>
Subject:<br>
<input type = text name = title size = 38><br>
Your message:<br>
<textarea name = body cols = 30 rows = 10>
</textarea><br>
<input type = submit value = “Send!”>
</form>
</body>
</html>
LISTING 15.2 send_private_mail.php—Our PHP Script to Call GPG and Send Encrypted
<?
$to_email = “luke@localhost”;
// Tell gpg where to find the key ring
// On this system, user nobody’s home directory is /tmp/
putenv(“GNUPGHOME=/tmp/.gnupg”);
15
Trang 10//create a unique file name
$infile = tempnam(“”, “pgp”);
$outfile = $infile.”.asc”;
//write the user’s text to the file
$fp = fopen($infile, “w”);
fwrite($fp, $body);
fclose($fp);
//set up our command
$command = “/usr/local/bin/gpg -a \\
recipient ‘Luke Welling <luke@tangledweb.com.au>’ \\ encrypt -o $outfile $infile”;
// execute our gpg command system($command, $result);
//delete the unencrypted temp file unlink($infile);
if($result==0) {
$fp = fopen($outfile, “r”);
if(!$fp||filesize ($outfile)==0) {
$result = -1;
} else { //read the encrypted file
$contents = fread ($fp, filesize ($outfile));
//delete the encrypted temp file unlink($outfile);
mail($to_email, $title, $contents, “From: $from\n”);
echo “<h1>Message Sent</h1>
<p>Your message was encrypted and sent.
<p>Thank you.”;
} } if($result!=0) {
echo “<h1>Error:</h1>
L ISTING 15.2 Continued