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!

