{"id":140491,"date":"2015-05-03T08:00:18","date_gmt":"2015-05-03T12:00:18","guid":{"rendered":"http:\/\/premium.wpmudev.org\/blog\/?p=140491"},"modified":"2015-05-04T04:59:17","modified_gmt":"2015-05-04T08:59:17","slug":"wordpress-nonces","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/wordpress-nonces\/","title":{"rendered":"Using Nonces to Strengthen WordPress Security"},"content":{"rendered":"<p>WordPress security is a hotly debated topic and as I mentioned in my\u00a0<a href=\"https:\/\/wpmudev.com\/blog\/wordpress-aint-perfect\/\" target=\"_blank\">WordPress Ain&#8217;t Perfect<\/a> article a while back, it mostly comes down to issues with plugins and themes, not WordPress itself.<\/p>\n<p>Nonces are one of the best ways to protect users from possible threats. They are used to secure user actions initiated by the plugin such as the submission of a form, the deletion of post or anything else that could expose the database.<\/p>\n<p>In this Weekend WordPress Project\u00a0I&#8217;ll describe the problem nonces are meant to solve and how you can use them to make your products more secure.<\/p>\n<h2>Why We Need Nonces<\/h2>\n<p>Let&#8217;s say you&#8217;re writing a plugin that\u00a0allows the user to delete a post from the front-end. For the sake of simplicity the mechanism to delete a post is a link that takes you to <code>http:\/\/mysite.com\/2015\/02\/12\/my-article\/?delete=true<\/code>. In other words, the link to the article with a query string attached.<\/p>\n<p>The code you implement on that page checks if the user is an admin and if so, the post is deleted, the user is redirected back to the main page.<\/p>\n<p>This seems safe right? After all, you did check if the user was an admin right?<\/p>\n<p>Sadly, this isn&#8217;t enough.\u00a0There are two things you need to check before each action is taken: permission and intent.<\/p>\n<figure class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"attachment-490x490\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/05\/security.jpg\" alt=\"WordPress nonces can help strengthen the security of your website.\" width=\"490\" height=\"326\" \/><figcaption class=\"wp-caption-text\">WordPress nonces can help strengthen the security of your website.<\/figcaption><\/figure>\n<p>You have checked that the user has permission, but you can&#8217;t be sure the user actually does want to delete the post.<\/p>\n<p>Imagine I sent you an email saying I found a typo in one of your posts and I link it in. If I create a link in an email you won&#8217;t see the target, just the clickable text. So if I append the <code>?delete=true<\/code> string to the end you will end up deleting the post, even though you never meant to.<\/p>\n<p>This is where nonces come in. A nonce is a special code that gets generated at the source of the action. When using a nonce the link may look something like this: <code>http:\/\/mysite.com\/2015\/02\/12\/my-article\/?delete=true&amp;_wpnonce=234283223<\/code>. Since the nonce will always be different I won&#8217;t be able to send you a simple link since the deletion process won&#8217;t work without the correct nonce.<\/p>\n<h2>What Are Nonces Anyway?<\/h2>\n<p>Nonce are short for &#8220;number used once,&#8221; and they are used in cryptography for securing data by sending a one-time numeric code next to them.<\/p>\n<p>WordPress implements nonces a bit differently because they are neither numbers nor used only once but their purpose and use is very close. WordPress uses a hash and nonces can sometimes be used more than once, they have a short expiration time.<\/p>\n<h2>Using WordPress Nonces<\/h2>\n<p>The process is a fairly simple two-step affair: You generate a nonce at the origin of an action (placing it in a link or as a hidden field in a form) and validate it at the target. You&#8217;ll only need to know a couple of functions, here goes:<\/p>\n<h3>Adding Nonces to Forms<\/h3>\n<p>To add a nonce to a form you&#8217;ll need to add a hidden field with a name and a value. WordPress has you covered with the <code>wp_nonce_field()<\/code> function.<\/p>\n<p>In its most simple form you can use it with just one parameter:<\/p>\n<div class=\"gist\" data-gist=\"62f2039a45defb78df32bc9e737ac6fe\" data-gist-file=\"simple-nonce-field.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/62f2039a45defb78df32bc9e737ac6fe.js?file=simple-nonce-field.php\">Loading gist 62f2039a45defb78df32bc9e737ac6fe<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>This would create two fields for you, one for the nonce and one for a referrer, which WordPress can also check.<\/p>\n<div class=\"gist\" data-gist=\"ea48c47ca7b31cb4cd990064e4353d74\" data-gist-file=\"simple-nonce-field-output.html\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/ea48c47ca7b31cb4cd990064e4353d74.js?file=simple-nonce-field-output.html\">Loading gist ea48c47ca7b31cb4cd990064e4353d74<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>The function actually gives you four parameters to let you fine tune. The first parameter defines the action that is taken with the nonce. This doesn&#8217;t show up in the field, it is contained in the hash. The second parameter modifies the name, which is <code>_wpnonce<\/code> by default. The third parameter is a boolean value which controls whether or not the referrer is checked (true by default). Finally, the fourth is a boolean which determines whether or not the field is echoed \u2013 it is true by default.<\/p>\n<p>One important rule to follow: Always make the action name (the first parameter) as specific as possible. Don&#8217;t just name it &#8220;delete-post&#8221;, make it &#8220;delete-post-[post_ID].<\/p>\n<p>On the other end of the action you&#8217;ll need to verify the nonce. This would be where the form&#8217;s action parameter takes you. To verify the nonce use this simple code:<\/p>\n<div class=\"gist\" data-gist=\"996265fdc885d0bbffeb9c79a2405fa8\" data-gist-file=\"verify-nonce.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/996265fdc885d0bbffeb9c79a2405fa8.js?file=verify-nonce.php\">Loading gist 996265fdc885d0bbffeb9c79a2405fa8<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Note that this will only work if your form uses the <code>post<\/code> method. You really should be using <code>post<\/code> for anything sensitive though.<\/p>\n<h3>Adding Nonces To URLs<\/h3>\n<p>Sometimes you want to initiate an action through a link, especially in the admin area. Since links are essentially passed on as query parameters you can easily tack them on to links as well.<\/p>\n<p>You can use the <code>wp_nonce_url()<\/code> function to get this one done. Here&#8217;s how.<\/p>\n<div class=\"gist\" data-gist=\"433c2c526329b1f5f60a23096b62556e\" data-gist-file=\"nonce-url.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/433c2c526329b1f5f60a23096b62556e.js?file=nonce-url.php\">Loading gist 433c2c526329b1f5f60a23096b62556e<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>The end result will be a URL that looks something like: <code>http:\/\/mysite.com?p=553&amp;_mynonce=7278c82a8f3<\/code>. As you can see this is very similar to what we did with forms, the only difference is that the nonce is passed in the URL as <code>GET<\/code> parameters.<\/p>\n<p>You can verify the nonce using much the same method as before. This time let&#8217;s add the proper action name with the ID and use <code>GET<\/code> variables.<\/p>\n<div class=\"gist\" data-gist=\"cf5e01737f7fea5d68a9d0fc4e2bfdec\" data-gist-file=\"verify-get-nonce.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/cf5e01737f7fea5d68a9d0fc4e2bfdec.js?file=verify-get-nonce.php\">Loading gist cf5e01737f7fea5d68a9d0fc4e2bfdec<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<h2>Overview<\/h2>\n<p>That was pretty simple wasn&#8217;t it? And it adds a big layer of security to your product.<\/p>\n<p>Nonces should really be used any time you want to initiate a user action otherwise your application is vulnerable to all sorts of attacks.<\/p>\n<p>Don&#8217;t forget that nonces only check for intent. You&#8217;ll still need to make sure the user has the proper permissions as well.<\/p>\n<p>Image credit: <a title=\"Pixabay\" href=\"http:\/\/pixabay.com\/en\/security-protection-anti-virus-265130\/\" rel=\"noopener\" target=\"_blank\">Pixabay<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WordPress security is a hotly debated topic and it mostly comes down to issues with plugins and themes, not WordPress itself. Nonces are one of the best ways to protect from possible threats. But what are they and how do you use them?<\/p>\n","protected":false},"author":344049,"featured_media":209806,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"blog_reading_time":"","wds_primary_category":0,"wds_primary_tutorials_categories":0,"footnotes":""},"categories":[263],"tags":[9798],"tutorials_categories":[],"class_list":["post-140491","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-weekend-wordpress-projects"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/140491","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/users\/344049"}],"replies":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/comments?post=140491"}],"version-history":[{"count":9,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/140491\/revisions"}],"predecessor-version":[{"id":218987,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/140491\/revisions\/218987"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/209806"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=140491"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=140491"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=140491"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=140491"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}