writing secure wordpress code wordcamp nyc 2014

59
WRITING SECURE WORDPRESS CODE BY BRAD WILLIAMS Brad Williams @williamsba h-p://www.slideshare.net/williamsba/wri>ngsecurewordpresscodewordcampnyc2014

Upload: brad-williams

Post on 08-Sep-2014

308 views

Category:

Technology


1 download

DESCRIPTION

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.

TRANSCRIPT

Page 1: Writing Secure WordPress Code WordCamp NYC 2014

WRITING SECURE WORDPRESS CODE BY  BRAD  WILLIAMS  

Brad Williams @williamsba

h-p://www.slideshare.net/williamsba/wri>ng-­‐secure-­‐wordpress-­‐code-­‐wordcamp-­‐nyc-­‐2014  

Page 2: Writing Secure WordPress Code WordCamp NYC 2014

WHO IS BRAD?

Brad Williams @williamsba

Brad  Williams    

Page 3: Writing Secure WordPress Code WordCamp NYC 2014

CO-HOST DRADCAST

Brad Williams @williamsba

Page 4: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 5: Writing Secure WordPress Code WordCamp NYC 2014

TRUST NO ONE

Brad Williams @williamsba

Golden  Rule  of  Code  

Trust  No  One  

Page 6: Writing Secure WordPress Code WordCamp NYC 2014

TRUST NO ONE

Brad Williams @williamsba

Consider  all  data  invalid  unless  it  can  be  proven  valid  

Page 7: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

SQL  Injec>on  (SQLi)  

Page 8: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 9: Writing Secure WordPress Code WordCamp NYC 2014

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';  

Page 10: Writing Secure WordPress Code WordCamp NYC 2014

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';";

Page 11: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

h-p://www.sitepoint.com/forums/showthread.php?83772-­‐web-­‐site-­‐hacked  

My  Introduc>on  to  SQLi  

Page 12: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

h-p://www.sitepoint.com/forums/showthread.php?83772-­‐web-­‐site-­‐hacked  

My  Introduc>on  to  SQLi  

Page 13: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

WordPress  Database  Class  

Page 14: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

$wpdb->insert()

Page 15: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 16: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

$wpdb->update()

Page 17: Writing Secure WordPress Code WordCamp NYC 2014

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:  

Page 18: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

$wpdb->delete()

Page 19: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

$wpdb->delete( $wpdb->posts, array( 'ID' => 5 ), array( '%d' ) );

$wpdb->delete() $wpdb->delete( $table, $where, $where_format )

Example:  

Page 20: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

$wpdb->prepare()

Page 21: Writing Secure WordPress Code WordCamp NYC 2014

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()

Page 22: Writing Secure WordPress Code WordCamp NYC 2014

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()

Page 23: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 24: Writing Secure WordPress Code WordCamp NYC 2014

SQL INJECTION - SQLI

Brad Williams @williamsba

h-p://xkcd.com/327/  

Don’t  be  Li-le  Bobby  Tables  

Page 25: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE SCRIPTING - XSS

Brad Williams @williamsba

Cross-­‐Site  Scrip>ng    (XSS)  

Page 26: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE SCRIPTING - XSS

Brad Williams @williamsba

 What  is  Cross-­‐Site  Scrip>ng?  

 A-acker  injects  client-­‐side  scripts  into  your  web  pages  

Page 27: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 28: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 29: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE SCRIPTING - XSS

Brad Williams @williamsba

<h1><?php echo $title; ?></h1>

BAD  

Page 30: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE SCRIPTING - XSS

Brad Williams @williamsba

<?php $title = "<script>alert('YO!');</script>"; ?> <h1><?php echo $title; ?></h1>

BAD  

Page 31: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 32: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 33: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 34: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 35: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 36: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 37: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE SCRIPTING - XSS

Brad Williams @williamsba

Integers  

Page 38: Writing Secure WordPress Code WordCamp NYC 2014

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 ); ?>" />

Page 39: Writing Secure WordPress Code WordCamp NYC 2014

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 ); ?>" />

Page 40: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE SCRIPTING - XSS

Brad Williams @williamsba

Sani>zing  To  sani>ze  is  to  take  the  data  and  clean  

to  make  safe  

Page 41: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE SCRIPTING - XSS

Brad Williams @williamsba

<?php update_post_meta(

420,

'_post_meta_key',

$_POST['new_meta_value'] ); ?>

BAD  

Page 42: Writing Secure WordPress Code WordCamp NYC 2014

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'] ) ); ?>

Page 43: Writing Secure WordPress Code WordCamp NYC 2014

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'] ) ); ?>

Page 44: Writing Secure WordPress Code WordCamp NYC 2014

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'] ) ); ?>

Page 45: Writing Secure WordPress Code WordCamp NYC 2014

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>  

Page 46: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 47: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE REQUEST FORGERY - CSRF

Brad Williams @williamsba

Cross-­‐site  Request  Forgery  (CSRF)  

Page 48: Writing Secure WordPress Code WordCamp NYC 2014

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)  

Page 49: Writing Secure WordPress Code WordCamp NYC 2014

CROSS-SITE REQUEST FORGERY - CSRF

Brad Williams @williamsba

Nonces  Ac>on,  object,  &  user  specific  >me-­‐

limited  secret  keys  

Page 50: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 51: Writing Secure WordPress Code WordCamp NYC 2014

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 );

Page 52: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 53: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 54: Writing Secure WordPress Code WordCamp NYC 2014

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 );

Page 55: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 56: Writing Secure WordPress Code WordCamp NYC 2014

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  

Page 57: Writing Secure WordPress Code WordCamp NYC 2014

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/  

 

Page 58: Writing Secure WordPress Code WordCamp NYC 2014

DRADCAST PLUG

Brad Williams @williamsba

Listen  to  the  DradCast  WordPress  Podcast    

                                       LIVE  every  Wednesday  @  8pm  EDT    

DradCast.com  

Page 59: Writing Secure WordPress Code WordCamp NYC 2014

CONTACT BRAD

Brad Williams @williamsba

Brad  Williams  [email protected]    Blog:    strangework.com  Twi-er:  @williamsba      

h-p://bit.ly/prowp2