PHP

Introspection, Growth and Passion

Having a moment of introspection this morning, thinking back over the years of how my work has changed – sometimes in pretty dramatic ways. It seems like forever ago that I was fresh out of school and working my first real programming job at a domain host. I worked hard until I was ultimately let go from the role due to some interpersonal issues. Fortunately, the market was good and I found a new role with a natural gas provider relatively quickly. I did a lot of growing there, not only in my skills but just in my understanding of how business gets done. It was while I was there that I got married and soon had to figure out how to juggle work and kids, finally getting it down about the time the second one came around.

All the while, I was still working on my passion – programming and learning how to make “better” applications. I think at the time I didn’t know what “better” meant in the context of PHP applications but I spent a lot of time reading up on the subject and, yes, attending conferences (my first was php|tropics which I still can’t believe my employer paid for to this day). I made friends in the community, both local and national – even some international – that helped me build my skills. They were there when I had questions about how to create something and regularly had books, blog posts and other recommendations for resources to further my understanding of what “better” meant. I was constantly improving and moving up the ranks from junior developer to senior developer then lead developer and, yes, even a manager of a development team (it was weird).

Fast forward a few years to about five years ago. I sat back and looked over my career so far. I really looked at the work that I’d accomplished over the years, how I’d grown in my understanding of what “good code” and well-structured applications meant. I understood some of the higher level development concepts (like SOLID) and how to effectively apply them in my day to day work. I was co-organizaing the local PHP meetup, had started sharing my knowledge at conferences and through books and several articles on a wide range of topics. But I’d hit a problem that Young Me hadn’t thought was possible: I felt like I was stagnating.

I looked at the work I was doing (a security company but doing PHP development, not application security) and, while I was enjoying it and the people I was working with, there was something nagging in the back of my mind. It wondered if this was where things leveled out and the only way up was to a less technical role. I’d always been driven by the tech and exploration, so at the time that was a non-starter. I needed to find something that would fill my need for more tech and more exploration but I didn’t know exactly what.

I looked around at the work I was doing and the industry I was in and realized what I needed. I needed to specialize. I needed new challenges that both appealed to my desire to stay in the tech of things yet provided me with room to explore other things. I’d always had a passion for security (as anyone that knows me can tell you) so it seemed like a good option. I started to do more research and learn everything I could about the current state of application security. I’d had a cursory knowledge of it in the past but I really doubled down, watching recorded talks, reading tons of articles and even giving/writing some of my own (the best way to learn is to teach, right?).

So this was my first pivot. After I muddled through one role that didn’t turn out to be what I was hired to do, I ended up landing an application security job at a larger company. The group I worked for was a smaller acquisition of this company so it still had that “small company” atmosphere. I was still learning as much as I could and was being challenged daily to put this knowledge to the test. I worked with a great team of other security folks and engineering groups in a culture of mutual respect and growth. Unfortunately, some things changed with that role and I ended up leaving, going to my second position as an Application Security Engineer. I wasn’t doing as much development work as I had in the past outside of building some custom testing tooling, but I spent time outside of work scratching that itch.

I’ve been at my current role for over a year now and, while the work is interesting and I am working with a wide variety of tech and learning something new just about every day, I’m starting to feel that same nagging feeling in the back of my head. When I sit down and actually think about what that voice might be telling me, it’s an interesting story. I look back at how I pivoted before. I made use of my years of development background and turned it on its head, focusing on how to use it to understand the structure of applications and how to best work with development teams to improve their overall security.

One of the things that appealed to me the most about the role I’m in is the training program. There was already a program in place, started a year or so before I began there, to internally teach the development groups about application security-related topics. At this point I’d been a speaker and a “teacher” for years in various ways: conference presentations, mentorships, and writing plenty of tutorials and blog posts. I’ve always been excited to share my knowledge with others and delight in seeing that lightbulb go on behind their eyes when they really “get” a concept. I was excited to be able to be a part of that program. I presented the current courses numerous times and even worked up a new “advanced” full-day training to provide even more of an in-depth look at application security for our Engineering staff.

Some things have changed, however, and the team I’m on won’t be involved in the training program as much as before and I’d be lying if I said I wasn’t disappointed. There’s some additional context needed here that might help you understand why this is difficult for me. It has to do with that little voice again. See, a few months back, my excitement about the AppSec training program was really ramping up. I’d given the new course several times and had worked on efforts to help improve the program and processes around it. The excitement was so much so that I finally figured out what that voice was talking about and I applied to graduate school – and was accepted – at the University of Massachusetts (Boston) for a certificate in Instructional Technology Design, focusing on using technology to improve the learning process and experience. It was only after this, however, that things changed in my role and my team was less involved in the program. I won’t get too into it here but you can understand my disappointment. I’d figured out the next pivot that voice was urging on: taking the development background, combining it with the application security perspective and sharing that with others in an interesting, relevant, and effective way.

Being on a different team hasn’t stopped me, though. I still find places to help out where I can and try to make some kind of impact on the program when possible, it’s just not a direct influence. I don’t want all of this to come off as complaining. Despite what my current role’s focus might be, I’m still pushing on, learning as much as I can about learning and development, even if it’s just to apply it to my next conference talk or potential online training sessions. I feel the drive to learn again and it’s refreshing. It has already filled in some blanks for me that I was missing in my own instructional methods and has given me countless more to explore. I’m excited to see where this all will lead me.

I wanted to share my story here, not because I feel like it’s important or that it’s any kind of amazing. I wanted to share it for those out there that might have that little same voice inside their heads wondering “what’s next”. I share it because I want to show that it’s not always about becoming the “best of the best” in a single kind of role. As the saying goes: if you’re the smartest person in the room, you’re in the wrong room. It’s scary to think about change, especially in the tech world where change doesn’t always go so well and things can be unpredictable. Don’t be afraid to take a step back and look at what you’ve accomplished and where you’re headed. Make sure it’s what you want and really think about your future.

I look back on my over almost 20 years of work in technology and think about how far I’ve come in that time. I think about the “what if” of having stayed in that same role I was in years ago and where I’d be now and, honestly, I wouldn’t trade the experience and changes my career has gone through for anything. It has helped me become the person I am and has helped me find my passions along the way and, even now, is driving me on to learn more and grow. I hope that you can find the same kind of excitement in your work and can find what you’re passionate about, regardless of your current role and, most importantly, you don’t ignore that inner voice that could be guiding you towards something where you’ll find joy.

Advertisement

Preparing for Pentesting (@ Longhorn PHP 2018)

At this year’s Longhorn PHP conference I’ll be presenting two talks: an updated version of my “Securing Legacy Applications” session and something new and a bit different for a conference primarily aimed at development topics. I’ll be giving a tutorial on the first day (April 19th) about penetration testing. For those not familiar with the topic, penetration testing is a common security practice where you make attempts to locate the flaws in an application, usually without knowledge of the code running underneath.

For a group that’s primarily focused on “building” rather than “breaking” it might be a bit of a mind shift but I hope to at least provide my attendees with the basic concepts and tools to try it out on their own applications. There have been several sessions recently that focus on securing the code but that’s only half of the equation.

So, if you’re going to be attending my tutorial, here are a few things that can help you hit the ground running when we start. There’ll be a brief introduction to some of the basic application security concepts but we’re not going to dive too deep into those. Instead, you’ll be attacking a series of challenges I’ve created to teach the basics.

Here’s how to prepare:

– Go over the OWASP Top 10 to be familiar with the common vulnerability types (hint: several are in the challenges)
– Grab the Community Edition of the PortSwigger Burp Suite tool. We’ll be using this to help solve some of the challenges
– Check out the PHP security cheat sheet, some of the top PHP security issues and this guide to building secure PHP applications

Don’t worry if you’re not a PHP security pro – that kind of knowledge isn’t required here. The topics we’ll cover are more from the security testing side and, as an added bonus can be used on any kind of web-based application – not just PHP ones!

I hope to see you on Thursday morning – we’re going to have some fun!

Saying Thanks – Open Source Appreciation

Wow, it has been a really long time since I’ve posted here. Most of my writing has ended up in articles of php[architect] or over on Websec.io. I wanted to jump back into the blog though and talk about something inspired by a post over on the Symfony blog about giving thanks.

Normally the Thanksgiving holiday is more associated with sharing what you’re thankful for in your life. However, the Christmas holiday comes at a perfect time to look back over the past year and think about everything you’re thankful for and how your life has changed, hopefully for the better. In the Symfony blog post they share a Composer plugin – Thanks – that makes it simple to show your appreciation to those packages you’re currently using in your applications. It sends stars to the projects (the ones you haven’t already starred naturally) as a token of appreciation. This is a great first step to showing how much you appreciate the work the maintainers have done but there’s also other ways to show that you support them and that they’re doing a great job. Here’s a few other suggestions:

  • Find their email (often in the repo’s README.md file) and send them a quick note telling them how much you enjoy using the library and how important it is to your application.
  • Write a blog post about the package and how you use it to share with others. Maintainers always enjoy seeing how their work is used and maybe even get ideas for future features and fixes.
  • Send out a Tweet about the project, telling them how much you appreciate the work they do.
  • Support them on Patreon if they have a page on there with a recurring donation. This allows them to spend more time focusing on the project and making it better for everyone.
  • Open an issue on the project’s Github/Bitbucket repository with a quick “Thanks” to everyone involved.

These are just a few ideas to get you started, of course. There’s plenty of other ways that you can support and thank the authors and maintainers of your favorite packages. Get creative and think of your own but this is the perfect time of year to do it and let those developers know their work is appreciated!

Protecting your application with PropAuth (Property-based Policy evaluation)

Library: PropAuth (Property-based policy evaluation)

I’ve been working on a library for a while now that kind of distills down some of the ideas of property-based authorization (like XACML) and makes it a bit more accessible to the average developer. Property-based evaluation can be a little tricky to get your head around if you’re used to the usual RBAC world. Let me introduce it briefly.

Property-based evaluation is more or less what it sounds like: a system checks the properties of an object (or objects) and looks for different kinds of matches. That much is pretty simple but then you get into the “policies” aspect. This is where the real power comes in. With policies you can define the pass/fail requirements for the checks against an object and see if there’s a good enough match. With something like XACML it gets pretty complicated as it defines policies with XML documents (and we all know how “simple” XML is). There’s all sorts of different combining algorithms for the results like “first wins” or “all must match”. These can, of course, be nested and combined themselves leading to pretty complex policies and a mess if you’re not careful.

So, back to PropAuth now. In the work that I’ve been doing I’ve only really seen the need for a more streamlined version of this kind of evaluation. Some of the overall flexibility that XACML provides hasn’t been included in PropAuth, but I haven’t found much of a need for that so far anyway (like nested policies). The PropAuth library provides some of the basic property evaluation handling and policy creation I think could replace a lot of the mish-mash of role-based access control functionality out there and make for much more reusable code.

First off, to install just use Composer:

composer require psecio/propauth

And here’s a simple example of a policy evaluation:

<?php
require_once 'vendor/autoload.php';

$enforcer = new \Psecio\PropAuth\Enforcer();
$myUser = (object)[
    'username' => 'ccornutt'
];

$myPolicy = new \Psecio\PropAuth\Policy();
$myPolicy->hasUsername('ccornutt');

echo 'Result: '.var_export($enforcer->evaluate($myUser, $myPolicy), true);
?>

Here’s a quick summary of what’s happening here: the Enforcer object is the “frontend” that handles most of the work. You pass in a subject for the evaluation and the policy to evaluate against. In this case I’ve used the “hasUsername” check to look at the “username” property on the object and check to see if it matches the “ccornutt” value. The “evaluate” method is then called and a true/false result is returned…in this case true as our “myUser” object has a matching username.

This only scratches the surface of what the PropAuth library can do but it gives you an idea of how the evaluations are set up.

There’s also a simplified interface you can use with the same library to perform an authentication of a user with a system that uses bcrypted passwords (like with the password hashing API):

<?php
require_once 'vendor/autoload.php';

$password = $_POST['password'];

$myUser = (object)[
    'username' => 'ccornutt',
    'password' => password_hash('test1234', PASSWORD_DEFAULT)
];

$gate = new \Psecio\PropAuth\Gateway($myUser);
$subject = $gate->authenticate($password);
?>

If the password matches, you’ll be given an authenticated version of the “subject” back from the “authenticate” call. If not, you’ll get a false back on failure. Naturally, since this is all powered by the same library, you can also throw in policy checks too (warning: a bit more complicated example here):

<?php
require_once 'vendor/autoload.php';

$password = $_POST['password'];

$myUser = (object)[
    'username' => 'ccornutt',
    'password' => password_hash('test1234', PASSWORD_DEFAULT),
    'groups' => ['group1']
];

$policy = Policy::instance()->hasGroups(['group1', 'group2'], Policy::ANY);
$context = new Context([
    'policies' => PolicySet::instance()->add('policy1', $policy)
]);

$gate = new Gateway($myUser, $context);
if ($gate->authenticate($password) !== false && $gate->can('policy1')) {
    echo "They're authenticated and they have one of the required groups in the policy!";
}

?>

There’s a lot more going on here with a Policy Set and some of the “instance” calls but it’s all explained in the PropAuth documentation. I’d be interested in your feedback on the library and if you think it might be useful in your apps.

I’ve also put together a Provider for Laravel 5 applications that makes it simpler to incorporate the checks into both the controllers and your Blade templates, evaluating the policies directly.

There’s also a bit more detailed tutorial on using PropAuth over on the websec.io site with more information.

Custom Callbacks with Invoke

In putting the Invoke library to use I noticed something. While I could tell it to check for groups and permissions on the current user and limit HTTP methods on the request, there were more complex things I needed to check that weren’t part of these defaults. Now, I could just extend invoke to include match types for everything I needed (injecting a custom match class based on my needs) but I wanted something a bit more generic that I could use to call my own logic and return the pass/fail result.

So, I added in the “object.callback” match type that allows you to call a static method in your own code and perform the evaluation yourself. Here’s how it works. Say you have this configuration in your routes.yml file:

/foo:
  protected: on
  callback: \App\MyUser::test

This tells Invoke that when the user requests the /foo URL, the protection should kick in. It then goes into the checks portion of the process. This sees the special callback option and looks the class and method to call. In this case, we’ve told it to try calling the test method \App\MyUser. This class needs to be autoloadable so that Invoke can directly call it and its static method. Yep, that’s right – it needs to be a static method but you’ll be provided with everything about the request in the incoming $data variable. Here’s what the method should look like:

public static function test(\Psecio\Invoke\Data $data)
{
  /* perform your evaluation here and return a boolean */
}

In the $data variable there, you’ll have access to the context of the application via some object properties:

  • user: The current InvokeUser instance (ideally where your user lies too)
  • resource: The resource that was requested (includes access to the requested URI)
  • route: This is the route match from Invoke’s configuration the current request matches. This contains the route regex match, the configuration options and any additional parameters passed along

For example, say you needed to get the parameters from the request to do further evaluation. You could fetch them through $data->resource->getParams() and get the associative array back.

Adding these callbacks makes the Invoke system a lot more flexible and allows you to create those custom match types without having to have whole other classes just to perform your checks.

Laravel Route Protection with Invoke

I started on a tool a while back to “scratch an itch” in a personal project to make it easier to protect endpoints based on the requested URL. The Invoke library makes it possible to detect the route requested and ensure a set of criteria are met to be sure a user can access a resource. This isn’t anything new or revolutionary, but it is something I couldn’t find separate and effectively decoupled from other tools. It’s loosely based on how Symfony (v1) does it’s route protection, right down to the .yaml file that it uses for configuration. In my case, I was using it in a Slim framework-based application to evaluate the current user to see if they had the required groups and permissions.

More recently, though, I’ve been messing with Laravel and since they’ve been putting a heavy emphasis on middleware, I thought I’d see how tough an integration might be. I wanted to use Invoke to check my Laravel user to see if they met my requirements. Fortunately, it turned out to be super easy.

Here’s how I did it – hopefully it can be useful for you. I’ll provide one caveat though: Laravel’s default auth handling only sets up users, not groups/permissions, so you’ll need a way to manage those but that’s outside the scope of this. You’ll see how it integrates in a bit.

First off, we need to get Invoke installed via Composer:

composer require psecio/invoke

Once that’s installed, we need to set up our middleware. This will go in with the rest of the default middleware in the app/Http/Middleware folder in your application. Create a file called InvokeMiddleware.php with this code:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth as Auth;

class InvokeMiddleware
{
    /**
     * Handle an incoming request and validate against Invoke rules
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $en = new \Psecio\Invoke\Enforcer(app_path().'/../config/routes.yml');
        $user = Auth::user();

        $allowed = $en->isAuthorized(
            new \App\InvokeUser($user),
            new \Psecio\Invoke\Resource($request->path())
        );

        if ($allowed !== true) {
            return response('Unauthorized.', 401);
        }

        return $next($request);
    }
}

You’ll see there’s a reference to an InvokeUser class in there. Let’s make that next. In app/InvokeUser.php put this code:

<?php

namespace App;

class InvokeUser implements \Psecio\Invoke\UserInterface
{
	private $user;

	public function __construct($user)
	{
		$this->user = $user;
	}

	public function getGroups()
	{
		// This is where you fetch groups
		return [];
	}

	public function getPermissions()
	{
		// This is where you fetch permissions
		return [];
	}

	public function isAuthed()
	{
		return ($this->user !== null);
	}

}

Then, to turn it on, edit your app/Http/Kernel.php class and add this to the list of $middleware:

\App\Http\Middleware\InvokeMiddleware::class,

Viola, you’re set to go using Invoke. Now, the next step is to define your rules. You’ll notice in the middleware above we’re loading the config/routes.yml configuration file for our rules. Let’s make one of those with a super simple example. In app/config/routes.yml put:

/:
  protected: on

This configuration is telling Invoke that, when you hit the base URL of your application (“/”) it’s protected. This means that it requires a logged in user. If you’ve just added this to your application and try to load the main page without a user, you’ll be given the unhappy “Forbidden” message instead of your lovely site. It’s the check in InvokeUser::isAuthed that evaluates for this, checking to see if the user is null (no valid logged in user).

That’s it…it’s a pretty simple integration to get just get bare minimum up and running. If you’re interested in how to add group and permission checking to this, forge ahead and keep reading.

So we have our basic yaml configuration file with protection turned on. Say we wanted to add in group and permission checks too. I’ve already talked some about this kind of handling in a different post but I’ve more recently simplified it even more, no longer requiring extra classes in the mix.

Let’s start by changing our configuration file to tell Invoke that we want to be sure the user is in the “admin” group and has a permission of “delete_user” to access the /admin/user/delete resource:

/admin/user/delete:
  protected: on
  groups: [admin]
  permissions: [delete_user]

When you fire off the page request for that URL, Invoke will try to call the InvokeUser::getGroups and InvokeUser::getPermissions methods to return the user’s current permission set. Before it required you to use classes that implemented the InvokeGroup and InvokePermission interfaces for each group/permission. I streamlined this since it’s really only evaluating string matches and allowed those methods to either return a set of objects or of strings. Let’s update the InvokeUser class to hard-code in some groups/permissions for return:

<?php

namespace App;

class InvokeUser implements \Psecio\Invoke\UserInterface
{
        /** ...more code... */

	public function getGroups()
	{
		return ['admin','froods'];
	}

	public function getPermissions()
	{
		return ['delete_user','view_user','update_user'];
	}
        /** ...more code... */
}

Ideally you’d be fetching these groups and permissions from some role-based access control system (maybe, say Gatekeeper) and returning real values. These hard-coded values will work for now.

Since the user has all the requirements, Invoke is happy and they’re able to move along and delete all the users they want.

I’ve tried to keep the class as simple as possible to use and I’m definitely open to suggestions. There’s a few additions I’d though about including adding HTTP method matching (different rules for POST than GET) and other match types than just groups and permissions. Let me know if you’d like to see something else included in Invoke – I’d love to chat!

Why Drupal’s Bug Bounty is Important

The Drupal project has just announced a bug bounty program where they’re offering sums between $50-1000 USD for anyone who finds and reports a security issue with Drupal 8:

Drupal 8 is nearing release, and with all the big architectural changes it brings, we want to ensure D8 upholds the same level of security as our previous releases. That’s where you come in!

The security team is using monies from the D8 Accelerate fund to pay for valid security issues found in Drupal 8, from now until August 31, 2015 (open to extension). This program is open for participation by anyone.

One thing to note, they’re only looking for Drupal 8 issues here, not problems in past editions (I’m sure they’d still appreciate them being reported though). There’s some stipulations they list where the vulnerability doesn’t count including someone with Administer level access and several other very specific kinds of issues. I’m assuming they’ve already run some pretty extensive testing on those, though, otherwise they would’ve been included in the list of allowed vulnerabilities.

A mention of the bug bounty was posted over on the /r/php subreddit earlier and there’s already some good feedback about it. There’s two points that I want to touch on as to why Drupal announcing this bounty is a major and important thing for the entire PHP community, not just Drupal.

First off, it sends a message to the wider world of developers that it’s time to take (PHP) security seriously. PHP’s had a less than stellar reputation when it comes to security. Fortunately it seems like things are getting better and more developers are working towards building secure applications. Security is a hot topic everywhere, not just in development communities and it’s starting to rub off on PHP devs. This bold move from the Drupal organization takes that up to the next level. It’s essentially telling everyone that uses Drupal or has any kind of contact with it, that they’re taking the security of their systems seriously and are “putting their money where their mouth is” to encourage as much participation as possible.

Bold moves like this are what get people’s attention too, even people not in the PHP community. Bug bounties have become a pretty common place thing in the security world, for software and hardware alike. By posting this bounty Drupal has shown that they (and vicariously PHP) are ready to move up and join with the security community as a whole to make their software more secure. Not only does this look good for Drupal but it looks good for PHP too, elevating the status of the language back to a “major contender” in the security circles.

Second, it helps pave the way for other projects to do the same. Most PHP projects tend to be smaller, not only in size but in complexity. There’s only a handful that most PHP developers can immediately list that are larger and have really stood the test of time. Keep in mind, I’m not talking about corporate applications or services here. I’m talking about PHP-based applications like Drupal, WordPress or Joomla that can be used as a platform to build other things. For the most part, their PHP brethren trend more towards the smaller side. Some of the most popular packages on Packagist are smaller libraries and frameworks, not applications as a whole.

There are some larger projects, though. Frameworks like the Zend Framework and Symfony have put their own emphasis on security, having internal groups or just contributors handling the vulnerability discovery and disclosure. Drupal has done things similarly in the past, but with the posting of this bounty, they’ve set a precedent for other projects to follow. It’s an unfortunate fact but in the Real World, time spent on a project (that’s not for work) falls into two categories:

  1. You do it for passion, either because the project is “yours” and you want to see it thrive or
  2. You do it because you’ll get something back out of it, either financial or in terms of much needed features

Bug bounties, pretty obviously, fall into that second category. Being able to pay out that financial compensation for work done bug hunting could be enough to tip people over from the “eh, I could” mentality to the “that’s worth my time” world. Don’t get me wrong, I’m not saying that developers are only interested in the money…far from it. I’m only saying that bounties like this gather more attention and show that the project believes in itself enough to have people commit time, either free or for work, to hunting down bugs.

I do want to touch on a third (bonus!) point too, while I have you here. While bounties like this are good for projects that have a budget, it sort of rules it out for those smaller projects where it’s just a one person team (or just a few people). In general these kinds of projects have little to no budget associated with them and don’t have spare cash on hand to pay out for bugs found or fixed. Unfortunately, there’s not too much in the way of options on this one. I’ve seen differing opinions on the payout amounts too. Some people think that the payout should relate to the severity of the bug, but the project just may not be able to afford that. People could feel slighted by the low compensation for their time which could in turn reflect poorly on the project overall. It’s a tough line…

There is one option out there that might be a good fit for your smaller project, though. The Bountysource.com site has integrated an interesting concept of a “fundraiser” for open source projects. The idea is that a project could raise the finds in a Kickstarter-like fashion and use it to pay out bounties (or really however they might see fit). While it’s a good idea in theory, smaller projects that don’t have much exposure are still going to have a hard time raising any funds to make the bounties a realistic thing.

I don’t have a good answer here, unfortunately. I think with so much of the PHP world turing to smaller packages, it’s a tough problem to figure out. I’m all ears if you can think of any other options or even services that might help. I’d love to help make bug bounties a more wide-spread thing in the PHP world. I feel like, done correctly, they can only help to make the PHP ecosystem a better, more secure place.

Gatekeeper & Policies

I’ve been working on a system for a while now, inspired by the work that was done on the Sentry project, to provide a role-based access control system that was not only more well-maintained but also built on the foundation they provided to add in some new features. My “little project” Gatekeeper has really grown over time and (I think) really evolved into something that’s quite useful.

With this progression in mind, I’ve recently added another new feature that sits on top of the permissions and groups system that allows you to create reusable policies. Policies are a common concept when it comes to access control. They can make performing complex operations a lot simpler and, in the case of how it’s implemented here, make it much more reusable across the entire system (or multiple systems). Checking user permissions and groups is a relatively simple operation if you’re just doing one or two checks. You’d end up with something like this:

<?php
use \Psecio\Gatekeeper\Gatekeeper as g;

$user = g::findUserById(1);
if ($user->inGroup("group1") && $user->hasPermission("perm1")) {
    echo "Good to go!";
}

?>

In this case, the check is relatively simple but there’s one think that any DRY code advocate could tell you – this exact check would need to be reproduced throughout the entire application exactly as stated to ensure the evaluation is the same. Even worse, if the requirements changed you’d have to work across the entire application and replace all instances with the new logic.

This is where policies can come in very handy. With the functionality that Gatekeeper includes, they’re dead simple to use too. The key is in their use of the Symfony Expression Language component. This language allows you to define text strings that represent logic and allow for more complex and self-contained evaluation. Enough talk, let’s see how we can use these policies to perform the same check as above.

<?php
// First we'll make the policy - this only needs to be done once
Gatekeeper::createPolicy(array(
    'name' => 'admin-test1',
    'expression' => '"group1" in user.groups.getName() and "perm1" in user.permissions.getName()',
    'description' => 'See if a user has "permission1" and is in "group1"'
));

// Now, we need to evaluate the user against the policy
if (Gatekeeper::evaluatePolicy('admin-test1', $user) === true) {
    echo 'They have the permission! Rock on!';
}

?>

It’s a little more verbose than the previous example, but you can see how it would fetch the permissions and groups for the user and check it against the set of names. In this case the getName function is a magic method that filters the collection and returns a set of the name property values as an array. This way it can be used with the incheck. Once the policy is in place, then any time you need to perform that evaluation, all you need to do is call the evaluatePolicy method with the information and it will always execute the same logic making it super portable and DRY.

I also mentioned how it helps with changing requirements. All you’d need to do here is change the policy contents (the expression string) and all of the code already in place will now evaluate with that new logic with no code changes required. Easy, huh?

I hope this functionality will be useful if you’re a Gatekeeper user or, if you’re not, may give you a reason to check it out. I’m also interested to hear if you think this might make for a good stand-alone component, abstracted out from the Gatekeeper system. It’s integrated right now because of the known model/relationship structure but it’s not hard to pull it out and make it abstract enough to use for other systems.

Social Security

Let me preface this by saying I think that sharing knowledge and experiences is a great thing. I love that there’s so many tutorials out there from people showing good practices in security and things they’ve learned along the way. Unfortunately, this is the same place where I see a major downfall. This kind of “social security” is a problem and it needs fixing so secure application development can really thrive.

Technology is great, especially PHP. Sure, there’ll be haters out there and they’ll throw stones at the glass house that is PHP hoping to break down the walls and push it off away from the public eye and into the “Not A Real Language” world. Fortunately, this will never happen especially with more recent improvements to the language and its consistent popularity among web developers. PHP is both easy to pick up but difficult to master, especially when it comes to the security of the applications written with it. Along with this low barrier for entry comes people sharing things either in tutorials or just articles that they’ve found to be useful or think is a good practice. The web is littered with articles like these, some being a bit more factual than others. *This is where the real problem is.*

Well-meaning developers post tutorials about things like preventing XSS with just htmlspecialchars or only fixing SQL injection with prepared statements and bound parameters. While these are good practices in themselves, they’re not the only thing that needs to be done to prevent these issues. Security is a complicated subject and there’s no one answer to any problem. Usually a robust solution involves multiple layers (defense in depth anyone?) to ensure the problem doesn’t pop up again or in another location. Even worse are the numerous older articles posted around the internet that have bad or old information. Sadly I see some of these that are *years* old being recommended as good resources to learn from.

I see two kinds of resources out there:

  • Those that are posts from individuals or groups and are wholly maintained by them
  • community resources such as the OWASP wiki

I’ve done some picking on OWASP in the past about the quality of their PHP materials and what seems to be their general feel around PHP and PHP-centric security. This time, though, I don’t want to talk as much about their content itself but about the process they follow for generating that content.

I appreciate what OWASP is going for application security, I really do, but I think the “everyone can edit” mentality of their content is very flawed. I know it’s just not feasible for a single organization largely made up of volunteers to manage and audit all of the content on their site. I get that, I really do, but when I see people referring to PHP resources that haven’t been updated since 2006 or 2007 it makes me cringe. And, because of the visibility of the group, those are the resources people find and recommend not knowing any different.

I think this is the crux of my opinion – having resources where anyone can contribute and not auditing those resources is a “Bad Thing” in my book. Unfortunately, in the case of the masses of tutorials posted out on the web, there’s not much that can be done about that. Those are there to stay and search engines will continue to ensure they show in results regardless of their quality or relevance to the current state of things.

I’m not saying I want people to stop contributing here, I just think there needs to be a balance. There’s a lot of regurgitation of the same kinds of advice out there (“let’s rehash the Top 10 again…”) but there’s also a lot of more innovative content that gets deeper into PHP security matters beyond just the prevention of the most common issues. In my experience, PHP developers are becoming more and more savvy about the security of their applications (even if it is a “negative deliverable” so to speak) and require tips and techniques beyond these simple ten point checklists.

Unfortunately, there’s just not a good answer here. As long as the web continues to be a free for all in terms of posting content developers will keep posting the same things or they’ll post bad suggestions (or ones that just don’t make any sense). The only thing I can think to do is to offer advice to those doing research or reading through PHP security content to ensure they’re getting the best information they can:

  1. Check the article date. If it’s older than 9-12 months, close the tab and move on. That’s not content you need to be reading.
  2. If the content talks about “preventing the most common vulnerabilities” in PHP applications, chances are it’s just another Top 10 article. If you know those already, skip it.
  3. Favor articles with links from things other than search engine results. If you come across an article from a recommendation on another non-linkbait site chances are the content is at least mildly useful.
  4. Consider the source. Do a little research on the author, if they don’t have much of a presence on the web around PHP-related things either take the advice with a large grain of salt or move on.
  5. Look for things that are well-written. Chances are if something is easy to understand or provides plenty of technical detail (and less hand waving “do this not that”) you’ve found something worth reading through.

These are just guidelines, obviously. Ultimately it’s up to your best judgement and research skills to determine the validity of the content and if it applies to your situation.

Invoke and Gatekeeper for Route Authentication & Authorization

As a part of a new project I’m working on (personal, not work) I came across a common need to enforce authentication and authorization handling in a bit more automated way based on the URL requested. I looked around for options and didn’t really find many that could be implemented somewhat simply but I did like the way Symfony defines their YAML to enforce auth* on the various endpoints. I set out to make something similar but a little simpler and ended up making Invoke.

It’s a super simplified version of the YAML-based routing and only has functionality for checking groups and permissions right now, but that’s not what I really wanted to talk about in this post. Invoke is fun and all, but I wanted to show how I’ve integrated it with another more robust tool I’ve written, Gatekeeper. The goal of Gatekeeper is to make a simple drop-in authentication system for applications to take care of a lot of the boilerplate user management needs. It comes with the usual CRUD handling for users, groups and permissions (RBAC) and also supports password resets, security questions and “remember me” functionality. Again, Gatekeeper is a cool library but it’s not the primary focus here. I wanted to integrate the two libraries so I could let each do what they do best – Invoke to check the current user against a set of criteria and Gatekeeper to provide the data for this validation.

Invoke lets you hook in your own users via a `UserInterface` that you can implement in your own application. In this case Gatekeeper has a concept of users too, but they don’t exactly mesh with what Invoke is expecting. So, let’s make an Invoke-compatible user object that it can use for it’s checks. This is the real key to the integration:

<?php
use \Psecio\Gatekeeper\Gatekeeper as Gatekeeper;

class InvokeUser implements \Psecio\Invoke\UserInterface
{
  private $details = array();

  public function __construct(array $details)
  {
    $this->details = $details;
  }

  public function getGroups()
  {
    $groupSet = array();
    $groups = Gatekeeper::findUserById($this->details['id'])->groups;
    foreach ($groups as $group) {
      $groupSet[] = new InvokeGroup($group);
    }
    return $groupSet;
  }

  public function getPermissions()
  {
    $permSet = array();
    $permissions = Gatekeeper::findUserById($this->details['id'])->permissions;
    foreach ($permissions as $permission) {
      $permSet[] = new InvokePermission($permission);
    }
    return $permSet;
  }
}
?>

Then, we’ll define the Invoke configuration in a YAML document:

event/add:
  protected: on
  groups: [test]
  permissions: [perm1]

In this case we’re telling Invoke that when it sees the requested URL of `/event/add` it should check a few things:

  • That the user is authenticated (protected: on)
  • That the user has a group with the “name” attribute of “test”
  • That the user has a permissions with the “name” attribute of “perm1”

If the user passes all of these checks, they’re good to go. Here’s how that would look in the execution of the Invoke code:

<?php

$en = new \Psecio\Invoke\Enforcer(__DIR__.'/config/routes.yml');

// If you're already using Gatekeeper for user management, you
// can just use this:
$userData = Gatekeeper::findUserById(1)->toArray();

// Otherwise you can push in your own user data
$userData = array(
  'username' => 'ccornutt',
  'id' => 1,
  'email' => 'ccornutt@phpdeveloper.org'
);

$allowed = $en->isAuthorized(
  new Confer\InvokeUser($userData),
  new \Psecio\Invoke\Resource()
);

if ($allowed === false) {
  // They're not allowed on this resource, forward to an error!
}

?>

The Invoke Resource by default looks at the current REQUEST_URI value so no options are needed when it’s created.

I’ve found this a pretty simple way to integrate these two libraries while still maintaining the correct separation of concerns enough to let each tool do their job. I’m always welcome to feedback on both projects or, of course, PRs if you find something that needs improving or a bug to fix.

Here’s more information about each of them: