Securing WordPress Input
By: Ryan Kienstra on: December 31, 2014 in: Security, WordPress VIP
Lessons From The VIP Standards
All data entered on a site should be checked, no mattter who entered it.
Even the administrator could click a malicious link.
There are two methods of securing WordPress input: validation and sanitization.
As with any security issue, use the most restrictive measure you can.
Therefore,
Prefer Validation to Sanitization
Validation only allows a small range of values.
It’s the preferred method for enterprise WordPress VIP sites.
The most restrictive means of validation is called “whitelisting.”
For example, a checkbox might only have values of "1"
and "0"
.
So you can verify that the value is either "1"
or "0"
.
In my plugin Bootstrap Swipe Gallery, I created the function bsg_is_one_or_zero( $value )
.
I then used it in the validation callback. You can see it in the full file on GitHub.
function bsg_is_one_or_zero( $value ) { return ( '1' == $value ) || ( '0' == $value ); }
Another way to do this is to use a “whitelist” array.
In the example above, I could have checked input against array( '0' , '1' )
.
This is more useful if you have a select box, or many options.
The full function would be:
bsg_is_one_or_zero( $value ) { $trusted_values = array( '0' , '1' ); return ( in_array( $value , $trusted_values , true ) ); }
As this entry in the codex notes, it’s important to use the argument true
as the third argument for in_array
.
This forces strict comparison.
Otherwise, the value "1 DROP DATABASE wpDB"
would return true.
Selected Validation Functions
intval( $value )
- Returns
$value
unchanged if it’s an integer. - Returns
$value
as an integer if it’s possible. A string$value
of"23"
would cause a return of the integer23
. - If it’s not possible, returns
0
. For example, the argument"foo_string"
would cause a return of0
.
absint( $value )
- Returns
$value
unchanged if it’s a non-negative integer. - If it’s possible, evaluates
$value
as an integer, and returns its absolute value. - Otherwise, returns
0
.
is_email( $address )
- Returns
$address
if it’s a valid email address. - Otherwise, returns
false
.
Sanitization
When Validation Isn’t Possible
Sometimes, there are too many possible values.
For example, there may be a text input. You should usually use sanitize_text_field
.
But use the most restrictive check you can when securing WordPress input.
If you only want urls, use esc_url
.
In my “Adapter” theme, I used esc_url
to sanitize a url passed to a filter.
This ensures that it has the right protocol (http, https, etc.). And no mailicious characters.
You can see the full file on GitHub.
add_action( 'after_setup_theme' , 'awp_editor_styles' ); function awp_editor_styles() { $style_path = apply_filters( 'awp_editor_style_path' , '' ); if ( $style_path ) { add_editor_style( esc_url( $style_path ) ); } }
See more sanitization functions in the WordPress Codex. Most of them start with sanitize_
, like sanitize_html_class
.
Code Reviews
Checking Your Work
It’s hard to always use the right function, and the stakes are high.
Having someone else review your code is almost necessary.
Weston Ruter was kind enough to do a review of my “Adapter” theme. He found some security issues.
All themes and plugins on wordpress.org are reviewed, as well.
Securing WordPress Input
By applying these guidelines, along with a reviewer, you’ll have a safer site.
What are your approaches to securing input?
Have your written custom functions for this?
Add your comment below.