What wp_verify_nonce() means? - wordpress

I've read the reference of this function on Wordpress but i still don't understand what this function really does.
I'm reading a tutorial about creating a meta box in wordpress and I have this code inside the function which saves the data:
if ( !wp_verify_nonce( $_POST[$meta_box['name'].'_noncename'], plugin_basename(__FILE__) )) {
return $post_id;
}
Can someone explain briefly what is the meaning of wp_verify_nonce() ?

The nonce is a 'number used once' - a code that WP uses to make sure that POST data is coming from a safe place. This is useful to make sure that your plugin does not end up digesting data from an unsafe source (see Cross-Site Request Forgery).
This blog post by Mark Jaquith is useful for understanding them.
[nonces] are unique to the WordPress install, to the WordPress user, to the action, to the object of the action, and to the time of the action (24 hour window). That means that if any of these things changes, the nonce is invalid. So if you (somehow) intercept a nonce being used by me, you would, first of all, only have 24 hours to use this key to attempt to trick me.
To create a nonce you must give wp_create_nonce a certain string, providing the 'context' for the nonce. It gives you back a string - the nonce itself. You then include this nonce as part of your POST request. The receiving page should then create a nonce of its own, using the same context, and see if they match up.
In this case, the context given is plugin_basename(__FILE__). This will generate the same string whenever it is called from within the same plugin (see here).
When your wp_verify_nonce recieves a nonce created under the same circumstances as specified by Mark, with the same context string, it returns true.
In short:
!wp_verify_nonce
returns true if wp_verify_nonce returns false.
($_POST[$meta_box['name'].'_noncename'],
First argument to wp_verify_nonce: the nonce to check. This code gets the nonce out of the post request, stored in the $_POST global.
plugin_basename(__FILE__) )
Second argument to wp_verify_nonce: the context for generating the new nonce against which the first will be checked.
{ return $post_id; }
If the nonce doesn't match, stop executing the current function, returning the variable $post_id.

Related

Detect WordPress REST API response?

What is the best way of detecting whether a WordPress response was generated by the REST API? There don't yet appear to be any conditional tags like is_feed() or is_page()?
Some hooks late in the WordPress lifecycle may alter output, such as naively appending html tags or debugging content. The problem is, if the response is a JSON blob from the REST API, appending content will invalidate the JSON response.
The is_feed conditional tag doesn't recognize REST API responses as feeds and returns false.
The rest_api_loaded method in wp-includes/rest-api.php defines a REST_REQUEST constant, that's helpfully labeled "Whether this is a REST Request". That constant then gets checked in class-wp-query.php. Here's a simple little is_rest conditional function based on that check:
function is_rest() {
return ( defined( 'REST_REQUEST' ) && REST_REQUEST );
}

javascript extension error: Cannot perform modifications

I'm building a custom dynamicValue extension for paw. However i'm not able to set header in the evaluate method. See the sample code below:
evaluate(context) {
const request = context.getCurrentRequest();
request.setHeader('Content-Type', this.contentType); // <-- this gives warning
return this.createSignable(request); // This returns a base64 string.
}
I get the warning saying Javascript extension error: Cannot perform modifications and the header is not set. ( when i comment out request.setHeader call, i get no warnings)
Can anyone please help me resolve this issue?
This is correct, you cannot use setters (set any value) in a dynamic value. In fact, the way Paw evaluates dynamic values is asynchronous and as multiple evaluations can take place simultaneously it would be impossible to record the modifications. For this reason, Paw is simply denying changes and no change is persisted during evaluation.
In the documentation, it's specified that these methods (like setHeaders) is only available for importer extensions. Sorry for the inconvenience!
I think to achieve what you're trying to do, you would need two dynamic values one set in the Authorization header and one set in the Content-Type header.
Alternatively, in the future we're going to add request post-processors, so you'll be able to mutate the computed request ready to be sent to the server for additional modifications.

Putting ID in Get request

I have a following url:
/Reports?reportId={value}
The problem is that not every user can see every report, but with this kind of url he can actually enter whatever ID he wants and access that report.
So my question is should I just add a server side validation to check if currently logged user has access to this report and if not return some Anauthorized response, or send this via POST so he cannot see the url and change it (if this approach is safe enough).
And generally I want to know if it is bad idea to send ID in url? Maybe it is better to use Guids for ID-s then instead of integers?
So my question is should I just add a server side validation to check if currently logged user has access to this report and if not return some Anauthorized response
Yes, a thousand times this.
or send this via POST so he cannot see the url and change it (if this approach is safe enough).
No. Never this. This is security through obscurity. POST data is not hidden in any way.
if it is bad idea to send ID in url? Maybe it is better to use Guids for ID-s then instead of integers?
No, that does not matter at all. That also is security through obscurity. The GUIDs still show up in plaintext, so anyone with access to browser history, firewalls, or the network in general can inspect and replay the traffic containing GUIDs.
See also Why not expose a primary key - Programmers Stack Exchange.
In addition to CodeCaster's answer:
IDs in URLs can indirectly reveal some business related information. For example from contract ID=963 your competitor may learn that you did since last month 40 new contracts (ID was e.g. 923) and earned cca 50k. This is sometimes not desired.
It's quite common though to mask ID e.g. by converting into a masked string. I usually use openssl_encrypt and openssl_decrypt respectively.
Here's example for converting ID to/from masked string:
public static function encryptOpenssl($textToEncrypt, $encryptionMethod = 'AES-256-CFB', $secretHash = "12#rk!", $raw = false, $password = ''){
$length = openssl_cipher_iv_length($encryptionMethod);
$iv = substr(md5($password), 0, $length);
return openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash, $raw, $iv);
}
public static function decryptOpenssl($textToDecrypt, $encryptionMethod = 'AES-256-CFB', $secretHash = "12#rk!", $raw = false, $password = ''){
$length = openssl_cipher_iv_length($encryptionMethod);
$iv = substr(md5($password), 0, $length);
return openssl_decrypt($textToDecrypt, $encryptionMethod, $secretHash, $raw, $iv);
}
You can of course use any other obfuscating algo, e.g. rot13, exchanging character positions, character mapping, prepending/appending irrelevant chars etc.

how to create this nonce?

I need a bit of help understanding what this means:
https://wordpress.org/plugins/json-api/other_notes/#Method:-create_post
Required argument
nonce - available from the get_nonce method (call with vars controller=posts >and method=create_post)
How should I create that nonce?
I'm trying:
wp_nonce_field( 'posts', 'create_post' );
Note that you don't have to use the wordpress nonce functionality directly, instead use Json Api's given method in the post controller.
You may try the solution of bbottema
First you need a nonce (Number used ONCE), which is a temporary key you'll use to be able to invoke the API with:
http://yourblog.com/?json=core.get_nonce&controller=posts&method=create_post&callback=?
This gives you a nonce number (be sure to use &callback=? as it marks the content as jsonp, or you'll get a similar -but invalid- nonce).
Then use this nonce to create a post:
http://yourblog.com/?json=posts.create_post&nonce='+nonce+'&title='+title+'&content='+content+'&status=publish (or draft, or leave it out altogether)
Make sure you have the 'posts' controller enabled in your wordpress plugin JSon API settings. Check this manual for what JSon data structures you can expect back from these calls.
Now, here's the tricky part: you need to be already logged into the wordpress site, because with this JSon API, you can't log in. I haven't figured that part out yet, so I'm still looking for a good solution myself. I tried manually posting and also width ajax but with limited results considering I'm missing a WordPress test cookie in my headers (at least this is the main difference I see when logging in from the site and doing it manually)
JSON API USER Does not work, it will only work if you are logged in to the website with an account of ADMIN ROLE!.. otherwise it won't create valid nonce

What does an empty input's value when using POST in asp?

I am using asp (JScript as my language) and working with getting data from a form that is sent using POST.
Specifically, I have a text input and I want to check if it was left empty. When leaving it empty, and including Response.Write(Request.form('opt2Dur')) in the called page, nothing prints (doesn't print null or undefined).
My thought was that it was just an empty string so I included this: Response.Write(Request.form('opt2Dur') === ''), however this printed false.
It will print true if I use Response.Write(Request.form('opt2Dur') == '') (== not ===). What is the true value that I can check against using ===? Or, in this case will it be sufficient to check with just ==?
Thanks for any help.
In scripting languages with "flexible" types and default values it's very easy to get confused with actual data types.
The actual type of each Request item (both QueryString and Form, it doesn't matter) is some sort of Array as it also supports more than one form element with the same name submitted to the ASP handler. It's mentioned in the documentation as well:
The Form collection is indexed by the names of the parameters in the request body. The value of Request.Form(element) is an array of all the values of element that occur in the request body.
Since the === also take into account type, it will return false in your case as array is not a string.
I wasn't able to find the exact actual type and reproduce it with local variable (it's not any plain array) so if you are keen on using the strict comparison operator, check the Count:
Response.Write(Request.Form('opt2Dur').Count === 0);

Resources