Introduction to FPDF – Take 2 – DC PHP

On August 14th I visited DC PHP to give my talk about FPDF. I gave a very similar talk to that presented to Baltimore PHP in July. I walked the audience through the creation of a simple invoice using the FPDF PDF creation library. I have uploaded the slides and the sample document that we created so that if you missed it, or you wan’t to walk through it again, you have that opportunity.

FPDF Example Documents

A Transition of Sorts

Over the past month I have been going through a fairly major transition in my career. I have left Physicians Management Group (PMG) in order to join TapFury. I spent just over a year with PMG working with them as a web developer. Leaving wasn’t always the easiest choice, but in the end it was the right decision to make. In leaving PMG allowed me the opportunity to join TapFury, also as a web developer.

I am extremely excited to see what the future holds for me during my time with TapFury. One challenge I will face with TapFury is a switch to working with Zend Framework. Prior to taking over the codebase I have never spent anytime with the Zend Framework, and while I’ve only spent a couple days playing with it thus far, I am impressed in its ease of use and understandability. Another thing that will take some adjustment is the change in work environment. Physicians Management Group is a medium sized company with about 80 people in the building, including people from the different departments that make up the company. Departments like IT, finance, and operations. With TapFury I will be working in an office of one, well maybe two, if you count my dog Pierre. The office of one is right down the hall, my home office.

I look forward to seeing whats to come next in my career.

Introduction to FPDF – Baltimore PHP

Baltimore PHP Logo

Baltimore PHP

I spoke at Baltimore PHP and gave a talk introducing the audience to FPDF. FPDF is a completely free library written in PHP for the creation of PDF documents. The talk was title “Introduction to FPDF”, for pretty obvious reasons. If you ever deal with PDF documents it might be a good idea to take a look at FPDF, and my presentation.

I have uploaded the slides to slideshare and have embedded them below. I also uploaded the files that I used to create the document shown in the presentation. The files are available in a zip format and weigh in at 47kb. Introduction to FPDF Example Documents

If you would like to see me present this talk in person, I will be presenting it at DC PHP on August 14, 2013.

Upcoming Speaking Engagements

If you are in the Baltimore or Washington D.C. areas you’ll have an opportunity to come out and see me speak in the next month or so. On July 17th I’ll be speaking at Baltimore PHP presenting on FPDF. I will be giving the same talk with DC PHP on August 14th. I will make the slides available online after the Baltimore PHP presentation.

If you are in either area at the appropriate times please come out and say “hey”.

Five Functions You Probably Didn’t Know PHP Had

PHP is a fairly large language, with many functions available to developers, including a few that you probably didn’t know existed. This post is going to take a brief look at various functions in the PHP programming language that are often overlooked, forgotten, or just unknown. Let’s just jump right in, shall we?

    1. get_defined_vars()

Have you ever wanted to see every variable defined in your PHP script. $_GET, $_POST, $_GLOBALS, $_SERVER, user defined. When called every, single, variable, that is defined is returned as an array.

    2. sys_getloadavg()

Has your server been sluggish lately and you can’t figure out why? This function would come in handy, especially if you are working on a shared hosting environment and you don’t have full access to the server’s logs. sys_getloadavg() returns an array with the average system load over the last 1, 5, and 15 minutes. On my local machine these were my results:

array(3) {
  [0]=>
  float(0.783203125)
  [1]=>
  float(0.56298828125)
  [2]=>
  float(0.5625)
}

As you can see, my machine is really showing offthe computational muscle (well, not really).

    3. levenshtein()

Ever find the need to determine how different (or similar) two words are? Then levenshtein() is just the function you need. The PHP manual suggests using levenshtein() to determine if a user submitted a typo.

    4. parse_str()

Allow me to set the scene. It’s a beautiful summer afternoon on a Friday, the clock is ticking away. Every time you look up you see it is later and later, first it’s 4:30pm. Then 6:00pm. Now it’s 8:00pm and it is now well beyond time to go home for the weekend, but there is one bug in your application that you just can’t squash. You keep submitting your HTML form over and over but the data isn’t being processed correctly. You waste time after each modification to the code filling in the same information, over and over, but the output still isn’t what you expect. Here is where parse_str() will come into handy. Simply supply a string of arguments that you wish to be mapped to your $_POST variable and away you go.

<?php 
$str = "firstName=Test&lastName=Data&address[]=123+Main+Street&address[]=A+City,+A+State+12345";
parse_str($str, $_POST);

var_dump($_POST);
/*
array(3) {
  ["firstName"]=>
  string(4) "Test"
  ["lastName"]=>
  string(4) "Data"
  ["address"]=>
  array(2) {
    [0]=>
    string(15) "123 Main Street"
    [1]=>
    string(21) "A City, A State 12345"
  }
}
*/
?>
    5. php_egg_logo_guid()

Unfortunately this gem was removed in PHP 5.5. But, did you know that you could output a modified version of the PHP logo with the ElePHPant with a simple function call?

<?php
echo '<img src="'.$_SERVER['PHP_SELF'].'?='.php_egg_logo_guid().'"/>';
?>

If you want to see the output, go ahead and give it a run on your server.

These are a few of a lesser known functions in the PHP language. There are many more buried under the hood. A bit of digging through the manual will uncover plenty of other useful (or in the case of php_egg_logo_guid(), fun) functions that were just waiting to be discovered. What are some of your favorite lesser known functions?

Creating and Verifying Hashes in PHP, The Easy Way

PHP 5.5.0 was released yesterday, with it came a whole list of new features and functions. One of the new APIs available is the Password Hashing API. This API currently contains four functions, password_get_info(), password_hash(), password_needs_rehash(), and password_verify(). Let’s step through each of these functions.

First we will discuss password_hash(). This is what will be used to create a new hash for a password. It accepts three parameters, password, hashing algorithm, and options, with the first two being required. To use this function, you will do something like the following:

1
2
3
$password = 'foo';
$hash = password_hash($password,PASSWORD_BCRYPT);
//$2y$10$uOegXJ09qznQsKvPfxr61uWjpJBxVDH2KGJQVnodzjnglhs2WTwHu

You’ll notice we didn’t add any options to this hash. Available options are currently limited to cost and salt. To add options to your hash you create an associative array.

1
2
$options = [ 'cost' => 10,
             'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM) ];

By adding our options to password_hash() we can see that our hash has been changed, making it more secure.

1
2
$hash = password_hash($password,PASSWORD_BCRYPT,$options);
//$2y$10$JDJ5JDEwJDhsTHV6SGVIQuprRHZnGQsUEtlk8Iem0okH6HPyCoo22

Now that we have our hash, we can use password_get_info() to find out information about our newly created hash. password_get_info() requires one parameter, hash, and returns an associative array containing the algo, the int representation of the hashing algorithm used, the algoName, the human readable name of the hashing algorithm used, and options, the options used when creating the hash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var_dump(password_get_info($hash));
/*
array(3) {
  ["algo"]=>
  int(1)
  ["algoName"]=>
  string(6) "bcrypt"
  ["options"]=>
  array(1) {
    ["cost"]=>
    int(10)
  }
}
*/

The next function added in the Password Hashing API is password_needs_rehash(), it accepts three parameters, hash, hashing algorithm, and options, with the first two being required. The usage of password_needs_rehash() is to determine whether or not a hash was created with a specific algorithm and options. This could be useful if your database has been compromised and needs to have the hashed adjusted. By checking each hash with password_needs_rehash() we can see if the existing hash matches the new parameters, and affect only those that were created using old parameters.

Finally, now that we have created our hash, checked how it was created, and checked to see if it needed to be rehashed, we need to verify it. To verify plain text to a hash we must use the password_verify(), it requires two parameters, password and hash, and will return TRUE or FALSE. Let’s check our against our hash to verify we are correct.

1
2
3
4
$authenticate = password_verify('foo','$2y$10$JDJ5JDEwJDhsTHV6SGVIQuprRHZnGQsUEtlk8Iem0okH6HPyCoo22');
//TRUE
$authenticate = password_verify('bar','$2y$10$JDJ5JDEwJDhsTHV6SGVIQuprRHZnGQsUEtlk8Iem0okH6HPyCoo22');
//FALSE

With this knowledge you now have the power to quickly and securely create password hashes in the brand new PHP 5.5.0.

Disconnect mysql_connect

As PHP 5.5 closer to public beta and therefore public release it is time to get away from using the MySQL API to connect and interact to MySQL databases. The original MySQL API has been around since before the days of PHP 3 and quickly became the most popular API (due in no small part to it being the only API) used to interact with MySQL databases. While the original MySQL API had it’s time in the sun, it is time to put the extension out to pasture. In the upcoming PHP 5.5 release the original MySQL API will be depreciated.

At this point you are probably asking yourself, “well, if the MySQL API is depreciated, how am I supposed to connect to MySQL database?” PHP has you covered, in PHP 5.0 two new APIs have been introduced. These APIs are the mysqli API and the PDO API. Both of these new APIs are included with the standard PHP builds and are easy to learn.

The reason to step away from the original MySQL API is not only because of its impending depreciation. The original MySQL API is also much less secure than it’s alternatives. The API lacks the ability to use prepared statements which allows for easier access to the database by malicious users by way of SQL injection.

With this bit of knowledge I hope that you take the steps required to disconnect from the original MySQL APIs in PHP and move to future-ready, more secure, mysqli API and/or PDO API for future development.

Obscurity IS NOT Security

I work with a fairly large piece of software day in and day out, which will remain nameless for the time being. This software is used in medical offices across the United States and beyond, and has an annual conference in Las Vegas for it’s users to mingle and learn some tricks and tips for the software. The software allows its users, based on permission levels, to access to patient information, prescription prescribing, and other sensitive information.

To access the software the user must first enter their username and password. Unfortunately, that is about where the security mechanisms fall apart. The password is limited to 12 characters, and is case insensitive. When was the last time you had a case insensitive password? Exactly, likely never, because that is very insecure.

Continuing to dig into the security in use, I looked to the underlying SQL Server database, which contains all of the user accounts for the software. When viewing the user table I noticed that there were similarities between most of the password hashes it stored. An example of the hash is F3d2427323a202034686f736973616 which is the hash for password All of the hashed started with F and many of the hashes end with 686f736973616. This peaked my interest and had me thinking that the hash maybe had a salt added to the end of it, but, since the end of each hash didn’t all match that couldn’t have been the case.

It turns out these password hashes aren’t really hashes at all, but rather a very easily reversed algorithm based on BITWISE Comparisons. The steps to create a valid hash are as follows:

Convert the password to lowercase.
Pad the password to 12 characters by appending spaces.
XOR the encoding of the password with the encoding of: metamorphosi
XOR each resulting byte with 0x20 (the ASCII encoding of a space).
Convert the result into hexadecimal.

Using this knowledge I reversed the process using some quick PHP to dump the plain text of all the passwords stored in the database.

The results were shocking. Mainly in the fact that it was so simple to generate a list of all of the passwords, that restrict access to such a large amount of sensitive data. With the ability to convert the hash to plain text I set forth attempting to set passwords from PHP as well. At first I was finding that my hashes I was generating were matching up, but the log in attempts would fail. I couldn’t figure out what was going wrong, so I took to the SQL, I dumped the value for the passwords to their binary representation.

After looking at the output it showed that there was an un-shown character stored at the beginning of the password, specifically a horizontal tab. I reworked my code a little to account for the tab and was successful in creating a new password.

This exercise was great to point out a security flaw in a piece of software that should have maximum security. The worst part about the flaw is that the designers opted to ignore convention by using a homegrown hashing algorithm instead of using a known and accepted one way hashing algorithm like SHA-1,  MD4, or one of the many others available. I have contacted the company that develops the software, informing them that their security is far from up to par, and hopefully prod them a bit to step up their security in future releases of the software. In the event of a reply to my contact attempt I will update this post. 

Update
I have received a phone call from the software vendor in question. After being grilled as to my place of employment where I interact with their software I was told that a fix is in the works. This phone call took place on March 26, 2013, a full month after I initially contacted them about the issue. To this point, there have been no updates made to enhance the security practices of the software.

Your Pass to Passbook

Jeremy Curcio

Speaking about Passbook

Tonight I gave a talk about Passbook the monthly meetup of Baltimore Cocoa, a local group dedicated to Apple iOS and OS X developers. The talk was titled “Your Pass to Passbook” and explained what Passbook was and what it does. I explained what passes are, how they are used, and how to make them.

In case you were unable to attend, or even if you just want to look at the slides again I have included them below for your viewing and learning pleasure.

A Rant on Congruency

Yesterday I received a phone call from my supervisor informing me of an bug he found in one of the applications that I was left by a former developer. I was told the name of the application and where it happened. No mention of the error(s) noted, but that is a story for another day. So with this bug report I started to dig in to see what was happening. It turns out that using an apostrophe in a user provided field was causing issues. The errors were pointing to the SQL Server not accepting the input provided. I then took a look at the code to see how we were working with the submitted form data. I found we were ‘sanitizing’ data using the following code.

1
2
3
$Comments=str_replace("\'","''",$Comments);
$Comments=str_replace("\\\"","\"",$Comments);
$Comments=str_replace("\\\\","\\",$Comments);

So, we were looking for \', \", and \\ in the submitted data. Since the users aren’t escaping their own data (nor should they) these replaces were never happening.

Now armed with the knowledge of what was wrong, I set off to fix it. Since the rest of the code was a complete mess, much like the sample provided above, and I was on a “make this work now” deadline I went forth and just fixed the escaping of special SQL characters for now, and will go back to refactor when things slow down a little bit. The above block of code was changed to this:

1
$Comments=str_replace("'","''",$Comments);

I pushed the change to the development server and went through the reproduction steps to ensure that the change functioned as expected before moving them to the production environment. This is where things went from an eye roll to a face palm. Our development and production servers do not match up at all. The production server runs IIS 7 with PHP 5.4.0, the development server runs IIS 6.5 with PHP 5.0.4, and my local environment runs a local instance of IIS 6.5 with PHP 5.4. Upon testing on the development server things still weren’t working quite right. The data wasn’t being escaped as expected.

After checking the PHP Manual to ensure that str_replace() worked the same in 5.0.4 as it did in 5.4.0, echoing out the data submitted, and running about a half dozen different input tests, I figured it out. The development server has magic_quotes turned on in the php.ini, even though it was turned off (as it should be) on the production server.

When I started in my current position I was told that the php.ini files on the production and development servers were tuned for each server and to not touch them. I have scanned through each to see how they were ‘tuned’ (Spoiler: They aren’t) but must have missed the magic_quote being on, probably because it was appended to the end of the file, especially because they were off in their normal location in the file.

; Magic quotes for incoming GET/POST/Cookie data.
; magic_quotes_gpc = Off

I then turned magic_quotes off, by touching the php.ini I was told to not touch, and reran my fix. The SQL statement ran as expected and the new data was inserted into the database.

So the moral of my story for all the System Administrators out there: Please keep everything in sync between your environments. Server versions, PHP versions, configuration files, and anything else that is on both servers. If they do not match, then your developers will be tearing their hair out trying to figure out why code that worked on Development doesn’t work on Production and vice-versa, which then causes two versions of the code in the code base, one for each environment.