About the Author

Chris Shiflett

Hi, I’m Chris: entrepreneur, community leader, husband, and father. I live and work in Boulder, CO.


All posts for Jan 2006

PHP Security and SABSA

Andrew van der Stock has started providing more details about a proposed security architecture for PHP, beginning with the SABSA (Sherwood Applied Business Security Architecture) approach. This approach is broken down into layers:

  • Contextual
  • Conceptual
  • Logical
  • Physical
  • Component

He describes each of these layers and how they relate to PHP, and he also hints that more details are coming:

In the next installment, I'll start enumerating the current risks and identifying business drivers.

PHP Security Architecture

Andrew van der Stock wrote to let me know that he has posted a contextual overview of a security architecture for PHP. I think he clarifies many of the things he mentioned in his previous post, and he makes a statement that has been a guiding principle for me in my work on the Zend Framework:

Of course, it is possible to write insecure programs in any language if you try hard enough. What I want is the easiest way is also the safest way.

I'm really glad to hear Andrew make this statement, because I think it's a simple but important goal - make the easiest way the safest way. For example, I wrote recently about The addslashes() Versus mysql_real_escape_string() Debate. Which of those is easiest to type? Which is safest? When you want to output a username to the screen, is it easier to escape it with htmlentities() or just echo it and be done? We have some work to do.

One aspect of this discussion that has been heavily debated within the PHP community is whether PHP should provide a powerful and flexible foundation like C does, or whether it should behave more like a framework. For example, when the topic of XSS comes up, many people blame PHP for not doing something automatically such as removing specific characters or escaping. Others note that almost any PHP framework offers such protection, and they'd rather see PHP remain a foundation from which to build.

Not being a PHP core developer myself, I'm focusing my efforts on the framework side of things. However, I have high hopes for Andrew's influence, and it sounds like he's in touch with Rasmus:

I have a reply from Rasmus. Apparently, he saw Chris's blog and thus this rant, and replied.

Andrew's "Failure of Leadership" comment probably won't win him any brownie points, but at least he got some attention. :-)

Test::Simple for PHP

Via PHPDeveloper.org, I just read a post on PhpGirl that discusses a familiar topic, testing:

I'll write a Test::Simple for PHP. Yes, I know there exists one already that uses the power of Perl to test PHP files, but I didn't have time to figure out how to set that up and probably won't be able to use Perl anyways on the production system.

A few years ago, Geoff Young and I gave a talk called Testing PHP with Perl. We thought we were being funny (in our defense, those who listened to the talk seemed to agree), but I think all we did is make our project seem inaccessible to PHP developers. Perl is scary. :-)

Part of our project is a pure PHP implementation of Test::More. If you want to really keep things dirt simple (which seems to be Nola's goal), you can use it by itself with no framework, but more on that in a minute.

In a follow-up post, Nola describes how she uses her simple testing library. The first argument to ok() is a boolean that indicates whether the test passes. She demonstrates some tests using conditionals that compare two values expected to be equal:

<?php 
 
$t->ok($user->getRealName() == 'John Doe Test', 'get RealName'); 
$t->ok($user->getUserName() == 'jdoe', 'get UserName'); 
$t->ok($user->getEmail() == 'john@doe.com', 'get Email'); 
$t->ok($user->getPermission() == 1, 'get Permission'); 
 
?>

She also demonstrates some tests using conditionals that compare two values expected to not be equal:

<?php 
 
$t->ok($user->getRealName() != 'Susie Doe', 'Not Realname Suzie Doe'); 
$t->ok($user->getUserName() != 'sdoe', 'Not Username sdoe'); 
$t->ok($user->getEmail() != 'suz@doe.com', 'Not email suz@doe.com'); 
$t->ok($user->getPermission() != 0, 'Not Permission 0'); 
 
?>

You can do the same sort of thing with Testmore:

<?php 
 
include './testmore.php'; 
include './userclass.php'; 
 
plan(8); 
 
ok($user->getRealName() == 'John Doe Test', 'get RealName'); 
ok($user->getUserName() == 'jdoe', 'get UserName'); 
ok($user->getEmail() == 'john@doe.com', 'get Email'); 
ok($user->getPermission() == 1, 'get Permission'); 
 
ok($user->getRealName() != 'Susie Doe', 'Not Realname Suzie Doe'); 
ok($user->getUserName() != 'sdoe', 'Not Username sdoe'); 
ok($user->getEmail() != 'suz@doe.com', 'Not email suz@doe.com'); 
ok($user->getPermission() != 0, 'Not Permission 0'); 
 
?>

I created a simple userclass.php file to implement the methods she uses:

<?php 
 
class user 
{ 
    public function getRealName() { return 'John Doe Test'; } 
    public function getUserName() { return 'jdoe'; } 
    public function getEmail() { return 'john@doe.com'; } 
    public function getPermission() { return 1; } 
} 
 
$user = new user; 
 
?>

If you just run this PHP script, you'll see the raw TAP output:

1..8
ok 1 - get RealName
ok 2 - get UserName
ok 3 - get Email
ok 4 - get Permission
ok 5 - Not Realname Suzie Doe
ok 6 - Not Username sdoe
ok 7 - Not email suz@doe.com
ok 8 - Not Permission 0

If a test fails, the last line lets you know about it (in addition to one of the previous lines being not ok instead of ok):

# Looks like you failed 1 tests of 8.

So, even without a testing framework, you can use Testmore as a simple testing tool. If you want to try it yourself, you can download Apache-Test (it's bundled with the distribution) or grab it from GitHub.

Using Test::Harness to Test PHP Applications, a talk being given at PHP Québec, is supposed to cover this same topic.

Secure Logins

I use Yahoo for a few of their services. As Aaron notes, Yahoo makes you log in excessively. This is a bit annoying, especially since each login usually requires multiple clicks for me - I always choose the secure option, because it submits the form over SSL, and this isn't the default. (If my wife has been using the computer, it usually also means that I have to log her out first, but that's another story.)

Recently, Yahoo removed the secure option:

If you read the fine print, however, you'll see "Submits over SSL." The problem is that Yahoo has focused too much on the technical issues and not enough on the social ones. The average user looks for the lock icon when entering sensitive data into a form. Although it's not required that the login form itself be sent over a secure connection, the average user doesn't know this.

If you view source (which is the only way to verify Yahoo's claim prior to submitting the form), you'll see that they're telling the truth:

<form method="post" action="https://login.yahoo.com/config/login?" ...>

Wouldn't it be nice if browsers could give us a visual indication that a form's action uses the https scheme? Imagine a cursor with a lock icon beside it:

Anyone want to write a Firefox plugin? :-)

PHP Insecurity

Andrew van der Stock has written a strong criticism of PHP's insecurity. Andrew is a seasoned security expert and a major contributor to OWASP, and he states:

After writing PHP forum software for three years now, I've come to the conclusion that it is basically impossible for normal programmers to write secure PHP code. It takes far too much effort.

He continues, citing specific areas where he thinks PHP is weak and asserting that "PHP must now mature and take on a proper security architecture."

Many of the insecure features he cites (register_globals, magic_quotes_gpc, and safe_mode) are slated to be removed in PHP 6, but his core complaint seems to revolve around the fact that PHP makes too much power too easily accessible, often granting developers more power and flexibility than they realize (e.g., wrappers).

Aside from minor language features like taint mode, I don't see what other platforms offer to help prevent inexperienced developers from writing insecure code. Anyone care to enlighten me? :-)

addslashes() Versus mysql_real_escape_string()

Last month, I discussed Google's XSS Vulnerability and provided an example that demonstrates it. I was hoping to highlight why character encoding consistency is important, but apparently the addslashes() versus mysql_real_escape_string() debate continues. Demonstrating Google's XSS vulnerability is pretty easy. Demonstrating an SQL injection attack that is immune to addslashes() is a bit more involved, but still pretty straightforward.

In GBK, 0xbf27 is not a valid multi-byte character, but 0xbf5c is. Interpreted as single-byte characters, 0xbf27 is 0xbf (¿) followed by 0x27 ('), and 0xbf5c is 0xbf (¿) followed by 0x5c (\).

How does this help? If I want to attempt an SQL injection attack against a MySQL database, having single quotes escaped with a backslash is a bummer. If you're using addslashes(), however, I'm in luck. All I need to do is inject something like 0xbf27, and addslashes() modifies this to become 0xbf5c27, a valid multi-byte character followed by a single quote. In other words, I can successfully inject a single quote despite your escaping. That's because 0xbf5c is interpreted as a single character, not two. Oops, there goes the backslash.

I'm going to use MySQL 5.0 and PHP's mysqli extension for this demonstration. If you want to try this yourself, make sure you're using GBK. I just changed /etc/my.cnf, but that's because I'm testing locally:

[client]
default-character-set=GBK

Create a table called users:

CREATE TABLE users (
    username VARCHAR(32) CHARACTER SET GBK,
    password VARCHAR(32) CHARACTER SET GBK,
    PRIMARY KEY (username)
);

The following script mimics a situation where only addslashes() (or magic_quotes_gpc) is used to escape the data being used in a query:

<?php
 
$mysql = array();
 
$db = mysqli_init();
$db->real_connect('localhost', 'myuser', 'mypass', 'mydb');
 
/* SQL Injection Example */
$_POST['username'] = chr(0xbf) .
                     chr(0x27) .
                     ' OR username = username /*';
$_POST['password'] = 'guess';
 
$mysql['username'] = addslashes($_POST['username']);
$mysql['password'] = addslashes($_POST['password']);
 
$sql = "SELECT *
        FROM   users
        WHERE  username = '{$mysql['username']}'
        AND    password = '{$mysql['password']}'";
 
$result = $db->query($sql);
 
if ($result->num_rows) {
    /* Success */
} else {
    /* Failure */
}
 
?>

Despite the use of addslashes(), I'm able to log in successfully without knowing a valid username or password. I can simply exploit the SQL injection vulnerability.

To avoid this type of vulnerability, use mysql_real_escape_string(), prepared statements, or any of the major database abstraction libraries.

This type of attack is possible with any character encoding where there is a valid multi-byte character that ends in 0x5c, because addslashes() can be tricked into creating a valid multi-byte character instead of escaping the single quote that follows. UTF-8 does not fit this description.

Technical Vocabulary and Grammar

I sometimes wonder why people feel so compelled to use technical terms when talking about computers, even when they don't know what the terms mean. In my experience, those who know the least about a particular topic use the most complicated vocabulary when discussing it. I considered compiling a list of the popular ones, but since I'm lazy and have a blog, I decided to blog about it instead. :-) Feel free to add to the list.

For some reason, there are multiple terms used for a computer. What's wrong with computer? I guess it doesn't sound cool enough, but drives and processors do. For the record:

  • Hard Drive != Computer
  • CPU != Computer

I'm sure this list could go on, but those are the two I see misused all the time. To me, they're just important computer parts.

Another problem is when technical terms closely resemble other, more common words. For example, have you ever had someone try to discuss object-orientated programming or tell you that a feature has been depreciated? I have. For the record:

  • Orientated != Oriented
  • Depreciated != Deprecated

(Spell checkers are partially to blame for these, because I think many people rely on them to determine when they've chosen the right combination of characters.)

I'm no grammar expert, so I'm sure I make my share of mistakes. Sometimes, what's considered correct just doesn't sound right. For example, why must companies be considered plural? When I think about a company, I always use a singular verb:

I wonder what Brain Bulb is up to these days.

Technically, I think this is wrong (anyone know for sure?), but I just can't bring myself to use a plural verb:

I wonder what Brain Bulb are up to these days.

Doesn't that sound weird? Another one is data, the plural of datum:

I'm going to store those data in MySQL.

I can never bring myself to say that, and it has nothing to do with my database preference. :-) Luckily, treating data as a singular noun appears to be gaining acceptance, according to a usage note:

Sixty percent of the Usage Panel accepts the use of data with a singular verb and pronoun in the sentence Once the data is in, we can begin to analyze it.

I'm not sure what the Usage Panel is, but it sounds important.

Another one that really bugs me is the way quotes are handled in the US:

"I think our quoting rules are dumb," Chris thinks to himself.

For whatever reason, it's required that the comma be within the quotes there, and this complete lack of precision bugs me, especially when writing about technical topics (where precision is important). The Jargon File agrees:

Then delete a line from the file by typing "dd."

In a vi tutorial, the period is actually misleading, because "dd." will delete a line and then repeat the last command, deleting two lines. The ambiguity caused by the lack of precision required by US grammatical rules can be very misleading. Is it better to be right or be clear? I usually choose clarity, but that's just me.

Pro PHP Podcast

You've probably heard the good news about the Pro PHP Podcast. The guys behind the show (Marcus Whitney and Chris Cornutt) are joining forces with php|architect in what should be a good thing for all of us.

A few months ago, Marcus and I tried to record a second episode of Ask Chris on multiple occasions, but technical difficulties prevented us from getting the job done. Marcus seemed discouraged by all of the trouble he was having with the various software involved, and the podcast was losing steam.

So, I was very happy to hear about the partnership with php|architect, because I know this will let Marcus focus on the show. There are also regular newscasts planned, and Chris is asking, What do you want out of your news?

The first show under the new partnership is an interview with Andi Gutmans scheduled for 27 Jan 2006. If you want to participate in the live broadcast, sign up here.

2005 Highlights

In the tradition of my 2003 and 2004 highlights, I'm posting my personal highlights of 2005. As in years past, this is mainly for my own benefit. I hope everyone has a wonderful 2006. :-)

I'm also starting a new tradition by mentioning a few goals for the upcoming year. The guiding theme is going to be:

Work smarter, not harder.

Here's hoping I can apply that to my life.

  • Speak at fewer conferences.

    I love conferences. I try to speak at several conferences each year, because I enjoy contributing something back to the community. However, the time required for preparation and travel make it difficult to do much else. In 2006, I want to increase my contributions in other areas, so I need to speak at fewer conferences.

  • Contribute more to open source.

    My contributions to the open source community generally revolve around education. I love to teach (Teach a Man to Fish), and I try to do so by answering questions on mailing lists and forums, writing articles, writing books, and speaking at conferences. However, I love programming even more, and I don't get to do that as much as I would like. In 2006, I want to contribute more code to the open source community. I pointed myself in the right direction by getting involved in the Zend Framework, and I plan to make my next PHP Security Consortium project an open source tool.

  • Do more cool stuff.

    Working on Ning was pretty fun, and it made me realize that I don't get to work on enough cool stuff for my liking. In 2006, I want to do more cool stuff, and my first cool project is already underway. More on that soon. :-)

  • Blog more.

    My blog has become more popular than I ever thought it would (possibly due in part to the popularity of Planet PHP and Planet MySQL). I think that's very cool, and I want to thank those who read my blog by offering more (and better) content in 2006.

  • Make Brain Bulb even better.

    Although it took me almost all of 2005 to transition my freelance career into a consulting company, Brain Bulb is everything I wanted it to be. In 2006, I want to offer better PHP security audits and PHP training courses for less. I also want to begin offering additional products and services.

Bye bye 2005, and welcome 2006!