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
                      Plugins

                                   Mark Jaquith

                           ...
XSS                            privilege




                                           shell execution
                  ...
Plugin
      security is
      hit-or-miss
Saturday, November 14, 2009
Mostly
                miss
Saturday, November 14, 2009
SQL
     Injection
Saturday, November 14, 2009
<?php
    $wpdb->query(
    	 "UPDATE $wpdb->posts
    	 SET post_title = '$newtitle'
    	 WHERE ID = $my_id"
    	 );
  ...
<?php
    $newtitle =
    	 	 	 	 	 esc_sql( $newtitle );
    $my_id = absint( $my_id );

    $wpdb->query(
    	 "UPDATE ...
$wpdb->update()



Saturday, November 14, 2009
<?php
    $wpdb->update(
    	 $wpdb->posts,
    	 array( 'post_title' => $newtitle ),
    	 array( 'ID' => $my_id )
    	...
$wpdb->insert()


Saturday, November 14, 2009
<?php
    $wpdb->insert(
    	 $wpdb->posts,
    	 array( 'post_title' => $newtitle )
    	 );
    ?>




Saturday, Novemb...
<?php
    $wpdb->update(
    	 $wpdb->posts,
    	 array(
    	 	 'post_title' => $newtitle,
    	 	 'post_content' => $ne...
<?php
    $post_title = 'New Title';
    $wheres['ID'] = 123;
    $wheres['post_title'] = 'Old Title';
    $wpdb->update(
...
$wpdb->prepare()



Saturday, November 14, 2009
<?php
    $title = 'Post Title';
    $ID = 123;
    $content = $wpdb->get_var(
    	 $wpdb->prepare(
    	 "SELECT post_co...
•Uses sprintf() formatting
                    •%s for strings
                    •%d for integers
                    •Y...
Escape
      late
Saturday, November 14, 2009
XSS
Saturday, November 14, 2009
<h1>
    <?php
    	 echo $title;
    ?>
    </h1>




Saturday, November 14, 2009
<?php
    	 $title = '<script> pwnage(); </script>'
    ?>

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




Sat...
Anything that
     isn’t hardcoded
        is suspect
Saturday, November 14, 2009
Better:
      Everything is suspect

Saturday, November 14, 2009
Saturday, November 14, 2009
esc_html()

Saturday, November 14, 2009
<?php
    	 $title =
    	 	 	 	 '<script> pwnage(); </script>'
    ?>
    <h1>
    <?php
    	 echo esc_html( $title );
 ...
<?php
    $title = '" onmouseover="pwnd();';
    ?>
    <a href="#wordcamp" title="
    <?php
    	 echo $title;
    ?>
  ...
esc_attr()



Saturday, November 14, 2009
<?php
    $title = '" onmouseover="pwnd();';
    ?>
    <a href="#wordcamp" title="
    <?php
    	 echo esc_attr( $title ...
<?php
     $url = 'javascript:pwnage();';
    ?>
    <a href="
    <?php
    	 echo esc_attr( $url );
    ?>
    ">
      ...
esc_url()

Saturday, November 14, 2009
<?php
     $url = 'javascript:pwnage();';
    ?>
    <a href="
    <?php
    	 echo esc_url( $url );
    ?>
    ">
    Lin...
esc_url_raw(),
                       sister of esc_url()


Saturday, November 14, 2009
esc_ js()

Saturday, November 14, 2009
<script>
         var foo = '<?php echo esc_js( $bar ); ?>';
         </script>




Saturday, November 14, 2009
CSRF
Saturday, November 14, 2009
Authorization
                              vs.

     Intention
Saturday, November 14, 2009
Nonces
              action-, object-,
             user-specific time
            limited secret keys
Saturday, November 1...
Specific to
                    •WordPress user
                    •Action attempted
                    •Object of attemp...
wp_nonce_field()



Saturday, November 14, 2009
<form action="process.php"
    method="post">
    <?php
    	 wp_nonce_field('plugin-action_object');
    ?>

    ...
    ...
check_admin_referer( )




Saturday, November 14, 2009
<?php
    // before output goes to browser
    check_admin_referer('plugin-
    	 action_object');
    ?>




Saturday, No...
Still need to use
     current_user_can()


Saturday, November 14, 2009
AJAX
                CSRF
Saturday, November 14, 2009
• wp_create_nonce(   'your_action' );

                    • &_ajax_nonce=YOUR_NONCE
                    • check_ajax_refe...
Privilege
       Escalation
Saturday, November 14, 2009
current_user_can()



Saturday, November 14, 2009
Set your salts!
                http://api.wordpress.org/secret-key/1.1/




Saturday, November 14, 2009
Stupid shit
               I see all
               the time
Saturday, November 14, 2009
exec()

Saturday, November 14, 2009
<form action="<?php echo
           $_SERVER['REQUEST_URI']; ?>">




Saturday, November 14, 2009
<a href="<?php echo $url; ?>"
      title="<?php echo $title; ?>">
      <?php echo $text; ?>
      </a>

      <script>
 ...
<a href="<?php echo esc_url( $url ); ?>"
      title="<?php echo esc_attr( $title ); ?>">
      <?php echo esc_html( $text...
Discussion

Saturday, November 14, 2009
Upcoming SlideShare
Loading in …5
×

Writing Secure Plugins — WordCamp New York 2009

9,273 views

Published on

How to write secure plugins, from my presentation at WordCamp New York 2009.

Published in: Technology, Business

Writing Secure Plugins — WordCamp New York 2009

  1. 1. Writing Secure Plugins Mark Jaquith @markjaquith markjaquith.com coveredwebservices.com Saturday, November 14, 2009
  2. 2. XSS privilege shell execution escalation CSRF SQL injection Saturday, November 14, 2009
  3. 3. Plugin security is hit-or-miss Saturday, November 14, 2009
  4. 4. Mostly miss Saturday, November 14, 2009
  5. 5. SQL Injection Saturday, November 14, 2009
  6. 6. <?php $wpdb->query( "UPDATE $wpdb->posts SET post_title = '$newtitle' WHERE ID = $my_id" ); ?> Saturday, November 14, 2009
  7. 7. <?php $newtitle = esc_sql( $newtitle ); $my_id = absint( $my_id ); $wpdb->query( "UPDATE $wpdb->posts SET post_title = '$newtitle' WHERE ID = $my_id" ); ?> Saturday, November 14, 2009
  8. 8. $wpdb->update() Saturday, November 14, 2009
  9. 9. <?php $wpdb->update( $wpdb->posts, array( 'post_title' => $newtitle ), array( 'ID' => $my_id ) ); ?> Saturday, November 14, 2009
  10. 10. $wpdb->insert() Saturday, November 14, 2009
  11. 11. <?php $wpdb->insert( $wpdb->posts, array( 'post_title' => $newtitle ) ); ?> Saturday, November 14, 2009
  12. 12. <?php $wpdb->update( $wpdb->posts, array( 'post_title' => $newtitle, 'post_content' => $newcontent ), array( 'ID' => $my_id, 'post_title' => $old_title ) ); ?> Saturday, November 14, 2009
  13. 13. <?php $post_title = 'New Title'; $wheres['ID'] = 123; $wheres['post_title'] = 'Old Title'; $wpdb->update( $wpdb->posts, compact( 'post_title' ), $wheres ); ?> Saturday, November 14, 2009
  14. 14. $wpdb->prepare() Saturday, November 14, 2009
  15. 15. <?php $title = 'Post Title'; $ID = 123; $content = $wpdb->get_var( $wpdb->prepare( "SELECT post_content FROM $wpdb->posts WHERE post_title = %s AND ID = %d", $title, $ID ) ); ?> Saturday, November 14, 2009
  16. 16. •Uses sprintf() formatting •%s for strings •%d for integers •You should not quote or escape Saturday, November 14, 2009
  17. 17. Escape late Saturday, November 14, 2009
  18. 18. XSS Saturday, November 14, 2009
  19. 19. <h1> <?php echo $title; ?> </h1> Saturday, November 14, 2009
  20. 20. <?php $title = '<script> pwnage(); </script>' ?> <h1> <?php echo $title; ?> </h1> Saturday, November 14, 2009
  21. 21. Anything that isn’t hardcoded is suspect Saturday, November 14, 2009
  22. 22. Better: Everything is suspect Saturday, November 14, 2009
  23. 23. Saturday, November 14, 2009
  24. 24. esc_html() Saturday, November 14, 2009
  25. 25. <?php $title = '<script> pwnage(); </script>' ?> <h1> <?php echo esc_html( $title ); ?> </h1> Saturday, November 14, 2009
  26. 26. <?php $title = '" onmouseover="pwnd();'; ?> <a href="#wordcamp" title=" <?php echo $title; ?> "> Link Text </a> Saturday, November 14, 2009
  27. 27. esc_attr() Saturday, November 14, 2009
  28. 28. <?php $title = '" onmouseover="pwnd();'; ?> <a href="#wordcamp" title=" <?php echo esc_attr( $title ); ?> "> Link Text </a> Saturday, November 14, 2009
  29. 29. <?php $url = 'javascript:pwnage();'; ?> <a href=" <?php echo esc_attr( $url ); ?> "> WRONG Link Text </a> Saturday, November 14, 2009
  30. 30. esc_url() Saturday, November 14, 2009
  31. 31. <?php $url = 'javascript:pwnage();'; ?> <a href=" <?php echo esc_url( $url ); ?> "> Link Text </a> Saturday, November 14, 2009
  32. 32. esc_url_raw(), sister of esc_url() Saturday, November 14, 2009
  33. 33. esc_ js() Saturday, November 14, 2009
  34. 34. <script> var foo = '<?php echo esc_js( $bar ); ?>'; </script> Saturday, November 14, 2009
  35. 35. CSRF Saturday, November 14, 2009
  36. 36. Authorization vs. Intention Saturday, November 14, 2009
  37. 37. Nonces action-, object-, user-specific time limited secret keys Saturday, November 14, 2009
  38. 38. Specific to •WordPress user •Action attempted •Object of attempted action •Time window Saturday, November 14, 2009
  39. 39. wp_nonce_field() Saturday, November 14, 2009
  40. 40. <form action="process.php" method="post"> <?php wp_nonce_field('plugin-action_object'); ?> ... </form> Saturday, November 14, 2009
  41. 41. check_admin_referer( ) Saturday, November 14, 2009
  42. 42. <?php // before output goes to browser check_admin_referer('plugin- action_object'); ?> Saturday, November 14, 2009
  43. 43. Still need to use current_user_can() Saturday, November 14, 2009
  44. 44. AJAX CSRF Saturday, November 14, 2009
  45. 45. • wp_create_nonce( 'your_action' ); • &_ajax_nonce=YOUR_NONCE • check_ajax_referer( 'your_action' ); Saturday, November 14, 2009
  46. 46. Privilege Escalation Saturday, November 14, 2009
  47. 47. current_user_can() Saturday, November 14, 2009
  48. 48. Set your salts! http://api.wordpress.org/secret-key/1.1/ Saturday, November 14, 2009
  49. 49. Stupid shit I see all the time Saturday, November 14, 2009
  50. 50. exec() Saturday, November 14, 2009
  51. 51. <form action="<?php echo $_SERVER['REQUEST_URI']; ?>"> Saturday, November 14, 2009
  52. 52. <a href="<?php echo $url; ?>" title="<?php echo $title; ?>"> <?php echo $text; ?> </a> <script> var foo = '<?php echo $js; ?>'; </script> Saturday, November 14, 2009
  53. 53. <a href="<?php echo esc_url( $url ); ?>" title="<?php echo esc_attr( $title ); ?>"> <?php echo esc_html( $text ); ?> </a> <script> var foo = '<?php echo esc_js( $js ); ?>'; </script> Saturday, November 14, 2009
  54. 54. Discussion Saturday, November 14, 2009

×