Nonces are your friends
First and foremost, a nonce can be defined as a “number used once” to help protect URLs and forms from misuse. WordPress nonces are made up of hash numbers and letters, but they have a limited lifetime after which they expire. They help protect against several types of attacks. For example, CSRF, Link spoofing, Spear phishing attacks just to name a few.
Example
Consider the possibility that an admin screen generates a URL like this, which deletes post 19.
http://example.com/wp-admin/post.php?post=19&action=trash |
When you visit the above URL, WordPress will check your authentication cookie information and, if you’re permitted, it will erase the post. Moreover, an attacker may use this to force your browser to visit that URL without your permission. For example, on a third-party page, the attacker could create a disguised link like this:
<img src=”http://example.com/wp-admin/post.php?post=19&action=trash” /> |
Moreover, this would cause your browser to send a request to WordPress, which would include your authentication cookie, and WordPress would accept it as a valid request.
When employing a nonce, for example, the URLs WordPress generates for the user look like this:
http://example.com/wp-admin/post.php?post=19&action=trash&_wpnonce=b192fc4204 |
If anyone tries to erase post 19 without having the correct nonce generated by WordPress and provided to the user, WordPress will respond with a “403 Forbidden” response to the browser.
Sanitizing, Validate and Escape Everything
Data validation should be handled by plugins and themes:
- When entering data into the database, validate and sanitize all untrusted data.
- Before being output in the Settings form fields, all untrusted data is escaped.
- Before being output in the Theme template files, all untrusted data is escaped.
For text inputs, plugins and themes should use esc attr(), and for text areas, esc html() or esc textarea().The WordPress API also provides esc url(), esc url raw(), esc js(), and wp filter kses ().
Bad Example:
<?php $url = 'javascript:pwnd()'; ?><a href="<?php echo $url; ?>">link</a>
Good Example:
<a href="<?php echo esc_url($url); ?>">link</a>
Use WordPress Settings API when possible
Using this method, you may add new settings fields (essentially, an option in the wp options database table that is completely handled by you) to existing WordPress sites. Furthermore, the only thing your callback function needs to do is produce the relevant HTML input and fill it with the old value; the saving will happen automatically.
How to make a setting:
<?php // add the admin options page
add_action('admin_menu', 'plugin_admin_add_page');
function plugin_admin_add_page() {
add_options_page('Custom Plugin Page', 'Custom Plugin Menu', 'manage_options', 'plugin', 'plugin_options_page');
}
?>
a. It adds a “Custom Plugin Menu” link to the settings menu.
b. Then redirected to a page called “Custom Plugin Page.”
c. To go there, you’ll need the “manage options” capability (admins only).
d. The link will be /wp-admin/options-general.php?page=plugin (so “plugin” should be something that only you will use).
e. Finally, the “plugin options page” function will construct the page’s content.
Create a Function for the Setting:
<?php // display the admin options page
function plugin_options_page() {
?>
<div>
<h2>My custom plugin</h2>
Options relating to the Custom Plugin.
<form action="options.php" method="post">
<?php settings_fields('plugin_options'); ?>
<?php do_settings_sections('plugin'); ?>
<input name="Submit" type="submit" value="<?php esc_attr_e('Save Changes'); ?>" />
</form></div>
<?php
}?>