PHP
PHP, Tip & Tricks - Friday, May 30, 2008 3:20 - 0 Comments
Reuse Excel business logic with PHPExcel
Reuse Excel business logic with PHPExcel
n many companies, business logic resides in Excel. This business logic is sometimes created by business analysts and sometimes by business users who want to automate parts of their everyday job using Excel. This same Excel-based business logic is often copied into an application (i.e. a website) and is maintained on 2 places: if the Excel logic changes, the application should also be modified. Did you know you can use PHPExcel to take advantage of the Excel-based business logic without having to worry about duplicate business logic?
Here’s a scenario: You are working in a company which sells “dream cars”. For every model, the company has created an Excel spreadsheet which is used to calculate the car’s price based on customer preferences. These spreadsheets are updated frequently in order to reflect the car manufacturer’s pricing schemes.
Your manager asks you to create a small website which accepts some input fields (Does the customer want automatic transmission? What colour should the car be painted? Does the customer want leather seats? Does the customer want sports suspension?). Based on these questions, the car’s price should be calculated. Make sure all prices on the website are in sync with this Excel sheet!
Download example source code
View live example
1. Create the Excel sheet containing business logic
First of all, we’ll create an Excel sheet containing business logic. If you’re lazy, download my example here. To make things easy for yourself when scripting, make sure you add some defined names on each field you want to use as input/output. Of course it’s possible to work with the sheet’s cell references later on, but if you want to be able to change the location of cells within the worksheet later, these defined names are much easier!
2. Download the latest PHPExcel version
You can find PHPExcel on www.phpexcel.net. If you want a stable version, download an official release. The source code tab on CodePlex reveals the latest Subversion source code if you want to use it.
3. Create the web based front-end
Next thing we’ll do is creating a simple webpage containing an HTML form which corresponds woth the parameters you want to pass to the Excel sheet.
4. Let’s do some PHP coding!
Since you came here for the good stuff, here it is! What we’ll do is load the Excel sheet, pass in the parameters and use some calculated values on our resultign page. First things first: include the necessary class references:
/** Include path **/
set_include_path(get_include_path() . PATH_SEPARATOR . ‘./PHPExcel/Classes/’);
/** Class requirements */
require_once(’PHPExcel.php’);
require_once(’PHPExcel/Reader/Excel2007.php’);
PHPExcel is the base library which represents an in-memory spreadsheet. Since we need to interface with an Excel2007 file, we also include the required reader class.
Now load the Excel sheet into a PHPExcel object:
// Load price calculation spreadsheet
$objReader = new PHPExcel_Reader_Excel2007();
$objPHPExcel = $objReader->load(”price_calculation.xlsx”);
All data from the web form is passed in via the $_REQUEST array. Let’s pass these to the Excel sheet. I named all form fields equal to my defined names in Excel which makes coincidence of all array keys and cell names being the same intentional.
// Set active sheet
$objPHPExcel->setActiveSheetIndex(0);
// Assign data
$objPHPExcel->getActiveSheet()->setCellValue(’automaticTransmission’, $_REQUEST[’automaticTransmission’]);
$objPHPExcel->getActiveSheet()->setCellValue(’carColor’, $_REQUEST[’carColor’]);
$objPHPExcel->getActiveSheet()->setCellValue(’leatherSeats’, $_REQUEST[’leatherSeats’]);
$objPHPExcel->getActiveSheet()->setCellValue(’sportsSeats’, $_REQUEST[’sportsSeats’]);
This is actually about it. The only thing left is to fetch the formula’s calculated values and we’re done!
// Perform calculations
$_VIEWDATA[’totalPrice’] = $objPHPExcel->getActiveSheet()->getCell(’totalPrice’)->getCalculatedValue();
$_VIEWDATA[’discount’] = $objPHPExcel->getActiveSheet()->getCell(’discount’)->getCalculatedValue();
$_VIEWDATA[’grandTotal’] = $objPHPExcel->getActiveSheet()->getCell(’grandTotal’)->getCalculatedValue();
You can use these values to print the result on your web page:
Based on your chosen preferences, your car will cost <?php echo number_format($_VIEWDATA[’grandTotal’], 2); ?> EUR.
5. Summary
Embedding business logic in Excel and re-using it in PHP is not that hard. The PHPExcel library helps you simplify development: your application logic and business logic is separated. Business logic can be maintained by a business expert or key user in Excel. As an application developer, you can easily pass data in the sheet and make use of PHPExcel’s calculation engine.
A Guide to Cryptography in PHP
A Guide to Cryptography in PHP
In an ideal world, words like cryptography and security wouldn’t even exist, but the real world is far from perfect, so software developers have to spend a good deal of time building security into applications. Cryptography is just one piece of the security puzzle, along with SSL/TLS, certificates, digital signatures, and so on. This article explains how to use PHP to implement the most common cryptographic algorithms. In addition to describing PHP’s default encryption functions, you’ll see how to use a wide variety of cryptographic libraries and packages.
The code examples in this article use the contents of a short text file, textfile.txt, which contains the following plain-text content:
For every difficult and complicated question there is an answer that is simple, easily understood, and wrong. H.L. MenckenDefault PHP Encryption Functions
PHP ships with three built-in encryption functions: md5(), crypt(), and sha1(). The md5() function prototype is:string md5(string $str [, bool $raw_output ])The function calculates the MD5 hash of a supplied string using the MD5 Message-Digest algorithm. The $str argument represents the string to be encrypted. If you pass FALSE in the $raw_output argument (the default), the function returns the hash as a 32-character hexadecimal number. If you pass TRUE then the function returns a 16-byte raw binary value.
The PHP crypt() function is a one-way encryption function that lets you confirm that an entered password matches a stored encrypted one—without having to decrypt anything. The crypt() function prototype is:
string crypt (string $str [, string $salt ])It returns an encrypted string using the standard Unix DES-based encryption algorithm (or alternative algorithms that may be available on the system). The $str argument is the string to be encrypted and the optional $salt argument is a string on which to base the encryption. If you don’t provide the salt string, PHP will randomly generate one each time you call this function.
The PHP sha1() function calculates the SHA-1 hash of a string. The sha1() function prototype is:
string sha1 (string $str [, bool $raw_output ])
Figure 1. Encrypted File: The encrypted.txt file contains a password encrypted with md5, crypt, and sha1 PHP default functions. The function returns the SHA-1 hash as a string. Again, the $str argument represents the input string. If you set the optional $raw_output argument to TRUE, the function returns the sha1 hash in raw binary format with a length of 20 characters; if you set it to FALSE, it returns a 40-character hexadecimal number.
As an example, the following code shows how to use the PHP default encryption functions to encrypt the contents of texfile.txt file and write the encrypted result in the file encrypted.txt (see Figure 1):
<?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ $password = 'OctaviaAnghel'; //Calculates the md5 hash $md5_data = md5($password); //This function encrypts data $crypt = crypt($password); //Calculate the sha1 hash $sha1 = sha1($password); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,'md5: '. $md5_data."\r\n".'crypt: '.$crypt."\r\n".'sha1: '.$sha1); if($ok_encrypt){ echo 'The encrypted code was succesfully created'. ' in encrypted_file.txt!!!'.' '; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); } ?>In addition to the built-in functions, PHP supports encryption via external libraries and packages. Table 1 shows the libraries and packages described in the rest of this article.
Table 1. Cryptography in PHP: The table contains a list of packages and libraries described in this article that work with PHP to perform various types of encryption and decryption.Package/Library Description MCrypt Use MCrypt to encrypt large files or data streams using any of a wide range of encryption functions. You can find more information at http://mcrypt.sourceforge.net/. MHash Use the MHash library to obtain hashes. MHash supports the most popular algorithms and implementations, such as SHA, MD5, and CRC. You can use these algorithms to compute checksums, message digests, and create other signatures. MHash is often used to obtain password hashes for passwords entered into HTML password fields. You can find more information at http://mhash.sourceforge.net/. Crypt_Blowfish Use Crypt_Blowfish for quick two-way encryption both with or without a secret key. You don’t need the MCrypt PHP extension to use Crypt_Blowfish; however, the package can use MCrypt if it’s installed. More details at: http://pear.php.net/package/Crypt_Blowfish. Crypt_RSA Crypt_RSA provides RSA-like key generation, encryption/decryption, signing and signature checking. More details here: http://pear.php.net/package/Crypt_RSA. Crypt_ HMAC This class calculates RFC 2104-compliant hashes. You’ll find complete information at: http://pear.php.net/package/Crypt_HMAC. Crypt_DiffieHellman This package is a PHP5 implementation of the Diffie-Hellman Key Exchange cryptographic protocol. You can find more information at http://pear.php.net/package/Crypt_DiffieHellman. Encrypting Large Data with MCrypt
MCrypt allows developers to encrypt files or data streams using any of a large number of encryption functions without having to be cryptographers. MCrypt supports a wide variety of block algorithms such as Blowfish, DES, TripleDES, SAFER-SK128, TWOFISH, TEA, RC2, 3-WAY, SAFER-SK64, and several “modes of operation.” Normally a block chipper such as MCrypt operates on data blocks of fixed length, often 64 or 128 bits. But because messages may be of any length, and because encrypting the same plaintext using the same key always produces the same output, several solutions have been invented that allow block ciphers to provide confidentiality for messages of arbitrary length. These solutions are known as modes of operation. The modes supported by MCrypt include: CBC, CFB, CTR, ECB, OFB, and NCFB.The companion library for MCrypt is Libmcrypt, which contains the actual encryption functions themselves. Windows users can download it here, while Linux users can get it here.
Author’s Note: If you are using PHP 5.0.0 you will also need libmcrypt Version 2.5.6 or greater. Installing Libmcrypt:
- Download libmcrypt.dll.
- Copy the libmcrypt.dll file to {php_home}/ext and {Windows_home}/System32.
- In php.ini activate the extension=php_mcrypt.dll line by deleting the comment mark (“;”).
- Save the updated php.ini file.
Author’s Note: For Linux, you have to download the libmcrypt-x.x.tar.gz file and follow the included installation instructions. MCrypt can operate with the four cipher modes CBC, OFB, CFB, and ECB. If you are using a libmcrypt-2.4.x version or higher, then MCrypt functions also operate with the nOFB and STREAM cipher modes. Table 2 shows the most commonly-used encryption modes, along with a short description of when to use each.
Table 2. Commonly-Used MCrypt Modes: These cipher modes all operate with MCrypt, and are useful in different situations.Encryption Mode Description MCRYPT_MODE_ECB Use with random data. You can use this mode to encrypt different keys. MCRYPT_MODE_CBC Used for encrypting files. MCRYPT_MODE_CFB Recommended for encrypting byte streams. MCRYPT_MODE_OFB Used specifically in applications where error propagation is not accepted. MCRYPT_MODE_NOFB Comparable with OFB, but more secure. MCRYPT_MODE_STREAM Use when you need stream algorithms such as WAKE or RC4. In addition to the modes listed in Table 2, MCrypt also currently supports these ciphers:
- MCRYPT_3DES
- MCRYPT_ARCFOUR
- MCRYPT_BLOWFISH
- MCRYPT_ENIGMA
- MCRYPT_GOST
- MCRYPT_IDEA (non-free)
- MCRYPT_LOKI97
- MCRYPT_MARS
- MCRYPT_PANAMA
- MCRYPT_RIJNDAEL_128
Author’s Note: Because the list of supported ciphers can change over time, you should periodically check this list of the currently supported ciphers . MCrypt Example
Here’s an example that shows how to encrypt and decrypt the contents of a text file using MCrypt. Again, the example encrypts the contents of textfile.txt and stores the encrypted result in the file encrypted.txt. However, this example also decrypts that file and stores the unencrypted text in the file newfile.txt:// Listing file_encrypt.php <?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ //This function opens the module of the algorithm and the mode to be used $td = mcrypt_module_open('tripledes', '', 'ecb', ''); //Create an initialization vector (IV) from a random source $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); //This function initializes all buffers needed for encryption mcrypt_generic_init($td, $initial_contents, $iv); //This function encrypts data $encrypted_data = mcrypt_generic($td, $initial_contents); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,$encrypted_data); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); mcrypt_generic_init($td, $initial_contents, $iv); //This function decrypts data $p_t = mdecrypt_generic($td, $encrypted_data); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$p_t); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); //This function deinitializes an encryption module mcrypt_generic_deinit($td); //Close the mcrypt module mcrypt_module_close($td); } ?>Building Hashes with MHash
MHash is a free library that lets developers choose from a large number of hash algorithms. These algorithms can be used to compute checksums, message digests, and create other signatures.Installing Libmhash
- Download libmhash.dll.
- Copy the libmhash.dll file to {php_home}/ext and to {Windows_home}/System32.
- In php.ini, activate the extension=php_mhash.dll line by deleting the comment mark (”;”).
- Save the updated php.ini file.
Supported Hashes
The hashes currently supported by MHash are:- MHASH_ADLER32
- MHASH_CRC32
- MHASH_CRC32B
- MHASH_GOST
- MHASH_HAVAL128
- MHASH_HAVAL160
- MHASH_HAVAL192
- MHASH_HAVAL256
- MHASH_MD4
- MHASH_MD5
- MHASH_RIPEMD160
- MHASH_SHA1
- MHASH_SHA256
- MHASH_TIGER
- MHASH_TIGER128
- MHASH_TIGER160
The following example uses MHash to encrypt the contents of texfile.txt and write the encrypted result to encrypted.txt:
<?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ //mhash() applies a hash function specified by MHASH_MD5 //to the $initial_contents $encrypted = mhash(MHASH_MD5, $initial_contents); // get current Unix timestamp $current = time(); $salt = $current; $password = "Octavia"; //mhash_keygen_s2k generates a key according to the hash function //given and the password provided by the user. $hash = mhash_keygen_s2k(MHASH_GOST, $password, $salt, 20); //concatenate the $salt with the $hash $key = $salt . "|" . bin2hex($hash); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file, 'mhash: '.bin2hex($encrypted).' mhash_keygen_s2k: '.$key); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt !!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); } ?>Secret Keys and Crypt_Blowfish
Secret-key cryptography uses a single key for both encryption and decryption—also called a symmetric key. For example, the commonly-used DES algorithm is a secret key algorithm. The Crypt_Blowfish PEAR package is based on the Blowfish block cipher and supports two-way encryption, either with or without a secret key. The package doesn’t require MCrypt, but Crypt_Blowfish can use MCrypt if it’s installed. The latest released version is 1.0.1 (stable), and you install it like any other PEAR package:> pear install pear_package_nameThis package uses two classes defined in the Blowfish.php file, which you must include in all scripts that use the Crypt_Blowfish package:
require_once 'Crypt/Blowfish.php';Here’s the code for the by-now-familiar encryption example program using Crypt_Blowfish:
<?php require_once 'Crypt/Blowfish.php'; $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ $bf = new Crypt_Blowfish('some secret key!'); // Encrypts a string $encrypted = $bf->encrypt($initial_contents); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,$encrypted); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); // Decrypts an encrypted string $plaintext = $bf->decrypt($encrypted); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$plaintext); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); } ?>Encrypt Data Using an Arbitrary Key Length with the Crypt_RSA PEAR Package
This package supports two-way encryption; it’s based on the RSA block cipher. Crypt_RSA supports encryption and decryption using an arbitrary key length. You can download the latest version (1.0.0, stable) and install it like any other PEAR package:> pear install pear_package_nameCrypt_RSA performs intensive math calculations, for which it uses one of the following extensions:
- PECL big_int extension—(requires a version greater than or equal to 1.0.3)
- PHP GMP extension
- PHP BCMath extension for PHP4/PHP5. Required because libbcmath was bundled with PHP 4.0.4.
Here’s an example of using this package:
<?php require_once 'Crypt/RSA.php'; //Generates the pair keys function generate_key_pair() { global $public_key,$private_key; $key_pair = new Crypt_RSA_KeyPair(32); //Returns public key from the pair $public_key = $key_pair->getPublicKey(); //Returns private key from the pair $private_key = $key_pair->getPrivateKey(); } //Check runtime errors function check_error(&$obj) { if ($obj->isError()){ $error = $obj->getLastError(); switch ($error->getCode()) { case CRYPT_RSA_ERROR_WRONG_TAIL : // nothing to do break; default: // echo error message and exit echo 'error: ', $error->getMessage(); exit; } } } $file = 'textfile.txt'; generate_key_pair(); $plain_text = file_get_contents($file); //get string represenation of the public key $key = Crypt_RSA_Key::fromString($public_key->toString()); $rsa_obj = new Crypt_RSA; check_error($rsa_obj); //Ecnrypts $plain_text by the key $key. $encrypted = $rsa_obj->encrypt($plain_text, $key); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = fwrite($encrypted_file,$encrypted); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); $enc_text = $encrypted; //Get string represenation of the private key $key2 = Crypt_RSA_Key::fromString($private_key->toString()); check_error($key2); //Check encrypting/decrypting function's behaviour $rsa_obj->setParams(array('dec_key' => $key2)); check_error($rsa_obj); //Decrypts $enc_text $decrypted = $rsa_obj->decrypt($enc_text); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$decrypted); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); ?>Generating Hashes with Crypt_HMAC
The Crypt_HMAC PEAR package contains a class you can use to calculate RFC 2104-compliant hashes. Crypt_HMAC is easy to use; you need only provide your secret key, the hash method you want to use, and the plaintext string. Crypt_HMAC supports both MD5 and SHA-1 algorithms. The latest stable released version is 1.0.0. You install it just like any other PEAR package:> pear install pear_package_nameAnd here’s a simple example that creates a hash using Crypt_HMAC:
<?php require_once 'Crypt/HMAC.php'; //Creating a key by repeating the "0x0b" character for 20 times $key = str_repeat(chr(0x0b), 20); //Creating an instance of the Crypt_HMAC class //$crypt = new Crypt_HMAC($key, 'md5'); $crypt = new Crypt_HMAC($key, 'md5'); //Hashing function echo $crypt->hash('Hello')."<br />"; $key = str_repeat(chr(0xaa), 10); $data = str_repeat(chr(0xdd), 50); //Sets key to use with hash $crypt->setKey($key); echo $crypt->hash($data)."\n"; ?>Generating Secret Keys with the Crypt_DiffieHellman PEAR Package
This PEAR package implements the Diffie-Hellman Key Exchange cryptographic protocol in PHP5. You can use the protocol to generate a secret key for two foreign parties, who can then use the generated key for communications even on insecure channels. You can download the latest release, version 0.2.1 (beta) and then install it the same way as any other PEAR package.> pear install pear_package_nameThe following two code examples show two applications for generating a secret key between two parties: subject_1 and subject_2. The first example shows you the simplest way to obtain a secure key based on Diffie Hellman algorithm:
<?php //include Diffie Hellman functions require_once 'Crypt/DiffieHellman.php'; //set the required options for two subjects $subject_1 = array('prime'=>'123', 'generator'=>'7', 'private'=>'3'); $subject_2 = array('prime'=>'123', 'generator'=>'7', 'private'=>'34'); //apply Diffie Hellman algorithm $subject_1_GK = new Crypt_DiffieHellman( $subject_1['prime'], $subject_1['generator'], $subject_1['private']); $subject_2_GK = new Crypt_DiffieHellman( $subject_2['prime'], $subject_2['generator'], $subject_2['private']); //generate keys $subject_1_GK->generateKeys(); $subject_2_GK->generateKeys(); //compute the secret keys $subject_1_SK = $subject_1_GK->computeSecretKey( $subject_2_GK->getPublicKey())->getSharedSecretKey(); $subject_2_SK = $subject_2_GK->computeSecretKey( $subject_1_GK->getPublicKey())->getSharedSecretKey(); //displaying the secret keys echo('Subject_1_SK:'.$subject_1_SK.'<br />'); echo('Subject_2_SK:'.$subject_2_SK); ?>The second example shows you how to generate a secret key using the Diffie Hellman BINARY mode:
<?php //include Diffie Hellman functions require_once 'Crypt/DiffieHellman.php'; //set the required options for two subjects $subject_1 = array('prime' => '9568094558049898340935098349053', 'generator'=>'2', 'private' => '2232370277237628823279273723742872289398723'); $subject_2 = array('prime' => '9568094558049898340935098349053', 'generator'=>'2', 'private' => '0389237288721323987429834389298232433363463'); //apply Diffie Hellman algorithm $subject_1_GK = new Crypt_DiffieHellman( $subject_1['prime'], $subject_1['generator'], $subject_1['private']); $subject_2_GK = new Crypt_DiffieHellman( $subject_2['prime'], $subject_2['generator'], $subject_2['private']); //generate keys $subject_1_GK->generateKeys(); $subject_2_GK->generateKeys(); //compute the secret keys using BINARY mode $subject_1_SK = $subject_1_GK->computeSecretKey( $subject_2_GK->getPublicKey(Crypt_DiffieHellman::BINARY), Crypt_DiffieHellman::BINARY)-> getSharedSecretKey(Crypt_DiffieHellman::BINARY); $subject_2_SK = $subject_2_GK->computeSecretKey( $subject_1_GK->getPublicKey(Crypt_DiffieHellman::BINARY), Crypt_DiffieHellman::BINARY)-> getSharedSecretKey(Crypt_DiffieHellman::BINARY); //display the secret keys echo('subject_1_SK:'.$subject_1_SK.'<br />'); echo('subject_2_SK:'.$subject_2_SK.'<br />'); ?>With the wide variety of cryptographic options you’ve seen here, you should be able to achieve nearly anything you want. Cryptography is a delicate security problem—and as you can see there are many solutions and implementations. The information in this article can help you get started, but beyond that, only experience and hard work with secure systems will help you to choose the cryptographic implementation that represents the perfect compromise between security, speed, and implementation time.
Octavia Andreea Anghel is a senior PHP developer currently working as a primary trainer for programming teams that participate at national and international software-development contests. She consults on developing educational projects at a national level. She is a coauthor of the book “XML technologies—XML in Java” (Albastra, ISBN 978-973-650-210-1), for which she wrote the XML portions. In addition to PHP and XML, she’s interested in software architecture, web services, UML, and high-performance unit tests.8 Best Open Source Shopping Carts
8 Best Open Source Shopping CartsHey Everyone, On Sunday I was contacted by a client and they said the needed a shopping cart up by Monday. Since they needed this cart up so fast I went to the easiest solution I knew, Open Source Shopping Carts. I browsed through tons of shopping carts and put together a list of only the best carts. The list is below. Continue…
Computer Random vs. True Random
Computer Random vs. True Random
See the difference in how random numbers are generated. Thank you Random.org!
Note: I am doing more research comparisons and will have more data and analysis up very soon.
I’ve always been into scripting things using random numbers based on random functions, like PHP’s “rand()” function… but I’ve never compared these types of functions to true random number generators. Then one day, I stumbled upon Random.org, which is a true random number generating service.
Fetching a Web Page From Your PHP Code
To fetch a web page from your PHP application, you could use curl functions or simply open the page with fopen(). But these have some limitations. Your server needs to have PHP with curl enabled, or the PHP configuration should allow scripts to open an URL with fopen().If that is not the case, you can still fetch a web page by opening a socket connection to the remote host and make HTTP request.
How To Detect Internet Explorer Version With PHP
Awhile ago I needed to detect the Internet Explorer version of the visitor from inside of my PHP script. Being lazy I just tried to Google for some existing code, but to my surprise there was none available! Well, I think it’s time to rectify that problem by publishing the code I ended up creating. The ieversion() function looks at the HTTP_USER_AGENT header sent by the browser to determine if the visitor is using Internet Explorer. If not, then the script will return -1. If yes, then the script will extract the version number and return that.Secure PHP Programming
Secure PHP Programming! By Steven WelchWhen a web site is cracked, it typically tends to be a simple common sense mistake by a program author who forgets what an attacker can do with his code. By keeping good, secure practices when programming, you should be able to produce solid code.
However, before I even get into the code part of this shin dig, one obvious fact should be stated that you should never give a public_html directory (or any other directory that you are using to host your files) nor any of its files ownership by any user with root privileges. This and any other techniques you can think of must be implemented in order to minimize the damage an attacker can do. That being said, on with coding!
Let’s look at a typical attack of a PHP program. The following code is an example of an unsecure script to ‘echo’ the visitor’s name:
<?php if (isSet($_POST[‘name’])) { echo “Hello, “ . $_POST[‘name’]; } else { echo ‘<form action=”‘ . $PHPSELF . ‘” method=”post”><br>’; echo ‘Your name, please: <input type=”text” name=”name”><br>’; echo ‘<input type=”submit” value=”Submit”>’; echo “</form>”; } ?>
Now this may look fine if you were to input a name such as ‘John’ or ‘Marry’, but what if the attacker were to input something like:
<script language=“JavaScript” type=“text/javascript”> alert(“You have been hacked.”); window.location.href = “http://www.bad-side-to-go-to.com/”; </script>
This means that this script would allow the attacker to deface your page (among many other evil little deeds such as setting up a backdoor with a little skill). As a practice, you should never, ever output code that is directly inputted from the user. In this case, PHP has a few functions that would allow us to solve this problem.
First off, strip_tags() simply removes HTML and PHP tags from a string. For example:
<?php $str = “<html>hi</html>”; echo strip_tags($str); // outputs ‘hi’ ?>
This works for most cases, but there are also ways of outputting the HTML code without executing it. Two functions, htmlentities() and htmlspecialchars(), convert any sort of <, >, ” and & to their HTML entities (ex. “<” for “<” and “>” for “>”). Here’s an example of using htmlentities():
<?php $str = “<html>hi</html>”; echo htmlentities($str); // outputs ‘<html>hi</html>’ ?>
This way, you can see the actual code but it won’t be executed (as in you would see the JavaScript code I showed you above, but you won’t have the alert() popup box nor will the page redirect). I like to use htmlentities() because it converts ALL of HTML entities to their representitive codes, but htmlspecialchars() is fine for simply wanting to thwart off an attacker. (Note that htmlspecialchars() works exactly the same as htmlentities() does as far as usage is concerned.)
So, here’s an example of a fixed version of the script I showed you earlier:
<?php if (isSet($_POST[‘name’])) { echo “Hello, “ . htmlspecialchars($_POST[‘name’]); } else { echo ‘<form action=”‘ . $PHPSELF . ‘” method=”post”><br>’; echo ‘Your name, please: <input type=”text” name=”name”><br>’; echo ‘<input type=”submit” value=”Submit”>’; echo “</form>”; } ?>
NOTE: About 90% or more of PHP-related exploits are from some kind of way of attacking the developer’s input ($_GET, $_POST…).
Outputted code is not the only kind of input attack we have to worry about. Another kind is that which involve the programmer reading arbitrary files. For example, let’s say we have a script like:
<?php if (isSet($_GET[‘file’])) { $theFile = fopen($_GET[‘file’], “r”); echo fread($theFile, filesize($_GET[‘file’])); fclose($theFile); } else { echo ‘<form action=”‘ . $PHPSELF . ‘” method=”get”><br>’; echo ‘<select name=”file”><option value=”testFile.html”>testFile.html</select><br>’; echo ‘<input type=”submit” value=”Submit”>’; echo “</form>”; } ?>
This may look all fine and dandy, but it’s flawed out the kazoo. First of all, since this form uses the ‘get’ method of handling input, the user can simply change the file from the URL line of the browser. Second, an attacker could simply create a HTML page on his/her own site with code like:
<form action=“http://yoursitehere.com/scriptijustwrote.php” method=“get”> <input type=“text” name=“file”> <input type=“submit” value=“Submit”> </form>
Either way, they can change the file you open to anything they like. For example, let’s say that they set $_GET[’file’] to be something like ‘/etc/passwd’. They could have that easily obtained and possibly cracked into your account from the UNIX ‘passwd’ file! (Not to mention any other sensitive files they could’ve opened from this script…)
Clearly this script is very, very dangerous for you as a programmer. There are a few options you can do to prevent this:
First off, let’s say that you only have a list of available files that the script will open. Change the file opening code to first see if the file is one that you will let it open, such as:
if ($_GET[‘file’] == “testFile.html”) { // open the file } else { // don’t open the file }
Or, even better would be something like:
switch ($_GET[‘file’]) { case “testFile.html”: $file = “testFile.html”; break; case “otherFile.html”: $file = “otherFile.html”; break; } // open the file using $file
Another option would be to remove any slashes or dots from the filename, but then again you would still allow the attacker to open any file in that single directory. If that directory is safe, then use str_replace() like so:
$file = str_replace(“/”, “”, str_replace(“\”, ““, str_replace(”.“, ““, $_POST[’file’])));
Now, only open the $file variable.
This option is definitely not recommended simply because that entire directory is vulnerable to be publicly accessible, but if you don’t mind then go ahead.
Now then, let’s have a look at another type of input attack in the form of running arbitrary programs. Let’s say you have a script that will use the system command ‘ping’ to see if a network target is alive. Here’s an example of this script as a vulnerability:
<?php if (isSet($_POST[‘target’])) { system(“ping “ . $_POST[‘target’]); } else { echo ‘<form action=”‘ . $PHPSELF . ‘” method=”post”><br>’; echo ‘<input type=”text” name=”target” value=”Target Address”><br>’; echo ‘<input type=”submit” value=”Submit”></form>’; } ?>
This would be fine if the user simply inputted a target, like “yahoo.com”. However, what if the attacker inputted a statement like “; rm -rf /”? Just like that, your entire filesystem got whiped clean from one vulnerable script (assuming your account has root privelages, but either way a lot of important stuff is getting deleted).
There are a few solutions here, chiefly to filter out any bad input using a function like preg_replace(), but even I had trouble learning how to use that function. A more simple, but not as secure, solution is to use escapeshellcmd(). This function returns a string from your command that prevents the user from running any other program than the one you want it to run (”ping” in this example). As an example, you’d simply do this:
system(escapeshellcmd(“ping “ . $_POST[‘target’]));
While this prevents any other programs from being run, it does not prevent the attacker from inputting invalid data to ‘ping’. If there was an exploit for that program or some kind of input that would make it exit or run another program itself, then you’re still screwed. Your best bet is to try and stay away from allowing visitors to access any kind of system() commands.
Other than input attacks, there are plenty of code problems that you as a programmer may not even know about. One thing you should always remember, however, is to keep your code from being shown as much as possible. Let’s say an attacker somehow renames your file from index.php to index.phps. On most PHP web servers, this will show all the code in index.php (including the PHP code) so that the attacker can find a flaw they wouldn’t have found without seeing the code. A good bet to keep this from happening is to make your scripts executable only in a cgi-bin directory.
However, some web servers do not support scripts in a cgi-bin directory. If yours does, then simply try putting a test script in that directory and ‘chmod +x’ the file to make it executable. The code will change a little bit, because instead of PHP being inside of the HTML coded file, the HTML will be inside your PHP script! Here’s an example:
#!/usr/bin/php // if the path to PHP is different, then you’ll have to change that line echo “<html>\n<body>\nTesting!\n</body>\n</html>”;
Save this as something like ‘test.php’ and put it in your cgi-bin directory. From your web browser, try to execute it. If it works, then it’s a good idea to use your scripts in that style in the cgi-bin to prevent code leakage. If it doesn’t work, then either e-mail your admin or rebuild your PHP/Apache or whatever installation to include this option.
An entirely different topic in PHP security is encryption. There are many different kinds of encryption, but compared to other languages PHP makes them all easy as pie. The easiest example of encryption is the one-way 32 bit MD5 encryption. “One way” encryption means that the data CANNOT be decrypted. This means that even if the attacker gets the encrypted data, they cannot decrypt, but instead will have to ‘crack’ it. For example, let’s say we have a password file in our home directory (’/home/user/pass_info.php’):
<?php $user = ‘testuser’; $pass = md5(“mypasswd”); ?>
The md5() function converts “mypasswd” to a 32 bit “hash” (encrypted data, basically) that is about 32 or so characters long and each character is either a letter or a number. Any other text than “mypasswd” will produce a different hash, so we can rely on what the encrypted version of “mypasswd” is. Now that we have $pass set, let’s say we have another script like this that sets the user’s $_SESSION data to show he or she is logged in according to their password:
<?php include(“/home/user/pass_info.php”); if (isSet($_SESSION[‘user’]) && isSet($_SESSION[‘pass’]) && $_SESSION[‘user’] == $user && $_SESSION[‘pass’] == $pass) { echo ‘You are logged in.’; } else if (isSet($_POST[‘user’]) && isSet($_POST[‘pass’]) && $_POST[‘user’] == $user && md5($_POST[‘pass’]) == $pass) { $_SESSION[‘user’] = $user; $_SESSION[‘pass’] = $pass; ?> <script language=“JavaScript” type=“text/javascript”> alert(“you are now logged in”); window.location.href = window.location.href; </script> <?php } else { ?> <form action=“?” method=“post”> <input type=“text” name=“user”><br> <input type=“password” name=“pass”><br> <input type=“submit” value=“Login”> </form> <?php } ?>
In this way, $_SESSION[’pass’] is a 32 bit encrypted hash instead of a plaintext password. If the attacker was to get your $_SESSION data and see that a variable names $_SESSION[’pass’] was equal to a plaintext password, then he/she just cracked your user/pass! Now that we have it encrypted via md5(), he/she can only see the encrypted version. Now the attacker would have to run a bruteforce style attack on your encrypted password data which can take months depending on how good your password is. (This is also a good reason to change passwords often.)
If you think that md5() is out of your style, or you just want to use a different encryption key, you can use crypt() as well. crypt() uses the same method as UNIX /etc/passwd files, and is farely simple. First, let’s encrypt a string:
<?php $encryptedData = crypt(“testPass”); ?>
Now, let’s make a function to compare your crypt() data with a string to see if the password is correct:
<?php function verifyEncryptedData($str, $data) { $salt = substr($data, 0, CRYPT_SALT_LENGTH); // gets the crypt() encryption key into $salt $encryptedStr = crypt($str, $salt); // encrypt the given data using the current key return ($encryptedStr == $data); // returns a TRUE/FALSE statement based on if $str is indeed the encrypted test in $data } verifyEncryptedData(“testPass”, $encryptedData); // should return TRUE verifyEncrytpedData(“hahaha”, $encyptedData); // should return FALSE ?>
Here we see an example of encryption that uses different encryption ‘keys’, where as md5() uses the same key every time. crypt() generates a random key every time something is encrypted with it.
Now you may be wondering what I was talking about when I said an attacker would try a brute-force attack on your encrypted data. This means that he/she would try to encrypt every possible value from a-z 1-9 for however many characters it takes in whatever kind of encryption you are using until they have cracked the password. Let’s say you had a password of the letter ‘c’. A brute force program would first try to encrypt ‘a’ without success, ‘b’ without success, and then found out your password when it tries ‘c’. As you can see, the more characters and the more different of a letter/number/symbol combination you use in a password will make a password cracking program take longer to crack your password. Your best bet is to change passwords often so that even if he/she cracks the password, they’ll return to find that you’ve already changed the password and they’ll have to start all over again.
If you want to use encryption that allows you to decrypt its contents, look into PHP’s mcrypt module. (http://www.php.net/ comes in handy, folks!) It’s the best encryption module for PHP I know of as it lets you choose your encryption method from a wide selection though it takes just a tad bit of learning, but I’ll leave that up to you.
All in all, just use common sense and follow safe practices when it comes to PHP. Don’t let one vulnerable script be the reason your whole network gets cracked!
Most Popular Content
- Kopete, The KDE Instant Messenger
- Warning Signs You Can’t Ignore
- Robotic Jellyfish Swim and Fly at Hannover Fair
- The Real Indiana Jones
- Popular Wealth - Free Photoshop Brushes To Download
- 5 Ways To Combat Aging
- Inflatable robots could explore Mars
- Thinking the Way Animals Do
- Top 10 things to do in a blackout
- The most natural drug
- 30 Websites to follow if you’re into Web Development
- Please,I want you to help me with some of your books that will enable me to keep...
- You should also mention Ubercart (http://www.ubercart.org) a very powerful Drupa...
- Hello i am interessted on this script please can you contact me!?...
- Excellent article and oh so true.
Thanks...
- Well done.
If you use Ubuntu for, say, half a hour, you'll never go back to W...
- I own a "Super Battery" chinesse mobile phone, Chivak78, and I can assure you th...
- Thank You Very MUCH!!!
I had a working key, but the last time I reinstalled, it...
- Is this big deal end yet ?...