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.

Writing Secure Code for WordPress

1,374 views

Published on

Presentation on some of the most popular forms of web application vulnerabilities, and how to fix them "The WordPress Way".

Published in: Technology
  • Be the first to comment

Writing Secure Code for WordPress

  1. 1. Writing Secure Code for WordPress WordCamp Toronto 2015 ! Shawn Hooper
 Chief Technology Officer,Actionable Books @shawnhooper - shawnhooper.ca
  2. 2. • I’m Shawn Hooper, CTO at Actionable Books. Former Freelance Developer • GIAC Certified .NET Secure Software Programmer • Love Auditing Code (I’m Strange) Hi! @shawnhooper - shawnhooper.ca
  3. 3. We are going to look at a couple of different types of attacks and how to avoid them: 
 * SQL Injection * Cross Site Scripting (XSS) * Cross Site Request Forgery (CSRF) * Unvalidated Redirects and Forwards We’re Under Attack! @shawnhooper - shawnhooper.ca
  4. 4. ! ! ! on the
 Open Web Application Security Project (OWASP) Top Ten List Injection Attacks @shawnhooper - shawnhooper.ca
  5. 5. SQL injection is a code injection technique, used to attack data-driven applications, in which malicious SQL statements are inserted into an entry field for execution (e.g. to dump the database contents to the attacker). - Wikipedia SQL Injection Attacks @shawnhooper - shawnhooper.ca
  6. 6. Without protecting against injection attacks, what would happen if a 
 login form allowed this: ! ' OR '1'='1' -- SQL Injection Attacks @shawnhooper - shawnhooper.ca
  7. 7. SELECT * FROM wp_users 
 WHERE user_pass = '' OR '1'='1' --' SQL Injection Attacks @shawnhooper - shawnhooper.ca
  8. 8. '; DROP TABLE wp_users; -- SQL Injection Attacks @shawnhooper - shawnhooper.ca
  9. 9. SELECT * FROM wp_users 
 WHERE user_pass = ''; DROP TABLE wp_users; -- SQL Injection Attacks @shawnhooper - shawnhooper.ca
  10. 10. ! ! ! on the
 Open Web Application Security Project (OWASP) Top Ten List Cross Site Scripting (XSS) @shawnhooper - shawnhooper.ca
  11. 11. Cross-site scripting (XSS) is a type of computer security vulnerability typically found in web applications. XSS enables attackers to inject client- side script into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. - Wikipedia Cross Site Scripting (XSS) @shawnhooper - shawnhooper.ca
  12. 12. Cross Site Scripting can be used to capture a user’s authentication / session cookie and then impersonate them on a trusted website. ! Reflected (ex, delivered by e-mail)
 vs. Persistant (ex, return by DB in a forum) Cross Site Scripting (XSS) @shawnhooper - shawnhooper.ca
  13. 13. ! ! ! on the
 Open Web Application Security Project (OWASP) Top Ten List Cross Site Request Forgery @shawnhooper - shawnhooper.ca
  14. 14. Cross-site request forgery, also known as a one-click attack or session riding and abbreviated as CSRF (sometimes pronounced sea-surf) or XSRF, is a type of malicious exploit of a website whereby unauthorized commands are transmitted from a user that the website trusts. -Wikipedia Cross Site Request Forgery @shawnhooper - shawnhooper.ca
  15. 15. An example of a simple CSRF attack would be getting you to visit a link that would change your password to something the attacker knows. Cross Site Request Forgery @shawnhooper - shawnhooper.ca
  16. 16. ! ! ! on the
 Open Web Application Security Project (OWASP) Top Ten List Unvalidated Forwards & Redirects @shawnhooper - shawnhooper.ca
  17. 17. Could allow code in your website to forward the user to a malicious (ex: phishing) website. Unvalidated Forwards & Redirects @shawnhooper - shawnhooper.ca
  18. 18. @shawnhooper - shawnhooper.ca Scared Yet?
  19. 19. @shawnhooper - shawnhooper.ca Scared Yet? Let’s figure out how to stop all this stuff from happening…..
  20. 20. Sanitization & Validation @shawnhooper - shawnhooper.ca
  21. 21. Output Validation and Sanitization @shawnhooper - shawnhooper.ca
  22. 22. Validation @shawnhooper - shawnhooper.ca * Are values of the correct type? * Are values in range?
  23. 23. Validation @shawnhooper - shawnhooper.ca Is an input supposed to be an integer? 
 
 intval($_POST[‘quantity’])
 
 or
 
 absint($_POST[‘quantity’])
  24. 24. Validation @shawnhooper - shawnhooper.ca Is it in range? 
 $quantity = absint($_POST[‘quantity’]) ! if ( $quantity > 10 ) { die(‘Quantity Out of Range’); }
  25. 25. Validation @shawnhooper - shawnhooper.ca Should it be an e-mail address? 
 $email = is_email( $_POST[‘email’] ); returns false if invalid
  26. 26. Sanitization @shawnhooper - shawnhooper.ca Should it be an e-mail address? 
 $email = sanitize_email( $_POST[‘email’] ); removes characters that are not valid in an e-mail address.
  27. 27. Escaping Text @shawnhooper - shawnhooper.ca esc_html( $string ); esc_html__( $string, $attr ); ex:
 
 Hello <?php echo esc_html( $string ); ?> !
  28. 28. Escaping Text @shawnhooper - shawnhooper.ca esc_attr( $text ); esc_attr__( $text, $domain );
 
 Escaping a string for use in an HTML attribute tag.
 
 <div data-value=“<?php echo esc_attr( $value ); ?>”>
  29. 29. Escaping Text @shawnhooper - shawnhooper.ca esc_js( $text );
 
 Escaping a string for echoing in JavaScript. 

  30. 30. Escaping URLs @shawnhooper - shawnhooper.ca esc_url ($url );
 esc_url_raw ( $url );
 urlencode ( $string ); 
 urlencode_deep ( $array );
  31. 31. Escaping HTML @shawnhooper - shawnhooper.ca wp_kses( $fragment, $allowed_html, $protocols); array(
 'a' => array(
 'href' => array(),
 'title' => array() 
 ), 'br' => array(),
 'em' => array(),
 'strong' => array()
 );
  32. 32. Escaping HTML @shawnhooper - shawnhooper.ca wp_rel_nofollow( $html ) ! Adds rel=“nofollow” to every link in the HTML fragment.
  33. 33. Database Sanitization @shawnhooper - shawnhooper.ca
  34. 34. $wpdb Is Your Friend! Database Sanitization @shawnhooper - shawnhooper.ca
  35. 35. $wpdb->insert( ‘table_name’, array( 'column1' => 'value1', 'column2' => 123 ), array( '%s', '%d' ) ); Database Sanitization @shawnhooper - shawnhooper.ca
  36. 36. $wpdb->update( 'table', array( 'column1' => 'value1', // string 'column2' => 'value2' // integer (number) ), array( 'ID' => 1 ), array( '%s', // value1 '%d' // value2 ), array( '%d' ) ); Database Sanitization @shawnhooper - shawnhooper.ca
  37. 37. $wpdb->delete( 'table', array( 'ID' => 1 ), array( '%d' ) ); Database Sanitization @shawnhooper - shawnhooper.ca
  38. 38. What about other general queries? ! Statements that include joins? 
 ! $wpdb->query() Database Sanitization @shawnhooper - shawnhooper.ca
  39. 39. $wpdb->prepare() to make sure query is safe: ! ! $wpdb->prepare(SQL Code with Placeholders, variable 1, variable 2, etc.); Database Sanitization @shawnhooper - shawnhooper.ca
  40. 40. Database Sanitization @shawnhooper - shawnhooper.ca $safeSQL = $wpdb->prepare(“SELECT * FROM mytable 



WHERE col1 = ‘%s’AND col2 = %d”, $sParam, $iParam); ! $wpdb->query($safeSQL);
  41. 41. Database Sanitization @shawnhooper - shawnhooper.ca Valid Placeholders are: ! %s for strings ! %d for integers ! %f for floats
  42. 42. Database Sanitization @shawnhooper - shawnhooper.ca If your query includes a LIKE statement in the WHERE clause, use 
 
 esc_like() 
 
 to properly escape %, _ and characters, 
 which have special meanings.
 
 Still requires $wpdb->prepare()
  43. 43. Database Sanitization @shawnhooper - shawnhooper.ca $likeValue = ‘value_’; $safeSQL = $wpdb->prepare(“SELECT * FROM table 
 WHERE col1 LIKE ‘%s’", esc_like($likeValue) . '%' );
  44. 44. Input Sanitization @shawnhooper - shawnhooper.ca
  45. 45. Input Sanitization @shawnhooper - shawnhooper.ca There are a pile of functions to do input sanitization: sanitize_title() sanitize_user() balance_tags() tag_escape() is_email() sanitize_html_class() array_map() sanitize_email() sanitize_file_name() sanitize_term() sanitize_term_field() sanitize_html_class() sanitize_key() sanitize_mime_type() sanitize_option() sanitize_sql_orderby() sanitize_text_field() sanitize_title_for_query() sanitize_title_with_dashes() sanitize_user() sanitize_meta()
  46. 46. Nonces @shawnhooper - shawnhooper.ca
  47. 47. Nonces @shawnhooper - shawnhooper.ca A “number used once” to help protect URLs from malicious use (Cross Site Request Forgery)
  48. 48. Nonces @shawnhooper - shawnhooper.ca NOTE: In WordPress, a nonce is not a number, and it is not used once. ! ! !
  49. 49. Nonces @shawnhooper - shawnhooper.ca Create a Nonce for a URL: $complete_url = 
 wp_nonce_url( $bare_url, 'trash-post_'.$post- >ID );
 

  50. 50. Nonces @shawnhooper - shawnhooper.ca Create a Nonce for a Form: wp_nonce_field( 'delete-comment_'.$comment_id );

  51. 51. Nonces @shawnhooper - shawnhooper.ca Generates code like this: <input type="hidden" id="_wpnonce" name="_wpnonce" value="796c7766b1" /> <input type="hidden" name="_wp_http_referer" value="/wp-admin/edit-comments.php" />

  52. 52. Nonces @shawnhooper - shawnhooper.ca Generic Nonce: ! $nonce = wp_create_nonce( 'my-action_'.$post->ID );
  53. 53. Validate Nonces @shawnhooper - shawnhooper.ca To verify a nonce that was passed in a URL or a form in an admin screen: ! check_admin_referer( 'delete-comment_'.$comment_id );
  54. 54. Validate Nonces @shawnhooper - shawnhooper.ca To verify a nonce that was passed in an AJAX request:
 (parameter is the action sent via AJAX) ! check_ajax_referer( 'process-comment' );
  55. 55. Validate Nonces @shawnhooper - shawnhooper.ca To verify a generic nonce: ! wp_verify_nonce( $_REQUEST['my_nonce'], 'process- comment'.$comment_id ); ! Returns false if the nonce fails
  56. 56. Nonces @shawnhooper - shawnhooper.ca ! To learn more about nonces, see the WordPress Codex: ! https://codex.wordpress.org/WordPress_Nonces
  57. 57. Brain Full ? @shawnhooper - shawnhooper.ca Good, because we’re almost done.
  58. 58. Redirecting @shawnhooper - shawnhooper.ca wp_redirect( $url, $status ); exit; wp_safe_redirect( $url, $status ); exit; ! $status defaults to 302 (temporary) safe_redirect only allows redirects to a specified set of hostnames, which can be set using the allowed_redirect_hosts filter
  59. 59. Now you should get this… @shawnhooper - shawnhooper.ca XKCD # 327
  60. 60. Responsible Disclosure @shawnhooper - shawnhooper.ca If you find what you think may be a security vulnerability in WordPress’ code, be responsible. Send an e-mail with as much detail to:
 
 security@wordpress.org
 
 Don’t blog about it, Facebook it, put it in Trac, Tweet it, etc. Allow the team time to confirm and fix the bug before letting all the hackers out there know it exists.
  61. 61. Thank you!
 Slides: www.shawnhooper.ca
 E-Mail: shawn@actionablebooks.com
 Twitter: @shawnhooper
 WordPress Slack: shooper @shawnhooper - shawnhooper.ca

×