Author: ccornutt

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.

Advertisements

PHP, Security & PSR-9/PSR-10

Late yesterday afternoon the PSR-9 and PSR-10 drafts were moved into master on the php-fig/standards repository, moving them along to the next step and to get the wider perspective of the main PHP-FIG group’s opinions on it.

What are PSR-9 and PSR-10, you ask? Here’s a brief summary so far:

At the end of last year (2014) Lukas Smith made a proposal to the PHP-FIG group for a standard that would make reporting security issues with PHP projects and libraries a much more structured thing. The general idea is that a standardized document (or documents?) in a project’s repository would provide information about current and past security issues in a well-defined structure that could have some automated tooling around it. Much discussion was had around what the proposal actually entailed and how it would integrate with the goals of the PHP-FIG process. As work progressed on it, a few others besides Lukas came on-board to help flesh out the standard and work out the kinks, including myself.

It wasn’t long before we realized that, while having a standardized method for reporting vulnerabilities was good there also needed to be a way to discover this documentation for a given project (more than just a “look for this file” kind of thing). So, the original PSR-9 was split, giving us the security advisory reporting standard (PSR-9) and the security disclosure workflow (PSR-10) to make discovery of the reports easier. Both PSRs have received the votes needed for entrance and consideration and, as I mentioned, work is moving forward on them in the wider PHP-FIG group.

So, what are the standards? Well, I’m not going to just copy and paste from the documents (you can find those here if you’re interested) but I will give a quick overview of what they contain and their goals.

Note: these standards are by no means complete so this information is a bit subject to change. I just wanted to share their current state though.

PSR-9

The main goal of the PSR-9 standard is to provide structure around the documentation a project provides to the wider community around security vulnerabilities that have been found (and fixed) and those that are still pending. The idea is that any given user could look at the document and have a security-centric view into where the project currently stands. Right now, with the exception of those participating in the security-advisories database, most projects make it a bit of a run around to try to figure out what issues have come up and what problems have been fixed. Sometimes it’s reported in the Changelog, other times it’s in the mailing lists and other times you just have to know what to search for in the project’s issue tracker to get the list. This PSR-9 aims to eliminate a lot of this hassle and give a single source for the information.

The security-advisories database has provided a great start around this same kind of information but with PSR-9 the burden of reporting this information falls on the project, not a single source. We’re not aiming to replace that database by any means, though. We just want to empower the projects to share the information in a vetted, well-defined way. The PSR-9 proposal provides a lot more context around the security issues too.

This information includes:

  • An entry for each vulnerability that includes a short summary, published date, link to more information and a unique reference ID
  • CWE and/or CVE information, if possible (not all vulnerabilities are reported as CVEs)
  • What versions the issue affects
  • Current status of the issue
  • A description of the remediation if resolved
  • A low/medium/high severity rating based on the impact to the project’s users

We discussed the versioning of this resource (multiple files) so new vulnerabilities could be added and a “history” of sorts could be tracked over time but nixed that idea in favor of a single file that would just evolve over time. A lot of this vulnerability metadata is similar to information currently reported by other projects, so it’s not too far of a stretch to see this dropped into a structured, easy to find document. Speaking of which, this brings me to the next proposal…

PSR-10

Where PSR-9 is about the structured vulnerability list, PSR-10 is about the discovery of said document. As we worked through the original PSR-9 ideas, we found that reporting the vulnerabilities was one thing and having a structured way to access the documentation was another. One is more about the concrete thing, the document, and the other is more around process.

The PSR-10 proposal isn’t quite as fleshed out at the moment, but there are a few main points that give us a starting place:

  • The document that represents the data for a project’s PSR-9 disclosure should live somewhere the project can directly reference it, such as the project’s website or other documentation page. This is the ideal place as it removes ambiguity around which version of the document is the “master”.
  • Projects may opt to have the source in their version control system with the caveat that it should be publicly facing (not require a checkout) and that the “master” branch should be visibly documented.
  • Projects would be allowed to split up the information by the version number of the release but, as this can get much more confusing quickly, it would need to be well documented

We discussed just having the document in the version controlled repository of the project, but this leads to other issues including the definition of which branch is the “master” for the document and how to deal with private repositories (remember, the goal is public disclosure). Ultimately is was worked out that a public-facing resource was the best option. One suggestion includes a custom “link” tag with a relation value of “php-vuln-disclosures” to help with automated discovery.

We’re all excited about these two standards moving forward and look forward to the feedback the wider PHP-FIG group can provide around them. Things will be developing a bit more quickly now (it was slow going mainly because of holidays and other personal issues around the end of the year) and our hopes are that these two standards can evolve and be worked out as soon as possible.

Keep an eye on the proposals as they evolve. I’d love to get any feedback on them or suggestions based on your own experiences that would help make things even better.

Speaking at AppSec USA 2015

It’s always good to step outside of your usual bubble and try something new every once and a while. I recently took this step and submitted for the AppSec USA 2015 conference happening in San Francisco on September. My topic? PHP security, naturally but it’s to a much more diverse audience. At PHP conferences its easy to take a lot of things for granted. You’re able to assume that most of the people in the room are developers and understand what PHP’s all about and have at least a little experience with it. At AppSec I don’t really have that guarantee so it’ll be interesting to see how it turns out.

Here’s my prospectus for those that are interested:

PHP Security, Redefined

Let’s be honest, PHP has had a rocky history with security. Over the years the language has been highly criticized for it’s lack of a focus on security and secure development practices. In more recent years, however, a resurgence has happened in the language and community, bringing secure development back into focus. With PHP 7 on the horizon, the language is making even more strides to improve some of its wayward ways of the past and reinvent itself. I’ll share practical code examples, tools, libraries and best practices that are making it easier than ever to keep PHP applications safe.

Come along with me as I guide you through both the language improvements and community encouragement making PHP a more secure place.

I’m hoping that, while the talk is more specifically about PHP security, that it will also be a good platform to help some in the information security community shatter some of their own misconceptions about PHP (ones that are probably stuck in the late PHP 4 to early PHP 5 days). I’m excited to get to talk about PHP7 too which, if all goes well, should be in its final stages by the time the conference rolls around in September.

When I got the acceptance email, I felt that same feeling down in the pit of my stomach I felt when I first was accepted to php[tek] so many years ago. Now it’s a good feeling, though – one that’s more excitement than worry, more encouragement than stress.

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:

Developer Security Outreach

I’ve been thinking a lot lately about how to try to bring the security and development communities together, most specifically for PHP (see these two posts for more on that). PHP has a long standing reputation for being an insecure language that it’s had to overcome. I like to think that evidence in more recent years is helping to dissuade that, but it’s an uphill battle. Anyway, that’s not what I’m hear to talk about. True to the title of the post, I want to talk about developer outreach as it relates to security and secure development practices.

While comments were made on my two previous post about the relationship going both ways, I want to focus in on things from the perspective of the organization with the bulk of the knowledge – the application security group/company. Yes, it’s good for developers to contribute back to shared resources so both parties can benefit, but with so many new developers coming to the language every day, I see a real need for engagement. There are a lot of groups and individuals out there on the security side that specialize in training and resources to help developers write their code more securely. They provide training classes and white papers on new technologies that can be used to get the ideas across, but usually only in a limited fashion. They write blog posts about the latest exploits and vulnerabilities or even speak at conferences with case studies and their own real-world experience in the world of application security.

So, take a step back – do you see a problem with this model? Most of these things I’ve listed involve talking at the developers and not with them. Sure, some of the training classes are more hands-on and can be much more effective at getting the speaker’s ideas across. However, these kinds of resources are mostly provided if requested or actively sought out by the developer. There’s a wealth of information out there about securing applications, even PHP ones, that’s tucked away and only shown when the right Google search is performed.

Is there a solution? In thinking about it some this morning, I see a pretty obvious one – developer outreach. I’ve mentioned this same idea before in another post, but that one was more targeted towards the OWASP group and the services/resources it provides. It still surprises me when I ask in my sessions at PHP-related conference how many people have heard of OWASP and some hands go up but a lot don’t. Likewise, there’s a lot of companies out there that provide application security training (such as the Denim Group, WhiteHat Security or even SANS) but those are still presented as passive resources. Developers, by their nature, are notoriously lazy. They try to find the most efficient, most robust solutions to problems. How much would they benefit from someone from the Denim group reaching out to them or even just the PHP community as a whole and sharing what they have to offer.

Am I suggesting they hop on the various community mailing lists and start spamming them with ads for their training courses? Of course not. Here’s what I am proposing:

If you provide training, resources or any other kind of resources that developers could benefit from to create more secure applications, find an advocate (or a few) in the community of your choice and request their help to get the word out. I’d even go so far as to suggest having someone dedicated to working with communities, maybe even different people for different communities. This person should be dedicated to not only sharing what kind of things the company/group has to offer the developer community but to also act as a guide to keep them on the right path.

There’s a security subculture in just about every language out there. The key for those with the security knowledge and resources to do is to tap into it. Break into the community with a sense of humility, an open mind to learn about its members and a passion for teaching and sharing knowledge on a personal level.

An Open Suggestion to OWASP (or How to Bridge the Gap)

In a previous post I made a call out to the security community (mostly the OWASP group) about some of the lacking involvement in the world of PHP. There were some good comments on the post, and there’s some I’d like to give my own feedback on to maybe explain things rolling around in my head even better.

First off, there was the comment I knew was coming even before I hit the “Publish” button. In this comment Ryan turns some of my comments back around and wonders if the lack of PHP involvement by OWASP is more of a reflection of how much involvement the PHP community has with it. While I agree with this to a point, I’d also suggest that it has to be a two way street when it comes to communicating effectively with developers. An organization that wants to provide information about how to secure applications should be involved with the groups it’s trying to help. Likewise, that group can’t effectively provide the information developers are looking for without guidance from those developers themselves. After all, what good would a guide about not using “safe_mode” be to people using PHP 5.4.0+? More on this topic later…

Another comment brought up a few more specific issues around the tooling that the OWASP group provides, suggesting that it’s less attuned to what PHP developers actually need and is more of a direct port of an existing Java or .NET version of a similar project. The influence is definitely there and it makes me wonder how much PHP experience the author had in the language (not just writing PHP but actually knowing PHP…there’s a difference). The PHP community is a rapidly evolving one by the nature of the language and if you’re not keeping up with trends, advancements in the language or where the state of security in the language is at, your tool will be deprecated before it even hits 1.0.

Finally there’s the comment I hoped I’d get from a representative of the OWASP group themselves, a member of the board no less, Michael Coates. I’m glad that the response was one of openness and a desire to make things better. It’s easy to see how, especially in a community that tends to err on the side of keeping things under a rock, that the group I was mentioning was paying attention. Michael’s comment asks for direct suggestions about things that can be done to help the situation I put out there. With the somewhat wide chasm between the two words, I can see a lot of room for improvement, but I think there’s one suggestion I’d make to Michael and the rest of the OWASP folks (including those already involved in PHP-related projects under the organization):

Get involved.

Sounds simple, right? Honestly, I think the biggest problem here is the communication between the two groups. I feel like the OWASP group, while having good intentions, sometimes comes across as more of a “we’re security professionals and we know how to write the tools correctly” kind of mentality. As a result, you end up with projects like the PHP ESAPI  or the work being done on the PHP Security Project that’s recreating tools that already exist in the PHP ecosystem for the sake of having a “one tool to rule them all.” Essentially what it ends up being is a mish-mash of tools that a developer could use to secure their applications. What it doesn’t end up being is a useful tool that PHP developers want to use to secure their applications.

The goals of the project are admirable, but their time could be much better spent encouraging the package mentality the PHP community has evolved over the past few years and enhance the security features of pre-existing and well-tested/vetted libraries already in wide-spread use. Let me illustrate with a list of things the owasp/phpsec project includes that already have packages that solve the problem:

– a database abstraction layer (not an ORM or even ActiveRecord, just a layer on top of PDO)

– a “download manager” that seems to not do much more than stream a file to the given output

– an encryption class that does some crazy stuff to encrypt a string

– A HTTP request class that most frameworks have anyway (or even HttpFoundation)

– A Logging class that can output to a database, file, mail or syslog (or just use Monolog)

– A cryptographically secure random number generator (how about RandomLib instead)

– A sort of “security scanner” that looks for a limited set of keywords (try Parse instead)

– A session handler that forces database use and doesn’t plug into the SessionHandler interface

There’s a lot of other features in the tool that could go on this list too, but it feels like there’s just a big disconnect here between the goals of the project to provide a useful library PHP developers will want to use. While I get the whole idea that other packages are “written by developers and not security experts”, there’s a lot of things they’re reproducing here that have already been solved.

So, my suggestion to the group working on the PHP Security Project is this – stop with the Not Invented Here development and get involved in the work that’s already been done to make these “decoupled libraries” people are actually using. Help show the PHP development community that you’re interested in being a guiding force for security concepts and techniques rather than building something in a silo most developers would never even use.

The PHP community gets better tools and OWASP gets known in the community as an organization that cares about keeping PHP safe. Seems to me like this is a win/win situation for both sides.