WRITING SECURE WORDPRESS CODE BY  BRAD  WILLIAMS   Brad Williams @williamsba h-p://www.slideshare.net/williamsba/wri>ng-­‐secure-­‐wordpress-­‐code-­‐wordcamp-­‐nyc-­‐2014  
WHO IS BRAD? Brad Williams @williamsba Brad  Williams    
CO-HOST DRADCAST Brad Williams @williamsba
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  
TRUST NO ONE Brad Williams @williamsba Golden  Rule  of  Code   Trust  No  One  
TRUST NO ONE Brad Williams @williamsba Consider  all  data  invalid   unless  it  can  be  proven  valid  
SQL INJECTION - SQLI Brad Williams @williamsba SQL  Injec>on  (SQLi)  
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  
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';  
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';";
SQL INJECTION - SQLI Brad Williams @williamsba h-p://www.sitepoint.com/forums/showthread.php?83772-­‐web-­‐site-­‐hacked   My  Introduc>on  to  SQLi  
SQL INJECTION - SQLI Brad Williams @williamsba h-p://www.sitepoint.com/forums/showthread.php?83772-­‐web-­‐site-­‐hacked   My  Introduc>on  to  SQLi  
SQL INJECTION - SQLI Brad Williams @williamsba WordPress  Database  Class  
SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->insert()
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  
SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->update()
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:  
SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->delete()
SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->delete( $wpdb->posts, array( 'ID' => 5 ), array( '%d' ) ); $wpdb->delete() $wpdb->delete( $table, $where, $where_format ) Example:  
SQL INJECTION - SQLI Brad Williams @williamsba $wpdb->prepare()
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()
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()
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  
SQL INJECTION - SQLI Brad Williams @williamsba h-p://xkcd.com/327/   Don’t  be  Li-le  Bobby  Tables  
CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba Cross-­‐Site  Scrip>ng     (XSS)  
CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba   What  is  Cross-­‐Site  Scrip>ng?     A-acker  injects  client-­‐side  scripts  into  your  web  pages  
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  
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  
CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <h1><?php echo $title; ?></h1> BAD  
CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <?php $title = "<script>alert('YO!');</script>"; ?> <h1><?php echo $title; ?></h1> BAD  
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(&#039;Hello Europe!&#039;);&lt;/script&gt;</h1> GOOD  
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  
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  
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  
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  
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  
CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba Integers  
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 ); ?>" />
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 ); ?>" />
CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba Sani>zing   To  sani>ze  is  to  take  the  data  and  clean   to  make  safe  
CROSS-SITE SCRIPTING - XSS Brad Williams @williamsba <?php update_post_meta( 420, '_post_meta_key', $_POST['new_meta_value'] ); ?> BAD  
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'] ) ); ?>
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'] ) ); ?>
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'] ) ); ?>
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>  
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  
CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba Cross-­‐site  Request   Forgery   (CSRF)  
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)  
CROSS-SITE REQUEST FORGERY - CSRF Brad Williams @williamsba Nonces   Ac>on,  object,  &  user  specific  >me-­‐ limited  secret  keys  
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  
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 );
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  
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  
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 );
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  
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  
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/    
DRADCAST PLUG Brad Williams @williamsba Listen  to  the  DradCast  WordPress  Podcast                                            LIVE  every  Wednesday  @  8pm  EDT     DradCast.com  
CONTACT BRAD Brad Williams @williamsba Brad  Williams   brad@webdevstudios.com     Blog:    strangework.com   Twi-er:  @williamsba       h-p://bit.ly/prowp2  

Writing Secure WordPress Code WordCamp NYC 2014

  • 1.
    WRITING SECURE WORDPRESSCODE BY  BRAD  WILLIAMS   Brad Williams @williamsba h-p://www.slideshare.net/williamsba/wri>ng-­‐secure-­‐wordpress-­‐code-­‐wordcamp-­‐nyc-­‐2014  
  • 2.
    WHO IS BRAD? BradWilliams @williamsba Brad  Williams    
  • 3.
  • 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.
    TRUST NO ONE BradWilliams @williamsba Golden  Rule  of  Code   Trust  No  One  
  • 6.
    TRUST NO ONE BradWilliams @williamsba Consider  all  data  invalid   unless  it  can  be  proven  valid  
  • 7.
    SQL INJECTION -SQLI Brad Williams @williamsba SQL  Injec>on  (SQLi)  
  • 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.
    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.
    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.
    SQL INJECTION -SQLI Brad Williams @williamsba h-p://www.sitepoint.com/forums/showthread.php?83772-­‐web-­‐site-­‐hacked   My  Introduc>on  to  SQLi  
  • 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.
    SQL INJECTION -SQLI Brad Williams @williamsba WordPress  Database  Class  
  • 14.
    SQL INJECTION -SQLI Brad Williams @williamsba $wpdb->insert()
  • 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.
    SQL INJECTION -SQLI Brad Williams @williamsba $wpdb->update()
  • 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.
    SQL INJECTION -SQLI Brad Williams @williamsba $wpdb->delete()
  • 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.
    SQL INJECTION -SQLI Brad Williams @williamsba $wpdb->prepare()
  • 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.
    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.
    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.
    SQL INJECTION -SQLI Brad Williams @williamsba h-p://xkcd.com/327/   Don’t  be  Li-le  Bobby  Tables  
  • 25.
    CROSS-SITE SCRIPTING -XSS Brad Williams @williamsba Cross-­‐Site  Scrip>ng     (XSS)  
  • 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.
    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.
    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.
    CROSS-SITE SCRIPTING -XSS Brad Williams @williamsba <h1><?php echo $title; ?></h1> BAD  
  • 30.
    CROSS-SITE SCRIPTING -XSS Brad Williams @williamsba <?php $title = "<script>alert('YO!');</script>"; ?> <h1><?php echo $title; ?></h1> BAD  
  • 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(&#039;Hello Europe!&#039;);&lt;/script&gt;</h1> GOOD  
  • 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.
    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.
    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.
    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.
    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.
    CROSS-SITE SCRIPTING -XSS Brad Williams @williamsba Integers  
  • 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.
    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.
    CROSS-SITE SCRIPTING -XSS Brad Williams @williamsba Sani>zing   To  sani>ze  is  to  take  the  data  and  clean   to  make  safe  
  • 41.
    CROSS-SITE SCRIPTING -XSS Brad Williams @williamsba <?php update_post_meta( 420, '_post_meta_key', $_POST['new_meta_value'] ); ?> BAD  
  • 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.
    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.
    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.
    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.
    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.
    CROSS-SITE REQUEST FORGERY- CSRF Brad Williams @williamsba Cross-­‐site  Request   Forgery   (CSRF)  
  • 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.
    CROSS-SITE REQUEST FORGERY- CSRF Brad Williams @williamsba Nonces   Ac>on,  object,  &  user  specific  >me-­‐ limited  secret  keys  
  • 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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    DRADCAST PLUG Brad Williams @williamsba Listen  to  the  DradCast  WordPress  Podcast                                            LIVE  every  Wednesday  @  8pm  EDT     DradCast.com  
  • 59.
    CONTACT BRAD Brad Williams @williamsba Brad  Williams   brad@webdevstudios.com     Blog:    strangework.com   Twi-er:  @williamsba       h-p://bit.ly/prowp2