It's important to not only to try to prevent them from being uploaded, but to make sure that any directory which is writable by the web server or php engine, is not executable. In the case of WordPress, this can largely be mitigated by using specific location parameters in nginx which allow the execution of your intended entry points such as the primary index.php file, rather than a blanket fastcgi forward for all urls ending in .php.
`location ~ .php$ { [forward to fcgi] }`
This is a common configuration that allows the client to execute any php file within the web root. If you accidentally allow a php file to be uploaded, it may be executed.
Instead something like the following means that the web server will not allow arbitrary php files to be executed, only the ones you want to be executed:
I've converted my colleagues over to nginx from Apache, and one of the nicest parts of it (for PHP) is how easy it is to make sure nginx is only serving exactly what you want it to, and no more. The blanket "run any PHP in /var/www" configs that seem to be the copy-pasta default make me sad.
Of course - there is still the possibility that an uploaded script can be executed by the framework, but at least it requires an exploit to do the upload and another one to make your application execute it. If arbitrary php files can be executed, they only need to be able to upload them.
`location ~ .php$ { [forward to fcgi] }`
This is a common configuration that allows the client to execute any php file within the web root. If you accidentally allow a php file to be uploaded, it may be executed.
Instead something like the following means that the web server will not allow arbitrary php files to be executed, only the ones you want to be executed:
`location ~ /(index\.php|wp-admin/ajax.php)$ { [cgi] }`
(Just an approximation - I don't feel like looking up the exact expression I use.)