Showing posts with label PHP. Show all posts
Showing posts with label PHP. Show all posts

Friday, 14 September 2007

Use CAPTCHA to protect sites from abuse - PHP Approach




First thing first, lets take a look at CAPTCHA's physical appearance (a screenshot from my application) :


Ah... CAPTCHA is a program to tell whether the user is a human or a computer.

Secondly, CAPTCHA is very very secure as it uses two layers of protection when generating the image. It starts with images that can't be read by computers, and then distorts them even more as shown in the screenshot above. The OCR software read the image (screenshot above) as "ibataz Iueqm". :-)

-------------------------------------------------------------------------------------------------------
Now, Lets implement it by using PHP:

Step One: Display the image

require_once('recaptchalib.php');
$publickey = "xxxxxxxxxxxxxxxxxxxxxxxx";
$capImg = recaptcha_get_html($publickey);
echo $capImg; //Display the image

Step Two: Check if the user input is correct
The reason to use $_SESSION['Code'] is to stop checking it again if the last attempt was correct. For example, you need a user to specify a valid email address AND to get this image correct. But, he forgot to put his email ... So, he only need to tell you what his email address is on the next screen.
require_once('recaptchalib.php');
if ($_SESSION['Code'] != "yes") // user's last input was correct
{
$privatekey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$resp = recaptcha_check_answer ($privatekey,
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_POST["recaptcha_response_field"]);

if (!$resp->is_valid)
{
$_SESSION['Code'] = "no";
} else {
$_SESSION['Code'] = "yes";
}
}

Step Three: Display another image if the user's input was incorrect
if ($_SESSION['spamCode'] != "yes")
{
$Info = "Oops! You got it wrong, please try again ...";
$publickey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$capImg = recaptcha_get_html($publickey);
echo $capImg;
session_unregister('Code');
} else {
$Info = "Correct!";
}
echo $Info;

Wednesday, 12 September 2007

MySQL Transaction in PHP (Commit & Rollback)




We all know that an SQL query will either execute completely or not at all (i.e. they are atoms). But, sometimes, we want several queries to be bundled together as response to business logic. Transaction processing will help you to ensure this and maintain database integrity.

If you are new to MySQL transaction with PHP, then this article will definitely help. :-)

Step One - Make sure the type of your database table is innoDB not MyISAM.
(Here is a screenshot of from phpMyAdmin)

Step Two - Start transaction $dbh->query('BEGIN');
$dbh is an pearDB object ($dbh = new pearDB(), if you are not familiar with pearDB, please click here.)

Step Three - Specify your queries which reflect the business logic. ($sqlA and $sqlB)
Step Four - 'ROLLBACK' to cancel $sqlA and $sqlB, and 'COMMIT' to confirm the changes.

Code Example:

(Click the image to Enlarge)


If you have any question or suggestion, feel free contact me on twitter: http://twitter.com/alexzang

Tuesday, 11 September 2007

Smarty Templates - PHP Presentation Framework




Smarty templates can help to separate php coding from presentation. So, your code looks clean and tidy while the HTML templates are much easier to maintain. The beauty of it is that designers don't break your application code and you never messing with templates.

It is more like to put your php code on a layer beneath its presentation and keep a same logic.
Here is an example explaining how I use smarty:

Step One: Specify the smarty template file structure:
Create a folder named smarty under /home/www, and then create 4 sub-folders as named in the php file below. Make sure you change the file permission to 0777 on the templates_c folder.

/*zSmarty.php*/
<?
require_once('/usr/local/lib/php/Smarty/Smarty.class.php'); //Download it from smarty.org
class zSmarty extends Smarty {
public function __construct () {
$this->template_dir = '/home/www/smarty/templates';
$this->compile_dir = '/home/www/smarty/templates_c';
$this->cache_dir = '/home/www/smarty/cache';
$this->config_dir = '/home/www/smarty/configs';
}
}
?>

Step Two: PHP Code

<?
require_once ("zSmarty.php"); //include smarty template class
$ztpl = new zSmarty(); //create smarty template object
assign('name', "Alex"); //assign a value to {$name} which is on the
template
$ztpl->display('test.tpl'); //display the template
?>


Step Three: Template File (test.tpl)
Store test.tpl in /templates folder.

<html>
<head>
<title>testing</title>
</head>
<body>

Name: {$name}
</body>
</html>

Notes:
If you want to place javascript on your templates, please use {literal} tags. For example:

{literal}<script>... </script>{/literal}

Monday, 27 August 2007

PHP Basics (Section 5) - Object Oriented Programming




1. Prior to PHP5 OOP was a hack on top of the array implementation.
2. PHP5 changed eveything, in a great way.
3. Simple OO Example:

class
person
{
public $age;
public $name;
function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
function birthday()
{
echo "Happy Birthday " . $this->name . "!";
$this->age++;
}
}

4. Public - Method or property can be accessed externally.
5. Private - Method or property is private to that class and can not be accessed externally.
6. Protected - Method or property is private and can also be accessed by extending classes
7. Final - Method can be overridden by extending classes.
8. Extending Example:

class friend extends person
{
private $relationship;
const MYNAME = "paul";
function __construct($name, $age, $relationship)
{
parent::__construct($name, $age);
$this->relationship = $relationship;
}
function showStatus()
{
echo "{$this->name} is my {$this->relationship}";
}
function fight()
{
$this->relationship = "enemy";
}
static function phoneCall()
{
echo friend::MYNAME . " the phone is for you";
}


9. Autoloading Example:

function __autoload($class_name)
{
require_once "/www/phpClasses/
{$class_name}.inc.php";
}
$a = new friend;

10. Special Functions: __construct(), __destruct(), __toString(), __sleep() __wakeup(), __call(), __get(), __set()
11. Design Patterns - Some time ago people realized that we were solving the same problems again and again, they then decided to sit down and come up with really good solutions to those problems, they’re called design patterns.
12. The advantages of design patterns are two fold: first they present a well defined solution to common problems, second they provide a common language for developers.

Sunday, 26 August 2007

PHP Basics (Section 4) - Files



  1. Files provide a simple temporary to permanent data store.
  2. PHP5 presents two functions which make handling files, namely file_get_contents() and file_put_contents().
  3. For large amounts of data, or in issues where a race condition is possible a database would be a better data store.
  4. Steams are the way that PHP handles working with network resources.
  5. Whenever you open up a file PHP creates a stream in the background.
  6. Each stream consists of several components: file wrapper, one or two pipe-lines, an optional context, metadata about the stream.
  7. Files can be locked to prevent race conditions:
    flock($fp, LOCK_SH); //Place Shared lock
    flock($fp, LOCK_EX); //
    Place Exclusive (write) Lock
    flock($fp, LOCK_UN); //Release lock
  8. Placing and removing locks can inhibit performance as traffic increases, consider using a different data store.
  9. Using stream context and a few other techniques a lot can be done without resorting to sockets, however for more detailed control sockets can be used.
  10. Sockets allow read/write access to various socket connections, while things like HTTP may seem read only, at the protocol level information is being sent to identify the desired resource. Example:
    $fp = fsockopen
    ("example.preinheimer.com", 80, $errno, $errstr, 30)
    ;
    if (!$fp) {
    echo "$errstr ($errno)\n";
    } else {
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: example.preinheimer.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
    echo fgets($fp, 128);
    }
    fclose($fp);
    }
For more information, please read my another post Amazon S3 Makes My Document Management System Easier

Saturday, 25 August 2007

PHP Basics (Section 3) - Security




Defense in Depth

  1. When you plan with defense in depth, you plan for failure. Rather than internal functions assuming the data they receive is already validated or escaped, they will check and confirm.
  2. Application that demonstrate defense in depth are not noly more resistant to attack when they are developed, they also remain more resistant over time as new attacks are developed, and as more code is added to them.
Least Privilege
  1. Your PHP applications by default has a lot of power, they execute as the web user (often apache or www-data) with all the rights and privileges thereof.
  2. If an attacker gains control of PHP through an application vulnerability this can be used and abused.
Validation vs Escaping
  1. These terms are often confused, or used interchangeably.
  2. Validation or Filtering is the process by which you subject data to a series of rules, either it passes (validates) or does not.
  3. Escaping is the process by which you prepare data for a specific resource by "escaping" certain portions of the data to avoid confusion of instruction and data.
Validate Input
  1. Whenever you receive data one of three things can be said about it: 1) It is valid, the user entered the data you want, in the format you desire; 2) It is invalid because the user either did not comply or did not understand the rules on the data you requested (eg. Poorly formatted postcode); 3) It is invalid because the user is attempting to compromise your application.
  2. Data from the end user can not be trusted, it must be validated before it can be used.
  3. Validate data first don't save it for last.
  4. Fail early, tell the user what went wrong.
Whitelist vs Blacklist
  1. There are two major approaches to data validation, the whitelist and blacklist approach.
  2. Under the whitelist approach you select a series of valid characteristics (frequently characters) only data that follows these rules is accepted as valid.
  3. Under the blacklist approach you select a series of invalid characteristics, any data that contains these characteristics is considered invalid.
XSS
  1. Under a cross site scripting attack an attacker injects code into your page (forum post, shout box, etc) that contains code that re-writes the page to do something nefarious.
  2. This can be prevented through proper escaping and data validation techniques
CSRF
  1. Under a cross site request forgery attack a site exploits another sites persistent user trust relationship to make something happen.
  2. iFrames are another common tool leveraged in this technique.
Sessions
  1. Sessions provide safer state, it may not nesesarily be safe.
  2. Basically, sessions combine cookies containing a session ID with a local(ish) data store corresponding to that session id.
  3. If the session id is compromised, or the data store is not secure (/tmp on a shared machine) sessions are still vulnerable to attack.
  4. Session IDs are very random.
  5. Predicting them is hard, it’s much easier to: 1) Check out /tmp on a shared server, see what people have; 2)Intercept communications; 3)Implement session fixation.
  6. To defend, implement some browser fingerprinting.
For more information, please read my another post PHP Application Security Rules

Friday, 24 August 2007

PHP Basics (Section 2) - Functions & String



Function

  1. We use functions for several major reasons: readability, code separation, maintainability, modularity.
  2. In PHP4 objects were thrown around ByVal, this meant that you made copies without even thinking about it.
  3. In PHP5 objects are always passed BrRef unless you explicitly clone it, keep that in mind.
  4. Return statements can exist anywhere anywhere within the function, and you can even have multiple return values.
  5. Avoid situations where the same function may return nothing, or something.
String
  1. Strings are the most commonly used variable type in PHP, because they are both central to web development, and the common method of data transmission from the user
  2. Within strings many characters take a special meaning, matching quotes, back slashes, octal numbers, variables, if you wish to accept them as they are you mush escape them with the \ character.
  3. strcmp() - Compare two strings. Returns > 0 if $string_1 is greater than $string_2, and 0 if they are equal.
  4. strcasecrm() - Case insensitive version of strcmp()
  5. substr() - Used to retrieve a portion of a string
  6. number_format() - By default formats a number with the comma as the thousands separator, and no decimal.
  7. preg_match() - Returns the number of matches found by a given search string under this format, also capable of returning the match.
Examples:

echo number_format("1234567.123"); //Shows 1,234,567
echo number_format("1234567.123", 3, ",", " "); //Shows 1 234 567.123

$string = "156 abc";
var_dump(preg_match("/\w\s\w/", $string)); // 1 (matches)


PHP Basics (Section 1) - Database



I'd like to blog my understanding of PHP based on my 10+ years experience in developing scalable web based applications. There will be 14 sections in total, including: database, functions, strings, security, design pattern, javascript and more... :-) Here is the first section --- DATABASE

  1. Database cannot be tested by using specific code.
  2. While PHP is loosely types, databases are not. Therefore, detailed Information about the data being stored is required for efficient storage and retrieval, common data-types include: int(signed integer number, 32bits), char(fixed length character string), varchar(variable length character string), float(signed floating point number, 64bits)
  3. Most modern database systems fall into the relational category, the basis of which is the relationship between various tables
  4. Relationships link records based on some common data, relationships can be one to one, one to many, many to many
  5. DB systems can be configured to enforce those relationships to maintain referential integrity
  6. DB are smart and fast, but the DB designer has foreknowledge of how the DB will be used
  7. With this knowledge the designer can create an index on appropriate columns
  8. This index instructs the DBMS to store additional information about the data in that column, to make locating data within it as fast as possible
  9. Transactions allow you to merge multiple queries into one atomic operation, either they ALL execute successfully, or none do. (BEGIN TRANSACTION #name; ...queries here, COMMIT;) - Transactions are only available on InnoDB. :-)
So if you have a good idea which you think I need to improve (i.e. depth, examples, etc) , let me know and I will see what I can do.

Tuesday, 21 August 2007

Amazon S3 Makes My Document Management System Easier



Amazon S3 helps me to focus on innovating with data, rather than figuring out how to store it. Each file is stored and retrieved via a unique key which is stored on a DB table, together with its folder name (or associated object id) which fitted well in the document store structure. I am totally free from worrying about where the uploaded files are going to be stored and the safety on the hard-disc level.

Sample PHP code (Please contact me if you want a full copy):

if($s3->createFile($bucket, $key, $filePath, $contentType, $contentLength, $acl, $metadataArray, $md5))
{
if (!empty($focus->name))
{
$sql = "INSERT INTO .......";
$dbh->query($sql);
}
header("Location: index.php");
} else {
printError($s3->parsed_xml, $s3->responseCode);
}

List of Firefox Add-ons I am Using




Generic:
[A] del.icio.us
[B] Google web accelerator
[C] Firefox Operator 0.7
[D] Firefox Page Load Timer
[G] Skype

For Programming's Sake /* I am a PHP programmer :-) */
[E] HTML Tidy
[F] Firebug 1.05

Sunday, 19 August 2007

PHP Application Security Rules




Some basic but very important rules for PHP Apps:

  1. Set register_globals off (default value is off);
  2. Initialize all variables;
  3. Set the error_reporting (E_ALL) off;
  4. Grant permissions to users only to the level needed
  5. Only pass an identifier in a cookie, not actual data
  6. Set display_errors off, log_errors on
  7. Use PHP data validation rather than javascript validation which can be disabled
  8. Purge phpinfo.php
  9. If you use phpmyadmin, please do change its initial password
  10. MySQL : only select the fields you need rather than 'select *'
  11. The Tidy extension can also be used for a whilelist approach to HTML
  12. Escape the data before outputting it. i.e. htmlspecialchars(); htmlentities(); strip_tags()
  13. Don't forget to use is_uploaded_file($_FILES['upload_file']['tmp_name']) to prevent 'uploading' fake files

Properly validate user input (may not be enough; always remember to escape user-supplied content given in HTML, unless sure it was filtered)

Newest login methods also provide user-chosen image to help prevent against tricking them with 'pseudo' sites

PHP Data Validation Regexp (email, postcode, date)




[1] Email:
$email_regexp = '^([_a-zA-Z0-9-]+)(\.[_a-zA-Z0-9-]+)*@([a-zA-Z0-9-]+)(\.[a-zA-Z0-9-]+)*
(\.[a-zA-Z]{2,4})$';

[2] UK postcode:
$postcode_regexp = '^[A-Z]{1,2}[0-9]{1,2}[A-Z]{0,1}[[:space:]][0-9]{1}[A-Z]{2}';

[3] Birthday:
$date_regexp = '/^(0[1-9]|[12][0-9]|3[01])\D(0[1-9]|1[012])\D
(19[0-9][0-9]|20[0-9][0-9])$/';


Thursday, 16 August 2007

Caculate 8 UK Bank Holidays (PHP)




function get_bh($day, $month, $year) {
if ($month == 12 && $day == 25)
{
return 1; //Xmas
}
if ($month == 12 && $day == 26)
{
return 1; //Boxing
}
if ($month == 5 && (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, $day, $year), 0) == 1) && $day <=7) { return 1; //May Day } $c = floor($year/100); $n = $year-19*floor($year/19); $k = floor(($c-17)/25); $i = $c-floor($c/4)-floor(($c-$k)/3)+19*$n+15; $i = $i-30*floor($i/30); $i = $i-floor($i/28)*(1-floor($i/28))*floor(29/($i+1))*(floor(21-$n)/11); $j = $year+floor($year/4)+$i+2-$c+floor($c/4); $j = $j-7*floor($j/7); $l = $i-$j; $m = 3+floor(($l+40)/44); $d = $l+28-31*floor($m/4); if ($month == $m && $day == $d + 1) { return 1; //Easter Monday } if ($month == $m &&amp;amp;amp;amp;amp;amp; (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, $day, $year), 0) == 5) && $day <= $d && $day > $d - 7)
{
return 1; //Good Friday
}
if ($month == 1 && $day == 1 && (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, $day, $year), 0) != 6) && (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, $day, $year), 0) != 0))
{
return 1; //New Year Day
} elseif ($month == 1 && $day == 2 && (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, $day, $year), 0) != 0) && (jddayofweek(cal_to_jd(CAL_GREGORIAN, 1, 1, $year), 0) == 0))
{
return 1;
} elseif ($month == 1 && $day == 3 && (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, 2, $year), 0) == 0) && (jddayofweek(cal_to_jd(CAL_GREGORIAN, 1, 1, $year), 0) == 6))
{
return 1;
}
if ($month == 5 && (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, $day, $year), 0) == 1) && $day >= 25)
{
return 1;
}
if ($month == 8 && (jddayofweek(cal_to_jd(CAL_GREGORIAN, $month, $day, $year), 0) == 1) && $day >= 25)
{
return 1;
}
}

Thursday, 2 August 2007