Secure Coding
             with WordPress



                    @markjaquith
Mark Jaquith        m@rkj.me
     “JAKE-with”    markjaquith.com
The state of
WordPress plugin
  security is...
Problem #1


 Lack of
awareness
Problem #2


Apathy
Goals
   I want you to learn the following:

1. How to thwart the three most
common attacks
2. Two useful principles
3. Common mistakes to avoid
Attack #1

  SQL
Injection
$wpdb->query(
   "UPDATE $wpdb->posts
    SET post_title = '$newtitle'
    WHERE ID = $my_id"
);
$wpdb->update()
$wpdb->update(
   $wpdb->posts,
   array( 'post_title' => $newtitle ),
   array( 'ID' => $my_id )
);
$sets = array(
   'post_title'   => $newtitle,
   'post_content' => $newcontent
);

$wheres = array(
   'post_type' => 'post',
   'post_name' => $my_name
);

$wpdb->update( $wpdb->posts, $sets, $wheres );
$wpdb->insert( $table, $data )
$wpdb->prepare()
$wpdb->prepare(
   "SELECT * FROM $wpdb->posts
WHERE post_name = %s OR ID = %d",
   $some_name,
   $some_id
);
• Powered by sprintf(), but only %s
and %d are supported right now

• Do not quote %s — use %s, NOT '%s'
• Does the escaping for you
Rule #1


Escape Late
Attack #2



   XSS
(Cross-Site Scripting)
<h1>
<?php echo $title ?>
<h1>
$title = '<script>pwnage();</script>';
Rule #2


 Anything that
isn’t hardcoded
   is suspect
Rule #2 (revised)


Everything
 is suspect
Easy as...
esc_html()
<h1>
<?php echo esc_html( $title ); ?>
</h1>
<?php $title = '" onmouseover="pwnd();'; ?>
<a href="#wordcamp" title="<?php echo
$title; ?>">
Link Text
</a>
esc_attr()
<?php $title = '" onmouseover="pwnd();'; ?>
<a href="#wordcamp" title="<?php echo esc_attr( $title ); ?>">
Link Text
</a>
<?php $url = 'javascript:pwnd()'; ?>
<a href="<?php echo $url; ?>">
Link Text
</a>
esc_url()
esc_url_raw()
esc_js()
<script>
var foo = '<?php echo esc_js( $unsafe ); ?>';
</script>
esc_textarea()
wp_filter_kses()
Attack #3




 CSRF
Cross-site Request Forgery
Authorization
     vs.

Intention
Nonces
action-, object-, & user-specific
    time-limited secret keys
Specific to
• WordPress user
• Action attempted
• Object of attempted action
• Time window
wp_nonce_field( 'plugin-action_object' )
<form action="process.php" method="post">
<?php
wp_nonce_field('plugin-action_object');
?>
...
</form>
check_admin_referer( 'plugin-action_object' );
Still need to use
current_user_can()
CSRF for
Ajax/XHR
// 1. On the front end
$nonce = wp_create_nonce
( 'your_action' );

// 2. add &_ajax_nonce=$nonce to your
//    post/get vars

// 3. On the backend
check_ajax_referer( 'your_action' );
Stupid shit I
see all the time
eval()
<form action="<?php echo $_SERVER['REQUEST_URI']; ?>">
<a href="<?php echo $home; ?>" title="<?php echo $title; ?>">
<?php echo $text; ?>
</a>
<script>var foo = '<?php echo $var; ?>';</script>
<a href="<?php echo esc_url( $home ); ?>" title="<?php
echo esc_attr( $title ); ?>">
<?php echo esc_html( $text ); ?>
</a>
<script>var foo = '<?php echo esc_js( $var ); ?>';</
script>
Thanks!
                   @markjaquith
Mark Jaquith       m@rkj.me
     “JAKE-with”   markjaquith.com

WordPress Security - WordCamp Phoenix