provides software and services that enable enterprises
Live Chat 1-888-673-6564

Open Source Software Technical Articles

  • Home
  • Search
  • Contact Us
  • Products and Support
  • Services
  • Enterprise OSS Blog
  • Wazi Technical Blog
  • About Wazi
  • Attributions and Licensing
  • Supply Chain Compliance
  • How to Contribute
  • Contributors
  • Resources Library
  • Cloud Services
  • Partners
  • Customers
  • Community
  • Company
  • Careers
  • News and Events

Subscribe to Wazi by Email

Your email:


Enterprise Developer Support 24 x 7, Get a Support Quote Now!


click-here-to-chat-with-an-online-representative

download-oss-discovery

Latest Posts

  • Use Perl to enhance ModSecurity
  • The secret to great reporting with Drupal 7
  • A more colorful LibreOffice unveiled
  • Toward a more colorful LibreOffice
  • Flexible administration with Puppet's Facter and templates
  • Knock for OpenSSH
  • Get more out of phpMyAdmin
  • Image annotation in GIMP, Dia, and OpenOffice Draw
  • Solr, Drupal 7, and faceted search
  • Using FreeNAS' new full disk encryption for ZFS

Connect with Us!

Current Articles | RSS Feed RSS Feed

Tips for Writing Safe, Secure PHP Code

Posted by Gary Sims on Tue, May 01, 2012
  
Email This Email Article  
Tweet  
  

PHP has established itself as a cornerstone of web development, and powers popular platforms such as WordPress and Joomla. However, because today's Internet is rife with hackers searching for weaknesses in web applications' security, PHP programmers must code defensively and guard against potentially destructive errors.



Before embarking on a discussion on how to code with a security mindset, consider some of the common techniques hackers use to try and breach a website.



One of the most common forms of attack is SQL injection. Many websites rely on a database to store information for the site and for user authentication. An injection attack tries to modify SQL code that is sent to the database in order to manipulate the site or circumvent user authentication. It works through HTML forms, in which data is entered by users, or in this case by an attacker.



For example, a programmer might use the following PHP statement when trying to authenticate a user:




$auth = mysql_query("SELECT username, password FROM users WHERE username = '" . $_POST['username'] . "' and password = '" . md5($_POST['password']) . "'");


The danger here is that the input entered by the user is directly used in the SQL statement without any validation or checking.



If an attacker were to enter, for example, ' OR 1=1 # for the username, the SQL statement would be transformed into:




SELECT username, password FROM users WHERE username = '' OR 1=1 # and password = '286755fad04869ca523320acce0dc6a4';


Everything after the # is ignored, and 1=1 is always true, so the hacker would trick the code into thinking the user is authenticated.



Similar to SQL injection, cross-site scripting (XSS) attempts to inject JavaScript code into a web page and use that code to load more code from an unrelated site (hence the term cross-site). If he's successful, the hacker can run his own code in the victim's browser, which lets him launch more complex attacks and even infect the victim's computer with malware.



A simple example of XSS might target users when they register for a site. At that time users can enter information into form fields, including their name, which is often displayed on the user's profile page as simple HTML. Suppose a hacker tried to use the following code for a username:



<script>alert('Some JavaScript code')</script>


By entering the <script> tag, the hacker can make JavaScript run every time the page is loaded. Instead of showing something like:




<P>Username: John Smith</P>


the profile page would show:



<P>Username: <script>alert('Some JavaScript code')</script></P>


Replacing the call to alert() with code to download a complex JavaScript from another site (e.g. <script type="text/javascript" src="http://www.example.com/xss.js">) would allow the hacker to use a script on an external site that he could change as often as needed without needing to reregister or modify the profile on the site under attack.



Never Trust the User



SQL injection and cross-site scripting exploits show us that user input cannot be trusted. Any time you use a form to get information, you need to validate and verify the input. A convenient way to do this is to create a function to validate user input and call it for every piece of data from a web form. Suppose you have a form that sends the variable username as post data. You could call this function, which I'll call make_safe(), like this:




$username = make_safe($_POST["username"]);

19a98812-f823-48dc-841e-bf029c63c6d7

Protecting Against SQL Injection and Cross-site Scripting



PHP includes the mysql_real_escape_string() function, which makes a string safe by adding escaping so that it can be used by other MySQL-related functions without fear of SQL injections. By escaping, I mean adding a slash in front of any special characters. For example, a single quote (') would be converted to (\'). This tells MySQL that the single quote doesn't mark the end of a string but rather is part of the string. Escaping the leading single quote in the example above would foil the SQL injection attempt.



Using mysql_real_escape_string() in make_safe() gives us:




function make_safe($variable) {
$variable = mysql_real_escape_string(trim($variable));
return $variable;
}


To defend against cross-site scripting, input needs to be sanitized to remove any and all tags, including all HTML tags plus others such as <script>, <object>, and <embed>. PHP's strip_tags() can remove HTML tags, and we can use a string replace to remove the others:




function strip_html_tags( $text )
{
$text = preg_replace(
array(
// Remove invisible content
'@<head[^>]*?>.*?</head>@siu',
'@<style[^>]*?>.*?</style>@siu',
'@<script[^>]*?.*?</script>@siu',
'@<object[^>]*?.*?</object>@siu',
'@<embed[^>]*?.*?</embed>@siu',
'@<applet[^>]*?.*?</applet>@siu',
'@<noframes[^>]*?.*?</noframes>@siu',
'@<noscript[^>]*?.*?</noscript>@siu',
'@<noembed[^>]*?.*?</noembed>@siu'
),
array(
'', '', '', '', '', '', '', '', ''), $text );

return strip_tags( $text);
}


Adding this to make_safe() yields:




function make_safe($variable) {
$variable = strip_html_tags($variable);
$variable = mysql_real_escape_string(trim($variable));
return $variable;
}


As a further precaution, you should remove all special characters, such as / ' $ % and #, from the string:




function make_safe($variable) {
$variable = strip_html_tags($variable);
$bad = array("=","<", ">", "/","\"","`","~","'","$","%","#");
$variable = str_replace($bad, "", $variable);
$variable = mysql_real_escape_string(trim($variable));
return $variable;
}


URL Manipulation



Another way in which hackers attempt to gain access to restricted areas of a website is via URL manipulation. For example, a simple PHP script to show a record with the ID of 7 from a database might use a URL ending showrecord.php?id=7. It would be easy for a hacker to change this to showrecord.php?id=8.



To defend against this problem, you should take steps in several areas:




    • Check the owner of every record before displaying it. This means adding a userid (UID) to every record and comparing it to the current user's ID.

    • Use POST rather than GET to send the form data (i.e. <form action="action.php" method="post">). This prevents URL manipulation, as the data is sent in the HTTP headers and not in the URL.

    • Use URL rewriting to mask the variables used.



Password Strength



The most common way websites authenticate visitors is to have them enter a user name and password. Forcing users to enter a strong password is essential for website security. It's easy to check password criteria in PHP. The following code checks a password (in the variable $pw) to ensure that it is at least eight characters long and contains at least one number, one lower-case letter, and one upper-case letter:




if (preg_match("#.*^(?=.{8,20})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*$#", $pw))
// Password is strong
else
// Password is weak


Disable Dangerous Functions



PHP contains a variety of functions that can be dangerous, especially if passed unvalidated user-entered data. The most serious is the eval() function, which executes a given string as PHP. The PHP manual warns, "The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged.... Pay special attention not to pass any user provided data into it without properly validating it beforehand."



To disable eval(), and other potentially dangerous functions, add the following line to your system's php.ini file:




disable_functions = eval, ini_set, exec, shell_exec, system


Conclusion



When you're coding an enterprise application, you must consider all data entered by users via a web form to be potentially harmful. Before you process it, you must validated it and sanitize it. Using the methods outlined above to check for SQL injections and cross-site scripting will help secure your website. Disabling potentially harmful PHP functions like eval() will ensure that no easy-to-access system functions can creep into the code. Enforcing a good password policy will make it harder for script kiddies to gain access to legitimate user credentials. You should include all of these steps when you build sites with PHP.

Follow @openlogic
Follow @CloudSwing

This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.Follow @openlogic
Follow @OSCloudServices

This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.
Tags: PHP, Technical, Tips & Tricks, Joomla, WordPress, Programming

Comments

Nice article. 
THe important thing that i got from your article is "before you process it, you must validated it and sanitize it."
Posted @ Wednesday, September 26, 2012 11:13 PM by demby
Post Comment
Name
 *
Email
 *
Website (optional)
Comment
 *

Allowed tags: <a> link, <b> bold, <i> italics

Loading...
Error sending email
Email sent successfully

Email article
Email To : 
Your name : 
Message : (maximum 200 characters)
Home | Search | Contact Us | Products and Support | Services | Enterprise OSS Blog | Wazi Technical Blog | Resources Library | Cloud Services | Partners | Customers | Community | Company | Careers | News and Events
Products
OpenLogic Exchange (OLEX)
License Compliance Module
OSS Discovery
OSS Deep Discovery
OpenUpdate
Services
Open Source Support
CentOS Support
Scanning & Compliance
Open Source Training
Professional Services
Solutions
Support & Indemnification
Open Source Governance
Open Source Scanning
Open Source Provisioning
Consulting & Training
Contact Us
1-888-673-6564


© 2013 OpenLogic, Inc. All rights reserved.
Site Map  |  Privacy Policy