By default, when you site is created a .htaccess files is put in your sites/default/files directory (or wherever your public files are) and your private directory (if defined). See file_ensure_htaccess()
and file_create_htaccess()
for the details.
The first line of each should read
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
This is an Apache directive that resets how it handles the files in that directory, and all subdirectories. Basically, it resets the handler to a non-existent function, which prevents files from being executed. See SA-2006-006 - Drupal Core - Execution of arbitrary files in certain Apache configurationsSA-2006-006 - Drupal Core - Execution of arbitrary files in certain Apache configurations security advisory for more info. I have double checked this on a few of my servers, and this does prevent PHP from being executed.
If this line is missing, then you need to figure out what happened and how it was removed.
If this not preventing execution by Apache, then you need to look at your server configuration. It is also conceivable that PHP may be executed here from the CLI via some server exploits.