How to secure your wordpress plugin

how-to-secure-your-wordpress-plugin

When I browse through odesk.com, I always stumble across some job listings like “wordpress website hacked” or “Who can help me with my hacked WordPress-Sites?“. I feel sorry for these webmasters. At the same time, as a wordpress plugin developer I ask myself “are my plugins secure?”. I’m not %100 sure but at least they’re secure enough to avoid notorious hacking techniques.

Sun Tzu said: If you know the enemy and know yourself you need not fear the results of a hundred battles. To make secure wordpress plugin, you should know how hackers hack your plugin.

In this article, I will show you real-world exploits that can take advantage of the weakness of some particular wordpress plugins to hack server and provide solutions to tech you how to fix the weakness

Scenario 1 

WordPress Developer Formatter CSRF Vulnerability

Vulnerability

“no nonce given”

What is nonce? According to http://codex.wordpress.org/Function_Reference/wp_nonce_field, the nonce field is used to validate that the contents of the form came from the location on the current site and not somewhere else. For the maxiumum security, the nonce is also time sensitive and it’ll expire.

Solution

The form code:

<form method="post" enctype="multipart/form-data">
<?php wp_nonce_field( 'plugin_settings_page', 'plugin_settings_page' ); ?>
...........
</form>

The place where handle user input:

if(wp_verify_nonce( $_POST['plugin_settings_page'], 'plugin_settings_page' )){
//do something here
}

Other than wp_nonce_field, there is another nonce function wp_nonce_url which will generate a URL with nonce. Nonce validation function is wp_verify_nonce

Scenario 2

WordPress Easy Webinar Plugin Blind SQL Injection Vulnerability

Vulnerability

www.example.com/wp-content/plugins/webinar_plugin/get-widget.php?wid=3′ or ‘x’='x

The “3″ is grabbed from $_GET['wid'] and unfortunately, the plugin author didn’t sanitize $_GET['wid'] which results in SQL injection.

Solution

$wid = absint($_GET['wid']);

Scenario 3, what if wid should be string?

Solution

$wid = esc_sql($_GET['wid']);

OR

global $wpdb;
$sql = $wpdb->prepare('SELECT * FROM WP_MYTABLE WHERE wid = "%s"',$_GET['wid']);
//prepare will sanitize wid

Scenario 4, File Uploader

WordPress File Uploader Plugin PHP File Upload Vulnerability

Vulnerability

No file extension checking

Solution

if(!in_array(strtolower(pathinfo($_FILES['postimage']['name'], PATHINFO_EXTENSION)),array('jpg','png','gif'))){
exit("Invalid image");
}
if ( ! function_exists( 'wp_handle_upload' ) ) 
require_once( ABSPATH . 'wp-admin/includes/file.php' );
$movefile = wp_handle_upload( $_FILES['file'] );

Scenario 5, File Inclusing

WordPress TheCartPress Plugin 1.1.1 Remote File Inclusion

Vulnerability

$path = $_REQUEST['tcp_class_path'];
require_once( $path );

Solution

if(in_array($path,array('a.php','b.php','c.php')))
require_once( $path );

Scenario 6, Predictable File Name

Recently, I’m building a database backup plugin and I store the SQL files in plugin folder. The file name pattern is date(‘Y-m-d-H-i-s’).

Vulnerability

Disclose the database backup SQL files to hacker.

Solution
Add some random numbers to the file name.

$rand = mt_rand(1,mt_getrandmax());
$filename = date('Y-m-d-H-i-s').'-'.$rand.'.sql';

Besides, add a blank index.html or index.php to the backup folder for prevention of directory listing.

Conclusion

Most fatal attacks are involved with SQL Injection. If you are always using $wpdb->prepare to operate sql or update_option/get_option to store data, then your plugin is %60 secure.

To make your plugin safe, keep this rule in mind: never trust user input

WordPress also creates a useful list of data validation functions for reference. Data Validation

If you have any idea, please don’t hesitate to share with us!

Share and Enjoy

    FacebookTwitterGoogle PlusLinkedInStumbleUponPinterestRedditTumblrDiggEmailPrint

Related Posts