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 WordPress Code WordCamp NYC 2014

9,704 views

Published on

Learn the proper way to write the most secure code in WordPress. Whether you’re a plugin developer or build themes, it’s extremely important to understand how to secure your code from hacks and exploits. Overlooking some very easy to follow techniques can expose your website to the hackers everywhere. WordPress features a number of built-in methods to help make sure your code is safe and secure, and we’ll cover each and every one in detail.

Published in: Technology
  • Be the first to comment

Writing Secure WordPress Code WordCamp NYC 2014

  1. 1. WRITING SECURE WORDPRESS CODE BY  BRAD  WILLIAMS   Brad Williams @williamsba h-p://www.slideshare.net/williamsba/wri>ng-­‐secure-­‐wordpress-­‐code-­‐wordcamp-­‐nyc-­‐2014  
  2. 2. WHO IS BRAD? Brad Williams @williamsba Brad  Williams    
  3. 3. CO-HOST DRADCAST Brad Williams @williamsba
  4. 4. TODAY’S TOPICS Brad Williams @williamsba   • Cover  the  big  three  exploits   •  SQL  Injec>on  -­‐  SQLi   •  Cross-­‐Site  Scrip>ng  -­‐  XSS   •  Cross-­‐Site  Request  Forgery  –  CSRF   • Hack  Examples   • Data  Valida>on  and  Sani>za>on   • Resources  
  5. 5. TRUST NO ONE Brad Williams @williamsba Golden  Rule  of  Code   Trust  No  One  
  6. 6. TRUST NO ONE Brad Williams @williamsba Consider  all  data  invalid   unless  it  can  be  proven  valid  
  7. 7. SQL INJECTION - SQLI Brad Williams @williamsba SQL  Injec>on  (SQLi)  
  8. 8. SQL INJECTION - SQLI Brad Williams @williamsba SQL  injec*on  is  a  code  injec>on  technique   in  which  malicious  SQL  statements  are   inserted  into  an  entry  field  for  execu>on  
  9. 9. SQL INJECTION - SQLI Brad Williams @williamsba SQL  Injec>on  Example    global $wpdb; $ID = $_GET['ID']; $sql = "SELECT post_title FROM $wpdb->posts WHERE ID = '$ID';"; SELECT  post_>tle  FROM  wp_posts  WHERE  ID  =  '5';  
  10. 10. SQL INJECTION - SQLI Brad Williams @williamsba SQL  Injec>on  Example     SELECT  post_>tle  FROM  wp_posts  WHERE  ID  =  '';     SELECT  *  FROM  wp_users  WHERE  1  =  '1';   global $wpdb; $ID = "'; SELECT * FROM wp_users WHERE 1 = '1"; $sql = "SELECT post_title FROM $wpdb->posts WHERE ID = '$ID';";
  11. 11. SQL INJECTION - SQLI Brad Williams @williamsba h-p://www.sitepoint.com/forums/showthread.php?83772-­‐web-­‐site-­‐hacked   My  Introduc>on  to  SQLi  
  12. 12. SQL INJECTION - SQLI Brad Williams @williamsba h-p://www.sitepoint.com/forums/showthread.php?83772-­‐web-­‐site-­‐hacked   My  Introduc>on  to  SQLi  
  13. 13. SQL INJECTION - SQLI Brad Williams @williamsba WordPress  Database  Class  
  14. 14. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->insert()
  15. 15. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->insert( $wpdb->postmeta, array( 'post_id' => '5', 'meta_key' => '_custom_meta_key', 'meta_value' => 'true' ), array( '%d', '%s', '%s' ) ); $wpdb->insert() $wpdb->insert( $table, $data, $format ) Example:   %s  handles  strings     %d  handles  integers   %f  handles  floats  
  16. 16. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->update()
  17. 17. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->update( $wpdb->postmeta', array( 'meta_value' => 'false' ), array( 'post_id' => 5, 'meta_key' => '_custom_meta_key' ), array( '%s' ), array( '%d', '%s' ) ); $wpdb->update() $wpdb->update( $table, $data, $where, $format, $where_format ) Example:  
  18. 18. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->delete()
  19. 19. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->delete( $wpdb->posts, array( 'ID' => 5 ), array( '%d' ) ); $wpdb->delete() $wpdb->delete( $table, $where, $where_format ) Example:  
  20. 20. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->prepare()
  21. 21. SQL INJECTION - SQLI Brad Williams @williamsba •  Handles  strings  (%s)  and   integers  (%d)   •  Does  the  escaping  for  you   •  No  need  to  quote  %s   $wpdb->prepare( " SELECT post_title FROM $wpdb->posts WHERE ID = %d ", $ID ); $wpdb->prepare()
  22. 22. SQL INJECTION - SQLI Brad Williams @williamsba •  Handles  strings  (%s)  and   integers  (%d)   •  Does  the  escaping  for  you   •  No  need  to  quote  %s   $wpdb->prepare( " DELETE FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s ", 420, 'Europe' ); $wpdb->prepare()
  23. 23. SQL INJECTION - SQLI Brad Williams @williamsba $wpdb-­‐>prepare()  only  prepares  the  query,  it  does  not  execute  it.   $wpdb->query( $wpdb->prepare( " DELETE FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s ", 420, 'Europe' ) ); $wpdb->prepare() echo $wpdb->prepare( " DELETE FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s ", 420, 'Europe' ); To  view  the  fully  prepared  query  simply  echo  it  
  24. 24. SQL INJECTION - SQLI Brad Williams @williamsba h-p://xkcd.com/327/   Don’t  be  Li-le  Bobby  Tables  
  25. 25. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba Cross-­‐Site  Scrip>ng     (XSS)  
  26. 26. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba   What  is  Cross-­‐Site  Scrip>ng?     A-acker  injects  client-­‐side  scripts  into  your  web  pages  
  27. 27. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba Escaping   To  escape  is  to  take  the  data  you  may   already  have  and  help  secure  it  prior  to   rendering  it  for  the  end  user  
  28. 28. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba 1.  esc_  is  the  prefix  for  all  escaping  func>ons   2.  a-r  is  the  context  being  escaped   3.  _e  is  the  op>onal  transla>on  suffix   Props  to  Mark  Jaquith!   Escaping  
  29. 29. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <h1><?php echo $title; ?></h1> BAD  
  30. 30. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <?php $title = "<script>alert('YO!');</script>"; ?> <h1><?php echo $title; ?></h1> BAD  
  31. 31. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <?php $title = "<script>alert('Hello Europe!');</script>"; ?> <h1><?php echo esc_html( $title ); ?></h1> View  Source:   <h1>&lt;script&gt;alert('Hello Europe!');&lt;/script&gt;</h1> GOOD  
  32. 32. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <input type="text" name="name" value="<?php echo esc_attr( $text ); ?>" /> esc_attr() Used  whenever  you  need  to  display  data  inside  an  HTML  element   h-p://codex.wordpress.org/Func>on_Reference/esc_a-r  
  33. 33. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <textarea name="bio"> <?php echo esc_textarea( $bio); ?> </textarea> esc_textarea() Used  to  encode  text  for  use  in  a  <textarea>  form  element   h-p://codex.wordpress.org/Func>on_Reference/esc_textarea  
  34. 34. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <a href="<?php echo esc_url( $url); ?>">Link</a> esc_url()  Used  for  valida>ng  and  sani>zing  URLs   h-p://codex.wordpress.org/Func>on_Reference/esc_url  
  35. 35. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <?php $url = 'http://wordpress.org'; $response = wp_remote_get( esc_url_raw( $url ) ); ?> esc_url_raw()  Used  for  escaping  a  URL  for  database  queries,  redirects,  and  HTTP  requests   Similar  to  esc_url(),  but  does  not  replace  en>>es  for  display   h-p://codex.wordpress.org/Func>on_Reference/esc_url_raw  
  36. 36. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <script> var bwar='<?php echo esc_js( $text ); ?>'; </script> esc_js()  Used  to  escape  text  strings  in  JavaScript   h-p://codex.wordpress.org/Func>on_Reference/esc_js  
  37. 37. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba Integers  
  38. 38. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba $ID = absint( $_GET['ID'] ); absint() Coverts  a  value  to  a  non-­‐nega>ve  integer   h-p://codex.wordpress.org/Func>on_Reference/absint   <input type="text" name="number_posts" value="<?php echo absint( $number ); ?>" />
  39. 39. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba $ID = intval( $_GET['ID'] ); intval() Returns  the  integer  value.    Works  with  nega>ve  values   h-p://php.net/manual/en/func>on.intval.php   <input type="text" name="number_posts" value="<?php echo intval( $number ); ?>" />
  40. 40. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba Sani>zing   To  sani>ze  is  to  take  the  data  and  clean   to  make  safe  
  41. 41. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <?php update_post_meta( 420, '_post_meta_key', $_POST['new_meta_value'] ); ?> BAD  
  42. 42. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba sanitize_text_field() Sani>ze  a  string   h-p://codex.wordpress.org/Func>on_Reference/sani>ze_text_field   <?php update_post_meta( 34, '_post_meta_key', sanitize_text_field( $_POST['new_meta_value'] ) ); ?>
  43. 43. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba sanitize_email() Strip  out  all  characters  not  allowed  in  an  email  address   h-p://codex.wordpress.org/Func>on_Reference/sani>ze_email   <?php update_post_meta( 34, '_email_address', sanitize_email( $_POST['email'] ) ); ?>
  44. 44. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba sanitize_user() Sani>ze  username  stripping  out  unsafe  characters   h-p://codex.wordpress.org/Func>on_Reference/sani>ze_user   <?php update_post_meta( 34, '_custom_username', sanitize_user( $_POST['username'] ) ); ?>
  45. 45. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba wp_kses() Filters  content  and  keeps  only  allowable  HTML  elements.   h-p://codex.wordpress.org/Func>on_Reference/wp_kses   <a  href="#">link</a>.  This  is  bold  and  <strong>strong</strong>  
  46. 46. CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba wp_kses_post() Filters  post  content  and  keeps  only  allowable  HTML  elements.   h-p://codex.wordpress.org/Func>on_Reference/wp_kses_post   HTML  tags  allowed  to  be  put  into  Posts  by  non-­‐admin  users  
  47. 47. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba Cross-­‐site  Request   Forgery   (CSRF)  
  48. 48. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba Exploit  of  a  website  whereby  unauthorized  commands   are  transmi-ed  from  a  user  that  the  website  trusts.   Cross-­‐site  Request   Forgery   (CSRF)  
  49. 49. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba Nonces   Ac>on,  object,  &  user  specific  >me-­‐ limited  secret  keys  
  50. 50. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba <?php if ( isset( $_POST['email'] ) ) { //process form data } ?> <form method="post"> <input type="text" name="email /><br /> <input type="submit" name="submit" value="Submit" /> </form> Example   There  is  no  way  to  know  where  $_POST[‘email’]  is  being  posted  from  
  51. 51. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba <form method="post"> <?php wp_nonce_field( 'bw_process_email_action', 'bw_newsletter' ); ?> <input type="text" name="email" /><br /> <input type="submit" name="submit" value="Submit" /> </form> wp_nonce_field() <form method="post"> <input type="hidden" id="bw_newsletter" name="bw_newsletter" value="287de957e8" /> <input type="hidden" name="_wp_http_referer" value="/x/sample-page/" /> <input type="text" name="email" /><br /> <input type="submit" name="submit" value="Submit" /> </form> View  Source:   Form  Code:   h-p://codex.wordpress.org/Func>on_Reference/wp_nonce_field   wp_nonce_field( $action, $name, $referer, $echo );
  52. 52. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba if ( isset( $_POST['email'] ) ) { check_admin_referer( 'bw_process_email_action', 'bw_newsletter' ); //process form data } check_admin_referer() Processing  Code:   check_admin_referer( $action, $query_arg ); h-p://codex.wordpress.org/Func>on_Reference/check_admin_referer  
  53. 53. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba <?php if ( isset( $_POST['email'] ) ) { check_admin_referer( 'bw_process_email_action', 'bw_newsletter' ); //process form data } ?> <form method="post"> <?php wp_nonce_field( 'bw_process_email_action', 'bw_newsletter' ); ?> <input type="text" name="email" /><br /> <input type="submit" name="submit" value="Submit" /> </form> Fixed  Example  
  54. 54. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba $url = 'http://example.com/wp-admin/?ID=5'; $url = wp_nonce_url( $url, 'bw_process_email_action', 'bw_newsletter' ); wp_nonce_url() http://example.com/wp-admin/?ID=5&bw_newsletter=287de957e8 New  URL:   URL  Code:   h-p://codex.wordpress.org/Func>on_Reference/wp_nonce_url   wp_nonce_url( $actionurl, $action, $name );
  55. 55. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba if ( isset( $_GET[ID'] ) ) { check_admin_referer( 'bw_process_email_action', 'bw_newsletter' ); //process data } wp_nonce_url() Processing  Code:   h-p://codex.wordpress.org/Func>on_Reference/check_admin_referer  
  56. 56. CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba Nonces   Specific  to   • WordPress  User   • Ac>on  A-empted   • Object  of  a-empted  ac>on   • Time  Window  
  57. 57. RESOURCES Brad Williams @williamsba •  Security  Ar>cles   •  h-p://codex.wordpress.org/Data_Valida>on   •  h-p://codex.wordpress.org/Valida>ng_Sani>zing_and_Escaping_User_Data   •  h-p://wp.tutsplus.com/tutorials/7-­‐simple-­‐rules-­‐wordpress-­‐plugin-­‐development-­‐best-­‐ prac>ces/   •  h-p://wpengine.com/2013/05/brad-­‐williams-­‐on-­‐secure-­‐wordpress-­‐development/   •  h-p://codex.wordpress.org/WordPress_Nonces   •  Security  Presenta>ons   •  h-p://wordpress.tv/2013/08/09/mike-­‐adams-­‐three-­‐security-­‐issues-­‐you-­‐thought-­‐youd-­‐fixed/   •  h-p://wordpress.tv/2013/09/26/brennen-­‐byrne-­‐employing-­‐best-­‐security-­‐prac>ces-­‐for-­‐ wordpress-­‐sites-­‐3/   •  h-p://wordpress.tv/2011/01/29/mark-­‐jaquith-­‐theme-­‐plugin-­‐security/    
  58. 58. DRADCAST PLUG Brad Williams @williamsba Listen  to  the  DradCast  WordPress  Podcast                                            LIVE  every  Wednesday  @  8pm  EDT     DradCast.com  
  59. 59. CONTACT BRAD Brad Williams @williamsba Brad  Williams   brad@webdevstudios.com     Blog:    strangework.com   Twi-er:  @williamsba       h-p://bit.ly/prowp2  

×