prison theory - php edition
DESCRIPTION
Prison Theory of Web Development Security covers both some key security principles in PHP as well as an overview of Prison Theory of website development and the need to have a "security-first" mindset.TRANSCRIPT
Prison Theory Web Development Security
michael stowe
October 18, 2013
MIKESTOWE
• Open Source Contributor
• Author, Speaker, and Consultant
• 10+ years experience hacking PHP
• Zend Certified PHP 5.3 Software Engineer
• Developer Advocate with Constant Contact
.com @mikegstowe
SIDEBAR Top secret conference stuff
WHY THIS PRESENTATION? Today in the web development field there exists a false
sense of security regarding security. There is this idea that
we can “fix it when it happens” or that “it’s not that
important to worry about now.”
The problem is…
! Shortcuts often lead
to long detours
WHY WORRY ABOUT SECURITY?
• According to TechWorld, Google discovers 9,500 new
malicious sites everyday
• SearchEngineLand reports that a hacked site appears in
Google results 12-14 million times everyday
• According to Sohpo’s 2008 Security Threat Report, a
website is hacked every 5 seconds
NOT SCARY ENOUGH? • In 2008 there was an estimated 1 Trillion dollars worth of
stolen intellectual property
• 73% of Americans have fallen victim to a cyber-crime
• There is an average of 156 days between a system
compromise and detection
• In a recent survey, 90% of businesses reported being
hacked in the last 12 months
https://www.stopthehacker.com/2012/04/20/ten-scariest-hacking-statistics/
NOT SCARY ENOUGH?
• It’s estimated that 30,000 websites are infected everyday
• In 2010 the average website was found to have over 230
serious vulnerabilities, but over the course of a year only
53% were addressed
• In 2011 9 million Americans were victims of Identity Theft
https://www.stopthehacker.com/2012/04/20/ten-scariest-hacking-statistics/
WHAT THE HECK IS PRISON THEORY? Prison theory of web development security isn’t new, or
even ground breaking… there’s nothing new being
recommended, but rather it is a systematic way of thinking
about HOW to implement security best practices and what
mindset we should be using.
Read about Prison Theory in the Jan 2013 issue of Website Magazine
WHAT THE HECK IS PRISON THEORY?
Instead of proceeding with a “fix it as it comes” mindset,
Prison Theory suggests utilizing the same mindset, tools,
and techniques that are applied in law enforcement.
Including a focus on law enforcement’s greatest weapon…
WHAT THE HECK IS PRISON THEORY?
Communication.
WHAT THE HECK IS PRISON THEORY?
Prison Theory is:
• Proactive – we do not wait for something to happen
• Expecting – always alert and on the look out
• Communicative – communication is everything
• Measured and Planned – planned protocols are followed
• Reactive – reactions are based on what happens
• Agile and Learning – reactions and approaches evolve
• A mindset – this is what we do, and we will not fail
PROACTIVE
Police officers do not wait for a person to attack them.
Instead they are cautious, carefully watching the suspect,
and taking necessary precautions to make sure they are not
armed.
Prison Theory suggests we do the same with our
application, being proactive in our approach instead of just
“waiting for something to happen” before we worry about it.
EXPECTING
In Law Enforcement it is not a matter of IF, but rather
WHEN something bad will happen. A Police Officer needs to
be ready at ALL TIMES, not only for a call to come in, but
for something to happen right in front of them.
Likewise, we need to realize it’s not a matter of IF there will
be a breach in security, but rather WHEN and how ready for
it we will be.
COMMUNICATIVE
Communication is the most valuable tool Law Enforcement
has. Communication allows LEOs to work together, to get
quick answers, and call for backup.
Likewise, in application development and security
communication allows us to ensure the security of the
application, and provide for a rapid response when that
security is questioned.
MEASURED AND PLANNED Law enforcement officers are trained what to do in specific
situations, and while no situation can be entirely planned for,
because of this training and protocols they are able to
provide a uniform, measured, and planned response that
deals with the issue without creating other issues or putting
others in harms way.
Likewise, our responses should be swift and measured,
planned responses to deal with the issue without creating
more issues.
REACTIVE
The two dangers are not being prepared, and being so
prepared you are stuck in a box. LEOs are often called to a
scene with vague details, and are required to assess what is
ACTUALLY going on.
Likewise, it is important that we can quickly assess what is
going on, and react to what is happening rather than simply
following a numbered list.
AGILE AND LEARNING
Along with being able to react to the situation to assess
what is happening, LEOs need to be able to quickly adjust
their approach as situations change at the tip of the hat.
Failure to do so for an officer can be catastrophic.
Likewise, we need to be flexible and willing to adjust our
approach or even push aside certain issues to address more
critical ones, all while learning what works and what doesn’t
for the situation at hand.
A MINDSET
It takes a special type of person to work in law enforcement,
someone who is willing to put their life on the life. It isn’t
just a job, it’s a lifestyle. Every time an officer steps foot out
the door they make it their #1 priority to protect the public
from whatever may be thrown their way. For law
enforcement, failure is not an option.
Likewise, we cannot allow ourselves to sacrifice the security
and well being of our users. We should go into security with
the mindset that we will not fail.
PRISON THEORY OF WEB DEVELOPMENT SECURITY TECHNIQUES
• 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
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.
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
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'); } /** ... **/ } }
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.
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.
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
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.
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 in PHP: add_slashes()).
$ You can INVEST in your DEVELOPER’S
EDUCATION or you can PAY for their
MISTAKES. Guess which one costs more…
$ The AVERAGE cost of a security breach
involving personal information is
USD $5,500,000
http://www.stormpath.com/blog/password-breach-thatll-be-172000000-please
$ Unless you’re Sony
and Playstation gets hacked
USD $172,000,000
http://www.stormpath.com/blog/password-breach-thatll-be-172000000-please
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…
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)
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
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
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.
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'); /** ... **/ } }
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()
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
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, Captcha, and the use of
Cross-site Request Forgery tokens we can eliminate
several potential threats.
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.
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(); }
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.
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
CROSS-SITE REQUEST FORGERY
Cross-site Request Forgery tokens (or CSRF) are tokens
designed to make sure the request is coming from your
site (although they’re not perfect). This is usually done
by saving one token in the session, and placing another
token in the form with a timed expiration. If the form is
completed within so many minutes the two tokens are
compared, ensuring the form is being submitted using the
same session- or at least same session ID.
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>
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.
Many frameworks, including Zend Framework 2 (PHP) allows you to setup form filters that will remove any undefined form elements
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(); } }
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.
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. Keep in mind you
should never get the session ID from the URL (querystring).
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 reset the session ID when performing sensitive tasks
(logins, credit cards, password updates, etc).
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); } ?>
VALIDATE POST/ GET
Whenever possible, try to avoid using generic $_REQUEST
to get incoming data, instead ensuring the data is being
sent to your script through the proper (and expected)
channels. Especially since in PHP $_REQUEST will utilize
Post, Get, and Cookie data unless otherwise set in your INI.
Be sure to check that the data exists, for example using
isset() in PHP before trying to validate to avoid index errors.
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'); }
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
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'); }
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.
In PHP Three helpful functions for sanitizing incoming data include:
• filter_var()
• strip_tags()
• htmlentities()
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 // <script>location.href='mysite';</script>
For PHP versions prior to 5.4 be sure to set the Encoding parameter
BLACKLIST BLACKLISTING
Blacklisting certain types of text/ tags can be useful as an added
layer of security, but should not be trusted as a primary means of
validating/ sanitizing data. The problem with blacklisting is that it is
restricted in its capabilities, and limited to what we can think of,
verses what hackers may try.
For example, if we created a regular expression blacklist token, but
forgot to make it case-insensitive, a hacker could easily get around it
simply by changing the case of one letter. Regular expression
blacklisting is extremely easy to break.
DATABASE SANITIZATION
It is important to sanitize your data prior to submitting it
to the SQL Query Engine. Failure to do so allows for SQL
injection and gives the hacker access to the entire
database within the database user’s permissions. Also
make sure you are using modern methods to connect and
query the database, preferably using SQL Templates
instead of active queries (in PHP this can be done using
MySQLi (Improved Extension) or PDO.
SQL INJECTION
Query:
SELECT * FROM `TABLE` WHERE USERID = “$userId”
Input:
1” OR 1 = 1
New Query:
SELECT * FROM `TABLE` WHERE USERID = “1” OR 1 = 1
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);
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
*** It only takes 10 minutes to crack a six
character password consisting of just
lowercase letters
https://www.stopthehacker.com/2012/04/20/ten-scariest-hacking-statistics/
USE OBFUSCATION
Requiring users to create more complex passwords (P@$sw0rd!)
exponentially increases the complexity of the password and the
time required to hack it through a brute force attack.
Using a Captcha service such as ReCaptcha or locking accounts
after a set number of failed logins can also help prevent brute
force attacks.
Try to restrict COMMON passwords as well – in fact Twitter has a whole list of banned passwords!
http://securitywatch.pcmag.com/security-software/284196-the-twitter-banned-password-list
LOG AND MONITOR
It is extremely important to log system access, system errors,
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 scripts.
Whenever testing an application, be sure to check the error log to
ensure you are not creating new errors or warnings.
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
LOG AND MONITOR
It is not enough to simply LOG details! Logs should be monitored
and checked frequently to look for attempted attacks.
My PERSONAL server receives over 2,000 attempts every day!!!
It’s important to know what people are trying to ensure you are
protected against it, both now and in the future.
Remember, the average time before a breach is discovered is 156
days!!! MONITORING logs can help reduce this time greatly!
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 PHP 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)
TO REVIEW…
Prison Theory is:
• Proactive – we do not wait for something to happen
• Expecting – always alert and on the look out
• Communicative – communication is everything
• Measured and Planned – planned protocols are followed
• Reactive – reactions are based on what happens
• Agile and Learning – reactions and approaches evolve
• A mindset – this is what we do, and we will not fail
PRISON THEORY OF WEB DEVELOPMENT SECURITY TECHNIQUES INCLUDE…
• 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
THANK YOU.
@mikegstowe
visit mikestowe.com/slides for more on PHP and Web Development
@ctct_api
A big thank you to Constant Contact for making this presentation possible