Wordpress does not use traditional nonces, instead binding them to a specific form action and user session combination, and persisting them for multiple usage over two ticks (default 12 hours each), which means they are by default valid for up to a full day, and may be repeatedly used over that time period, as well as being "refreshed" after a use to reset their time period entirely. This has been consistently criticized for a number of years by security professionals as misleading and insecure, and the WordPress core team has defended their stance by claiming that the requirement that someone has both the user session as well as the actual nonce makes this a negligible threat, although both a compromised host as well as a site that does not have valid ssl protection can make this pretty easy to accomplish.
The underlying issue you are encountering is symptomatic of the fact that a WordPress nonce is not a nonce at all. It is essentially an access control hash used repeatedly for a short duration for a single form action, and has no mechanism in place to insure its single use. This is why you were able to successfully intercept and re-use the nonce. FYI, this behavior can also be recreated pretty easily in Zed Attack Proxy, Wireshark, Charles Proxy, and numerous other similar utilities. Burp is not the only tool that is capable of uncovering this weakness.
You do however have some recourse to correct this if you want, but it is rather involved and not particularly simple to accomplish.
The following functions are pluggable, which means you can override them with your own, and also control the system interpretation of what a nonce is. You will need to provide your own nonce system using these specific methods, and return identical values to the original expected ones so you don't break plugins/core code functionality:
You could, for example, provide your own nonce implementation using a support from a package such as elhardoum/nonce-php or wbswjc/nonce, and then implement it through a custom plugin that overrides the above pluggable functions and uses them as wrappers for your own nonce implementation, although this is not incredibly straightforward and will require a great deal of custom logic to implement.
You will need to not only override the above pluggable functions, but will also need to call apply_filters
similarly to their own source, properly nullify whatever changes plugins attempt to make that are bound to those filters, and also return an expected value in the exact same format as the original so you do not disrupt how other plugins/themes you may be using have implemented them.
If you believe that there is sufficient risk, or that the data your site is safeguarding is of sufficient importance, it is likely worth the effort. If you are not handling financial transactions or sensitive data, are properly secured behind ssl, or have no particular interest in writing a custom implementation of nonces and subsequently maintaining it to work around the ways it inevitably breaks numerous plugins who expect the default lax implementation to be present, then you are probably best off taking the core devs at their word and using the defaults, provided you update frequently, have a strong security plugin like wordfence or sucuri, and routinely run updates on all of your plugins/themes.
As an absolute minimum, you pretty much must have SSL in place to mitigate MITM attacks, and should use proper access control headers to mitigate CSRF.
$_POST
, nor the step(s) by which you are creating the draft.... – Pawsner