php security 101

50
PHP SECURITY101 AUGUST 12, 2012 michael stowe

Upload: michael-stowe

Post on 15-Jan-2015

11.297 views

Category:

Technology


2 download

DESCRIPTION

The second in the series, PHP Security 101 is focused on the principles of web development security, and utilizes the methods of Prison Theory for Web Development Security.

TRANSCRIPT

Page 1: PHP Security 101

PHP SECURITY101

AUGUST 12, 2012

michael stowe

Page 2: PHP Security 101

• 10+ years experience hacking PHP

• Published Author, Speaker, and Consultant

• Developed applications used by the medical field and law enforcement

• Software Engineer at CaringBridge.org (half a million visitors every day)

• Zend Certified PHP 5.3 Software Engineer

.com

@mikegstowe

MIKESTOWE

Page 3: PHP Security 101

WHAT DOES IT MEAN

TO BE SECURE?

Page 4: PHP Security 101

PRISON THEORY OF WEB DEVELOPMENT

SECURITY

Page 5: PHP Security 101

PRISON THEORY OF WEB DEVELOPMENT SECURITY

• Control User Access and Mobility

• Have a Emergency Response Plan

• Provide Proper Training

• Restrict Potential for Negligence by Staff

• Scan Incoming Traffic

• Validate and Sanitize Everything

• Use Obfuscation

• Log and Monitor Everything

• Proactively Scan and Monitor Code

Page 6: PHP Security 101

CONTROL USER ACCESS

One of the most basic layers of security is to simply

control what pages the user has access to. This, in it’s

simplest form means providing work flows to direct users

to only the pages you want them to visit, and in more

complex forms: restricting script directives and validating

user roles and privileges on each page.

Page 7: PHP Security 101

Remember, it’s YOUR application. You built

it with a purpose. The way your application

is built should GUIDE users to do the things

you want them to, and PREVENT them from

doing the things you don’t.

Page 8: PHP Security 101

INI DIRECTIVES

register_globals = off; < PHP 5.4, Extremely Dangerous

session.use_only_cookies = 1; Ignores querystring session ID

session.cookie_httponly = 1; Limits access to cookies*

allow_url_fopen = 0; Disallows using fopen with external URLs

allow_url_include = 0; Disallows including external URLs

zend.script_encoding = UTF8; PHP 5.4+, sets encoding

* not supported by all browsers

Page 9: PHP Security 101

USER AUTHENTICATION <?php

<?php class restrictedController { public function restrictedAction() { // Load User Class $user = new User(); // Validate User if (!$user->loggedIn() || !$user->role('Author')) { $this->redirect('/notAuthorized'); } /** ... **/ } }

Page 10: PHP Security 101

HAVE A EMERGENCY RESPONSE PLAN

Security breaches can occur night or day, you need to

have a plan for responding when they do. Your plan

should include different scenarios, and the proper

protocols to follow. You should also have an escalation

plan, in case the security breach is beyond your control or

expertise. Your plan should also include a debriefing to

review how effective the response was, and how to

improve and prevent future security breaches.

Page 11: PHP Security 101

SAMPLE PLAN

• Take database containing personal data offline

• Place maintenance page online

• Review logs to identify breach

• Notify on-call experienced employee

• Patch and review for other obvious threats

• Restore database and site

• Proactively scan and identify any other threats

• Report issue and cause

• Debriefing with team

Page 12: PHP Security 101

THE DEBRIEFING

Version control, backups, logging, and proactive scans

can help reduce the damage caused by some breaches.

However, team debriefings can prevent this breach from

occurring again by explaining to team members what

caused the vulnerability to begin with.

Debriefings should not be blame sessions, but rather

teaching moments.

Page 13: PHP Security 101

PROVIDE TRAINING

It is vital that developers are trained on the proper

security techniques and stay up to date on new

vulnerabilities/ security techniques.

Training helps reduce the risk of security breaches by

teaching the BEST methods while identifying incorrect

practices (ie add_slashes()).

Page 14: PHP Security 101

You can INVEST in your DEVELOPER’S

EDUCATION or you can PAY for their

MISTAKES. Guess which one costs more…

Page 15: PHP Security 101

RESTRICT POTENTIAL FOR NEGLIGENCE

Some of the most dangerous hackers are on the payroll.

More often than not developers are rushed to complete

part of a project that is dependent on code that they are

not familiar with (ex: services, models, etc).

Without the proper steps this rush code has the potential

to be a welcoming mat for pernicious* visitors.

* Yes, I pulled out the dictionary…

Page 16: PHP Security 101

RESTRICT POTENTIAL FOR NEGLIGENCE

Methods to prevent negligent code include:

• Restricted Access (only the code they need)

• Version Control (Git, SVN, CVS, etc)

• Code Reviews and Audits

• End-Point Validation (ex: type-hinting)

• Using Magic (getters and setters)

Page 17: PHP Security 101

VERSION CONTROL

Version control allows you to quickly see WHAT code is

being modified, and determine whether or not it should

be merged into your master branch or trunk.

And when something breaks, version control makes it

fairly painless to identify issues and revert back to

previous code.

Git and SVN are two of the more popular version control methods

Page 18: PHP Security 101

VERSION CONTROL BASH

Get the latest from Master Branch in Git

git pull master

Create a new branch for a project

git checkout –b mybranch

Make Edits to index.php, and see differences

git diff index.php

Add to be committed

git add index.php

Commit file with message to local repository

git commit –m “Added check to redirect Mobile Users”

Push to Master Repository

git push origin master

GitHub.com provides a nice online code management interface

Page 19: PHP Security 101

END-POINT VALIDATION

Simply put End-Point Validation validates the data at it’s

end, instead of relying on previous validations. This

prevents the use of invalid or malformed code that is not

properly vetted prior to injection.

This also prevents developers from passing the wrong

type of information to a service, model, class, or function.

Page 20: PHP Security 101

END-POINT VALIDATION <?php

<?php class User { public function editPhone(PhoneNumber $phoneNumber) { if (!$phoneNumber->isValid()) { throw new Exception('Invalid Phone Number'); } $this->phoneNumber = $phoneNumber->get('number'); /** ... **/ } }

Page 21: PHP Security 101

USING MAGIC

PHP provides magic methods that can be used to validate

or restrict data based on value or type. By using the

magic __get() and __set() methods you are not

only able to restrict class properties, but ensure the data

passed is correct or manipulate it as necessary.

One such pre-existing code base for this is the

smrtClass() which allows you to set rules, restrict, and

even lock property values.

There are more useful magic methods such as __clone() and __invoke()

Page 22: PHP Security 101

USING MAGIC

class User { private $data = array('name', 'phone'); public function __set($name, $value) { if (!isset($this->data[$name])) { throw new Exception('Invalid Property Name'); } $this->data[$name] = $value; } public function __get($name) { if (isset($this->data[$name])) { return $this->data[$name]; } throw new Exception('Property Does not Exists'); } }

Learn more at: http://php.net/manual/en/language.oop5.magic.php

<?php

Page 23: PHP Security 101

USING SMRTCLASS

<?php $data = new smrtClass(); // Add an Integer $data->add('number', 'int'); $data->number = '10'; // Add a String $data->add('string'); $data->string = 'Hello World'; // Add an Email String $data->add('emailAddress', 'email'); $data->emailAddress = '[email protected]'; // Lock Data (No Changes) $data->lockData();

Download at: http://www.phpclasses.org/smrtClass

<?php

Page 24: PHP Security 101

SCAN INCOMING TRAFFIC

The first step to defending your site against hackers is to

prevent malicious incoming traffic. By checking the user

against a known database of hackers, checking the

browser, checking incoming data, and the use of Cross-

site Request Forgery tokens we can eliminate several

potential threats.

Page 25: PHP Security 101

IP BLACKLISTING

IP Blacklisting allows you to prevent IPs identified as

belonging to, or being used by spammers and hackers

from preventing your web application.

Page 26: PHP Security 101

IP BLACKLISTING <?php

<?php $blacklisted = array( '123.123.123.120', '123.123.123.121', '123.123.123.122', '123.123.123.123', ); if (isset($_SERVER['REMOTE_ADDR']) && in_array($_SERVER['REMOTE_ADDR'], $blacklisted)) { header('Location: banned.html'); exit(); }

Page 27: PHP Security 101

BROWSER SNIFFING

By checking the HTTP_USER_AGENT we can learn more

about our user, including what browser they CLAIM to be

using. Keep in mind that this, like all variables set client

side can be spoofed.

However, if a potential hacker has not gone the extra step

to set this variable in their attack, they will be easily

identified.

Page 28: PHP Security 101

BROWSER SNIFFING <?php

<?php $allowedBrowsersRegex = '/ Safari | Chrome | IE | Firefox | Opera /'; if (isset($_SERVER['HTTP_USER_AGENT'])) { if (!preg_match($allowedBrowsersRegex, $_SERVER['HTTP_USER_AGENT'])) { // Unsupported HTTP_USER_AGENT $this->redirect('/browserupgrade'); exit(); } } elseif (PHP_SAPI == 'cli') { // Accessed through Command Line - Unit Test? } else { // No HTTP_USER_AGENT! Curl attack? $this->redirect('/browserupgrade'); }

Remember, HTTP_USER_AGENT CAN be spoofed, do not rely on this

Page 29: PHP Security 101

CROSS-SITE REQUEST FORGERY

Simply put End-Point Validation validates the data at it’s

end, instead of relying on previous validations. This

prevents the use of invalid or malformed code that is not

properly vetted prior to injection.

This also prevents developers from passing the wrong

type of information to a service, model, class, or function.

Page 30: PHP Security 101

CSRF TOKENS <?php

<?php session_start(); if (!isset($_SESSION['token'])) { $_SESSION['token'] = sha1(uniqid(mt_rand(), TRUE)); $_SESSION['token_time'] = time(); } if ($_POST) { if (isset($_POST['token']) && $_POST['token'] == $_SESSION['token'] && (time() - $_SESSION['token_time']) <= 600) { // Valid Token Submitted within 10 minutes } else { echo '<span class="error">Invalid Submission. Please try again!</span>'; } } ?> <form action="..." method="post"> <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" /> ... </form>

Page 31: PHP Security 101

REQUEST SNIFFING

Request Sniffing is similar to Browser Sniffing with the

exception that we are testing the incoming GET/POST

data to ensure we are receiving ONLY the data we should

be.

Zend Framework 2 allows you to setup form filters that will remove any undefined form elements

Page 32: PHP Security 101

REQUEST SNIFFING <?php

<?php $formFields = array( 'name', 'address', 'city', 'state', 'zip', 'token', // don't forget to add any tokens! ); // Validating Post foreach ($_POST as $k=>$v) { if (!in_array($k, $formFields)) { // Delete it unset($_POST[$k]); // Or Just Redirect Them (Especially if Register_Globals enabled) $this->redirect('/invalidRequest'); exit(); } }

Page 33: PHP Security 101

VALIDATE EVERYTHING

The biggest mistake any developer can make is trusting

users to send them the correct data. Not only can users

make mistakes, but hackers are keen at taking advantage

of scripts that lack the proper vetting of incoming data.

Failure to validate and sanitize incoming data will open

your application to numerous attacks and vulnerabilities.

Page 34: PHP Security 101

SESSION VALIDATION

In order to prevent Session Fixation and Session Hijacking it is

important to validate that the Session ID being used belongs to the

correct user, and is not being used multiple times.

This can be done by storing and validating the user’s IP (problem for

AOL users), the HTTP_USER_AGENT, or using a Cookie based token

(recommended).

Also be sure to utilize session_regenerate_id() when performing

sensitive tasks (logins, credit cards, password updates, etc).

Page 35: PHP Security 101

SESSION VALIDATION <?php

<?php session_start(); if (!isset($_SESSION['token']) || !isset($_COOKIE['token']) || $_SESSION['token'] != $_COOKIE['token']) { session_regenerate_id(true); // note the delete_old_session parameter is set to true $token = md5(rand(11111111111, 99999999999)); // you can create a much more secure token // by utilizing alphabetic $_SESSION['token'] = $token; setcookie('token', $token); } ?>

Page 36: PHP Security 101

VALIDATE POST/ GET

Whenever possible, try to avoid using $_REQUEST to get

incoming data, instead ensuring the data is being sent to

your script through the proper (and expected) channels.

Especially since $_REQUEST will utilize Post, Get, and

Cookie data unless otherwise set in your INI.

Be sure to check that the data exists using isset()

before trying to validate to avoid index errors.

Page 37: PHP Security 101

VALIDATE GET/POST <?php

<?php // For a Specific Pattern if (!isset($_POST['year']) || !preg_match('/[0-9]{4}/', $_POST['year'])) { die('This is not a valid 4-Digit Year'); } // For Specific Choices $array = array('male', 'female'); if (!isset($_POST['gender']) || !in_array($_POST['gender'], $array)) { die('This is not a valid gender'); } // For Specific Types if (!isset($_POST['year']) || !is_int($_POST['year'])) { die('This is not a valid integer'); }

Page 38: PHP Security 101

PHP FILTER_VAR()

PHP 5.2+ includes the filter_var() function, which

allows you to both validate and sanitize data depending

on the flag used.

You can learn more about filter_var() at:

http://php.net/manual/en/filter.filters.validate.php

Page 39: PHP Security 101

PHP FILTER_VAR() <?php

<?php // VALIDATE DATA if (!isset($_POST['email']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) { die('This is an invalid email'); } if (!isset($_POST['genurlder']) || !filter_var($_POST['url'], FILTER_VALIDATE_URL)) { die('This is an invalid url'); }

Page 40: PHP Security 101

SANITIZE EVERYTHING

Validation helps reduce the risk of malicious data being passed

through, however, like any security measure it is not completely

fool proof. It is essential to sanitize the data once it has been

validated in order to help prevent malicious data from sneaking

through.

Three helpful functions for sanitizing incoming data include:

• filter_var()

• strip_tags()

• htmlentities()

Page 41: PHP Security 101

SANITIZE EVERYTHING <?php

<?php // Sanitize using filter_var() (PHP 5.2+) $safeEmail = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL); $safeUrl = filter_var($_POST['url'], FILTER_SANITIZE_URL); //------------------------------------- // Using strip_tags() $unsafeData = '<script>location.href=\'mysite\';</script>'; $new = strip_tags($unsafeData); echo $new; // echos out "location.href='mysite';" //------------------------------------- // Using htmlentities() $new = htmlentities($unsafeData, ENT_COMPAT | ENT_HTML401, 'UTF-8'); echo $new; // echos out // &lt;script&gt;location.href='mysite';&lt;/script&gt;

For PHP versions prior to 5.4 be sure to set the Encoding parameter

Page 42: PHP Security 101

DATABASE SANITIZATION

It is important to sanitize your data prior to submitting it

to the SQL Query Engine. When using MySQL you can

utilize the mysql_real_escape_string() function,

but it is highly recommended to take advantage of

MySQLi or PDO.

MySQLi and PDO allow you to build highly efficient

prepared statements, or parameterized statements that

utilize a single query template.

Page 43: PHP Security 101

USING PHP DATA OBJECTS <?php

<?php // Setup PDO Object and Connection Information $db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 'username', 'password'); // Build Query Template $stmt = $db->prepare("SELECT * FROM myTable WHERE username = :username AND password = :password"); // Bind and Sanitize Values // You can bind PHP Variables using the bindParam() method instead $stmt->bindValue(':username', $_POST['username'], PDO::PARAM_STR); $stmt->bindValue(':password', $_POST['password'], PDO::PARAM_STR); // Execute and Fetch $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Page 44: PHP Security 101

USE OBFUSCATION

Often times, the simplest forms of protection are also some of the

best. Obfuscation allows us to prevent users from having easy

access to our data and the architectural structure of our

application.

Methods of obfuscation include:

• Using harder to guess variable names

• Not using variable names in URLs or forms

• Encrypting personal information (password, credit cards, etc)

• Providing generic error messages

Page 45: PHP Security 101

LOG AND MONITOR

It is extremely important to log system access, system errors,

PHP errors, and user activities. These logs not only provide us

valuable insight into WHO the user is, and WHAT they are trying

to do, but also help us identify problems within our server

environments or PHP scripts.

Whenever testing an application, be sure to check the PHP Errors

log to ensure you are not creating new errors or warnings.

Page 46: PHP Security 101

LOGGING BAD ACTIONS <?php

<?php class restrictedController { public function restrictedAction() { // Load User Class $user = new User(); if (!$user->loggedIn()) { $this->redirect('/login'); } // Validate User if (!$user->role('Author')) { $this->logAttempt('restrictedAction', $user); $this->redirect('/notAuthorized'); exit(); } /** ... **/ } }

Multiple logs for the same user may identify a potential hacker

Page 47: PHP Security 101

PROACTIVELY SCAN AND MONITOR

It is also important to be proactive in scanning and monitoring

your code for bugs, unexpected behaviors, and maliciously

uploaded code.

Tools to Monitor and Scan Code Include:

• PHPUnit – behavior audit (phpunit.de)

• Selenium – front-end audit (seleniumhq.org)

• PHP Security Audit - code (sourceforge.net/projects/phpsecaudit/)

• Eval Scanner – code audit (mikestowe.com)

• PHP Scanner – front-end audit (mikestowe.com)

Page 48: PHP Security 101

TO REVIEW

Page 49: PHP Security 101

PRISON THEORY OF WEB DEVELOPMENT SECURITY

• Control User Access and Mobility

• Have a Emergency Response Plan

• Provide Proper Training

• Restrict Potential for Negligence by Staff

• Scan Incoming Traffic

• Validate and Sanitize Everything

• Use Obfuscation

• Log and Monitor Everything

• Proactively Scan and Monitor Code

Page 50: PHP Security 101

THANK YOU. @mikegstowe

visit mikestowe.com/slides for more on Security and PHP