AppSec Blog

AppSec Blog

A Proposal for a PHP "UserData" Class

The title of this blog is "Application Security Street Fighting". It is based on an idea I am pursuing for a while now. The goal is to come up with a set of simple and reproducible techniques to secure applications. Personally, I favor coding in unstructured languages like Perl and PHP for all the wrong reasons: It is fast and I am able to focus on the result. For example the first version of DShield.org was created over a Thanksgiving weekend. It worked "great", crashed hard on the first Slashdotting and set the server I build for cheap on fire during the Code Red outbreak. But it survived! (The fire destroyed some of the insulation on the power supply, but amazingly the server kept on running for another two weeks until I was able to replace it. The best $400 home made server I ever had).

However, you will not find much of the original code in the DShield site of today. I probably replaced it 3 or 4 times just that first year. Each time, I learned a bit more about PHP. On the other hand, the site would probably not exist if I had done it "right" the first time. Coding slow kills momentum and opportunity.

Now how do we code fast and safe? Most developers associate secure coding with slow coding. I think there are a few misconceptions when it comes to secure coding, and I would like to address some of them in this and future blog posts. In this post, let me focus on user input validation, one of my favorite topics.

How do I validate input securely using php? For deep and complex questions like that, there is only one answer: Google it! . The first link that came back for me was a page on Techrepublic, "Secure your Web Applications by validating user input with PHP". The solution presented on this page gets some things right: It uses a PEAR library, "Validation". Less code to write, less bugs to fix! At least the way I code, reusing code works always in my favor. But let's look at the rest of the code:

extract($_POST);
// check name field
if (!$validate->string($name, array("min_length" => 1))) {
$errors[] = "Error in NAME field";
}

Now you may want to argue the use of the "extract" command, but well, this is not the point here. The problem is that you need to first pull the user submitted data out of the super global array like "$_POST", then you need to validate it. And you need to do this every single time. I can tell you, it gets boring quickly. Before too long, you will miss a spot. If you clean a kitchen floor, "missing a spot" means having a happy dog help you fix the problem later. If you miss a spot in your PHP script, you got a vulnerability! That's right: As a developer, you have to get it right every single time.

Personally, I find user input validation one of the more boring parts when coding. I would rather make sure my business logic is soundly implemented. So let me talk about a different approach I got to like lately:

  1. Start out by pulling all the user submitted data into an object.
  2. The only way for you to get to the user data is to call an "extraction" function, which will also validate the data.
For example a bit of pseudo code:
$oUserData=new UserData($_POST);
$sName=$oUserData->getName("firstname");

And this is what the class approximately would look like (pseudo code)
class UserData {
protected $aData;

function __construct($aSource) {
/* pull data out of source and assign to $aData */
/* and clear out $aSource */
}

function getName($sLabel) {
if ( is_name($this->aData[$sLabel]) ) {
return $this->aData[$sLabel];
}
return false;
}
}


Cool. So now we got a very simple mechanism to extract validated user data. As a developer, I need to write the validation functions only once. The constructor for the class should also clear out the initial unvalidated userdata to avoid accidents down the line.

I will expand on this idea in future posts. Again: The idea is to write secure code without getting lost in endless and boring input validation exercises. That's what I consider "application security street fighting". It's not pretty, its not fancy. But it works. We need to find simple and repeatable techniques that work every time.

5 Comments

Posted May 22, 2009 at 5:14 PM | Permalink | Reply

Nathan Christiansen

Interesting Concept, not unlike what I have tried to do in my own code (Java). I did not encapsulate the functions into an object per-se.

Still with this approach, you still need to use the object/class to retrieve the data every time, or your input is not filtered.

The best approach may be to extend the actual object or structure that contains the user input. (The $ARGS hash in PERL, the $_POST hash in PHP, the HttpServletRequest object in Java.) I am not a PHP guy so I don't know if you can do this in PHP, but in PERL you can create a blessed reference to a Hash and add subroutines to it to extract the information you need. In Java it is a simple subclass that can hide the implementation of the standard getters of the superclass.

Posted May 22, 2009 at 5:41 PM | Permalink | Reply

Johannes Ullrich

The constructor of the 'userdata' class will erase $_POST to eliminate mistakes. $_POST (and similar "super globals" in PHP) are not extensible as far as I know. But that would be even better.

Thanks for the feedback!

Posted May 27, 2009 at 12:13 PM | Permalink | Reply

Carmady

As a useful port of call for people interested in this, http://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project and http://htmlpurifier.org/ might be worth a visit. http://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API#tab=PHP too.

Posted May 27, 2009 at 9:18 PM | Permalink | Reply

markez linda

I really liked your blog!

Posted May 28, 2009 at 2:08 AM | Permalink | Reply

ApplyCreditCards

Hi, cool post. I have been wondering about this topic,so thanks for writing.

Post a Comment






Captcha

* Indicates a required field.