2

I'm using Windows 7 x64 Enterprise, IIS, and PHP 5.6.32 in my development environment. My application's website has the following settings:

  • Anonymous authentication: disabled
  • Windows authentication: enabled (Negotiate, Negotiate:Kerboeros, NTLM)
  • App Pool: domain account.
  • Other than the default PHP extensions, I have Microsoft's PHP SQL Server driver (3.2 version) used in Windows Authentication mode.

My production server is the same setup running on Server 2008 R2.

I am needing to use exec(), shell_exec(), etc. to execute an executable (pdftk if it matters). However, whenever I use any of these functions, I always get "Unable to fork XXX" in the PHP error log. I've tried runing whoami, ping xxx, and other simple commands with the same result. None of the typical shell functions will work--they always result in the same error. I have checked my php.ini file and verified those functions haven't been disabled.

However, in my production environment, I do not have this problem, and I have no clue why. It only seems to be affecting my development environment. During my research, I did stumble across this (http://tech.trailmax.info/2012/12/php-warning-shell_exec-unable-to-execute-on-iis-7/) which, for some reason, does fix my problem; but, it completely breaks my SQL Server Windows authentication (which I need).

I have also disabled my antivirus in hopes maybe it was the culprit. It was not.

While doing more troubleshooting, I did find that proc_open() does work. We are using Prince for generating PDFs and I noticed it was working, while my exec() wasn't. When I looked at the Prince class, I discovered it was using proc_open() which explains why it seems to work.

Does anyone know why exec() and the related functions seem to work without issue in my production environment and not my development environment? And why does proc_open() work but the other shell functions do not? Thanks!

6
  • Are you trying to run a script from your http directory (within root directory of your website)? Commented Nov 4, 2017 at 17:13
  • The PHP script I'm executing is in my wwwroot directory. The executable I'm trying to execute is located outside of that directory. But, like I said, I can't execute anything like ping, whoami, etc. Commented Nov 6, 2017 at 13:46
  • Just to be sure we're on the same page: exec('cmd /c whoami 2>&1',$out,$exitcode); Both $out and $exitcode are empty -- or does it display an error? What about logs? Commented Nov 6, 2017 at 15:55
  • This is what I get when I run exec for your example: var_dump($out) = array(0) { }; var_dump($exitcode) = int(-1) . In the PHP error log, I get this error: PHP Warning: exec(): Unable to fork [cmd /c whoami 2>&1] in C:\inetpub\aggframework\app\apinvoices\view\view_payment_summary.php on line 29 Commented Nov 6, 2017 at 18:17
  • Do you have fastcgi.impersonate=1 set in your PHP.INI file? Commented Nov 6, 2017 at 22:18

2 Answers 2

1

Check the permissions on file 'C:\WINDOWS\system32\cmd.exe'. You need read/execute permission on this file.

I would recommend using the sysinternals Process Monitor 'procmon.exe' to confirm the user that is trying to run 'cmd.exe'. Filter on 'Process Name' is 'php-cgi.exe' and 'Path' ends with 'cmd.exe'. Look at the event properties for the task with the access denied error, and it will show you the 'Impersonating' user name. This is usually the 'Internet Guest Account', often 'NT AUTHORITY\IUSR'.

Sign up to request clarification or add additional context in comments.

Comments

0

I wanted to post an update to this since I figured out the issue. The answer can be found here in the very last post by 1heer2351 at zonnet dot nl1:

Located the problem and have been able to fix it.

I am using a special user for my Application Pool (say AppPoolUser), so PHP runs as this user. The new exec function uses CreateProcessAsUser() with impersonation. This means that the AppPoolUser must have the right to change the process level token.

You can assign this right to the user in the "Local Security Settings" -> User Rights Assignment.

I have granted my AppPoolUser the "Replace a process level token" setting -> fork error has gone.

Thought this might be useful information, so access is required to cmd.exe but in addition the "Replace a process level token" setting.

This is exactly what I did. I had created a new App Pool User using my domain account. By default, the Replace a process level token setting includes DefaultAppPool. Since I created a new App Pool User, it was not included in this policy setting. Adding the App Pool User I created resolved my issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.