The Problem
这个问题
I have a PHP script that uses shell_exec
to run a pdf-to-text converter. To simplify the problem I've created a short script that uses shell_exec
to just echo the output of the dir
command.
我有一个PHP脚本,它使用shell_exec来运行pdf到文本的转换器。为了简化这个问题,我创建了一个简短的脚本,它使用shell_exec只回显dir命令的输出。
<?php
$cmd = 'C:\\WINDOWS\\system32\\cmd.exe /c ';
echo shell_exec($cmd.' dir');
?>
When I run this on my Apache server, everything works as expected. When I switch to IIS, it's as though the line is skipped entirely: no errors, no output, no logs, no nothing.
当我在我的Apache服务器上运行这个时,一切正常。当我切换到IIS时,就好像完全跳过了这一行:没有错误,没有输出,没有日志,什么都没有。
Unfortunately, I need to use IIS because I'm going to authenticate my users against active directory.
不幸的是,我需要使用IIS,因为我将根据active directory对我的用户进行身份验证。
Here's what I've tried so far:
以下是我迄今为止所尝试的:
- Issue the command through
cmd.exe /c
rather than issuing it directly - 通过cmd发出命令。exe /c而不是直接发出
- Give
Read & Execute
permission toSERVICE
on "C:\WINDOWS\system32\cmd.exe" - 给予“C:\WINDOWS\system32\cmd.exe”的读取和执行权限
- Give
Read & Execute
permission toNETWORK SERVICE
on "C:\WINDOWS\system32\cmd.exe" - 给予“C:\WINDOWS\system32\cmd.exe”网络服务的读取和执行权限
- Give
Read & Execute
permission toIUSR_MACHINENAME
on "C:\WINDOWS\system32\cmd.exe" - 给予IUSR_MACHINENAME“C:\WINDOWS\system32\ system32\cmd.exe”的读取和执行权限
- Give
Read & Execute
permission toEveryone
on "C:\WINDOWS\system32\cmd.exe" (don't worry, it didn't stay like that for long, haha) - 在“C:\WINDOWS\system32\cmd”中给每个人读和执行权限。exe(别担心,这种情况不会持续太久,哈哈)
- Run PHP as an ASAPI module
- This is my standard configuration
- 这是我的标准配置。
- 作为ASAPI模块运行PHP这是我的标准配置
- Run PHP as a CGI extention
- This does not work, I get an error:
CGI Error The specified CGI application misbehaved by not returning a complete set of HTTP headers.
- 这不起作用,我得到一个错误:CGI错误指定的CGI应用程序没有返回完整的HTTP头集。
- This does not work, I get an error:
- 运行PHP作为CGI扩展这不起作用,我得到一个错误:CGI错误指定的CGI应用程序没有返回一组完整的HTTP头。
- In IIS Manager, set
Execute Permissions
toScripts and Executables
on your website - 在IIS管理器中,将执行权限设置为您的网站上的脚本和可执行文件。
- Added html markup and other php functions to script to see if that gets processed; it does. It's as if the
shell_exec
bit just gets skipped. - 在脚本中添加html标记和其他php函数,以查看是否对其进行处理;它的功能。这就好像shell_exec位刚刚被跳过。
Thank you so much for looking at this question, I am now pulling my hair out with the problem
非常感谢你看这个问题,我现在正为这个问题抓狂
Cheers, Iain
欢呼,伊恩
Update 1
更新1
I really didn't want to do this, but as a stop gap until I find a proper solution I'm running Apache on the web server (which runs shell_exec fine) and I call my apache script via cURL. It's ugly, but it works :).
我真的不想这样做,但在找到合适的解决方案之前,我只是暂时停下来,在web服务器上运行Apache(它运行shell_exec很好),并通过cURL调用Apache脚本。它很丑,但很管用:)。
Update 2
更新2
I'm beginning to think this isn't so much an issue with IIS or permissions as such, but perhaps a result of some policy we have on our network - although I can't imagine what. Any ideas from left of field?
我开始认为这不是IIS或权限的问题,而是我们网络上的一些策略的结果——尽管我无法想象会发生什么。你有什么想法吗?
6 个解决方案
#1
3
Below is a more systematic way to determine which user needs to be granted permission
下面是一种更系统的方法来确定需要授予哪些用户权限
Confirm that you have the following executables in C:\WINDOWS\SYSTEM32 (or more generically %systemroot%\system32)
确认你下面的可执行文件C:\WINDOWS\SYSTEM32 % systemroot % \ system32系统普遍(或更多)
cmd.exe
whoami.exe
Check the current ACL for these executables
检查当前ACL以获取这些可执行文件
c:\windows\system32> cacls cmd.exe
c:\windows\system32> cacls whoami.exe
If the user "Everyone" is not granted Read (R) access, then TEMPORARILY grant as follows
如果用户“Everyone”未被授予Read (R) access,则临时授予如下权限
c:\windows\system32> cacls cmd.exe /E /G everyone:R
c:\windows\system32> cacls whoami.exe /E /G everyone:R
Create whoami.php with the following content
创建显示本用户信息。php包含以下内容
<?php
$output = shell_exec("whoami");
echo "<pre>$output</pre>";
?>
Load whoami.php on a web browser and note the username displayed e.g. in my case it showed
加载显示本用户信息。在web浏览器上的php并注意显示的用户名,例如在我的例子中显示的
ct29296\iusr_template
ct29296 \ iusr_template
Revoke "Everyone's" permission if it had to be added in above steps
如果必须在上述步骤中添加“每个人”权限,则撤销该权限
c:\windows\system32> cacls cmd.exe /E /R everyone
c:\windows\system32> cacls whoami.exe /E /R everyone
Grant only the username found in step 5 with the Read+Execute permission (R) to cmd.exe
只将第5步中找到的用户名与Read+Execute权限(R)授予cmd.exe
c:\windows\system32> cacls cmd.exe /E /G ct29296\iusr_template:R
Remember to use the correct username for your own system.
记住要为自己的系统使用正确的用户名。
See: http://www.myfaqbase.com/index.php?q=php+shell_exec&ul=0&show=f
参见:http://www.myfaqbase.com/index.php?q=php显示= f + shell_exec&ul = 0
#2
2
Here's a few points:
这里有几点:
- Regarding PHP skipping the
shell_exec
function, make sure that PHP is not running in safe mode. From the PHP manual - on the shell_exe page: - 关于PHP跳过shell_exec函数,请确保PHP没有在安全模式下运行。从PHP手册-关于shell_exe页面:
Note: This function is disabled when PHP is running in safe mode.
注意:当PHP在安全模式下运行时,此函数将被禁用。
It also appears that this is quite a known problem with executing shell commands from PHP in Windows. The consensus seems to be that the best way to get it to work is to have PHP running in FastCGI mode (I know you tried this already and said you couldn't get it to work - hence my second point). You may find this Microsoft IIS Forum thread helpful.
在Windows中执行PHP的shell命令也是一个众所周知的问题。人们的共识似乎是,让PHP运行在FastCGI模式下是最好的方法(我知道您已经尝试过了,并且说您无法让它正常工作——这是我的第二个观点)。您可能会发现这个Microsoft IIS论坛线程很有用。
- Now, as far as having to run PHP on Windows in order to authenticate against Active Directory - you don't have to!
- 现在,就必须在Windows上运行PHP才能对Active Directory进行身份验证而言——您不必这么做!
Apache provides LDAP authentication via the mod_auth_ldap. And PHP provides LDAP support through the following functions:
Apache通过mod_auth_ldap提供LDAP身份验证。PHP通过以下函数提供LDAP支持:
- ldap_connect
- ldap_connect
- ldap_bind
- ldap_bind
- ldap_search
- ldap_search
- ldap_get_entries
- ldap_get_entries
Active Directory is an implementation of LDAP. So, you with any LDAP client you can perform authentication against Active Directory.
Active Directory是LDAP的一个实现。因此,对于任何LDAP客户端,都可以对活动目录执行身份验证。
- An example of how to authenticate with Active Directory from PHP.
- 如何使用PHP的活动目录进行身份验证的示例。
P.S. You can either use the Apache mod_auth_ldap, or the PHP LDAP functions - you don't need to use both at the same time to make this work. The Apache mod_auth_ldap works at the HTTP protocol level, whereas the PHP LDAP Functions give you more control over the authentication and authorization process.
您可以使用Apache mod_auth_ldap,也可以使用PHP LDAP函数——您不需要同时使用这两个函数来完成这项工作。Apache mod_auth_ldap在HTTP协议级别上工作,而PHP LDAP函数提供了对身份验证和授权过程的更多控制。
#3
1
couple of notes
两个笔记
if you want to execute a .exe directly, you can use proc_open() with $other_options=array('bypass_shell'=>TRUE)
如果您希望直接执行.exe,可以使用proc_open()和$other_options=数组('bypass_shell'=>TRUE)
also procmon.exe (sysinternals) is you best friend when digging into this class of problem
procmon。当你深入研究这类问题时,exe (sysinternals)是你最好的朋友
#4
0
I'd say Read & Execute
permission to the User thats running IIS (if thats not IUSR_MACHINENAME)
我要对运行IIS的用户说Read & Execute权限(如果不是IUSR_MACHINENAME)
#5
0
Unfortunately, I need to use IIS because I'm going to authenticate my users against active directory.
不幸的是,我需要使用IIS,因为我将根据active directory对我的用户进行身份验证。
The premise for basing your application on IIS is flawed. There's nothing to stop you doing this with Apache. Indeed, you don't even need to run it on a MS-Windows OS.
将应用程序基于IIS的前提是有缺陷的。没有什么可以阻止你用Apache做这件事。实际上,您甚至不需要在MS-Windows操作系统上运行它。
Have a google for how to set up all this up.
有一个谷歌如何设置这一切。
Note that with IIS and local clients potentially using NTLM, the security policy gets thrown out of the window. The IIS handler thread may run with the credentials of a NTLM MSIE client. Or not. Debugging this stuff will drive you mad!
注意,对于可能使用NTLM的IIS和本地客户端,安全策略将被抛出窗口。IIS处理程序线程可以使用NTLM MSIE客户机的凭据运行。与否。调试这些东西会让你发疯的!
C.
C。
#6
0
I added the user NETWORK SERVICE with READ & EXECUTE, READ to the directories where the executables of my application resides. Since this alteration, the problem is gone. Nevertheless, it's also neccessary to grant the permissions READ & EXECUTE, READ for IUSR_ to cmd.exe.
我添加了READ & EXECUTE的用户网络服务,并读取应用程序的可执行文件所在的目录。由于这种改变,问题就消失了。尽管如此,还需要向cmd.exe授予读和执行权限,为IUSR_读权限。
The solution I got from here http://forums.iis.net/t/1147892.aspx
我从这里得到的解决方案是http://forums.iis.net/t/1147892.aspx
#1
3
Below is a more systematic way to determine which user needs to be granted permission
下面是一种更系统的方法来确定需要授予哪些用户权限
Confirm that you have the following executables in C:\WINDOWS\SYSTEM32 (or more generically %systemroot%\system32)
确认你下面的可执行文件C:\WINDOWS\SYSTEM32 % systemroot % \ system32系统普遍(或更多)
cmd.exe
whoami.exe
Check the current ACL for these executables
检查当前ACL以获取这些可执行文件
c:\windows\system32> cacls cmd.exe
c:\windows\system32> cacls whoami.exe
If the user "Everyone" is not granted Read (R) access, then TEMPORARILY grant as follows
如果用户“Everyone”未被授予Read (R) access,则临时授予如下权限
c:\windows\system32> cacls cmd.exe /E /G everyone:R
c:\windows\system32> cacls whoami.exe /E /G everyone:R
Create whoami.php with the following content
创建显示本用户信息。php包含以下内容
<?php
$output = shell_exec("whoami");
echo "<pre>$output</pre>";
?>
Load whoami.php on a web browser and note the username displayed e.g. in my case it showed
加载显示本用户信息。在web浏览器上的php并注意显示的用户名,例如在我的例子中显示的
ct29296\iusr_template
ct29296 \ iusr_template
Revoke "Everyone's" permission if it had to be added in above steps
如果必须在上述步骤中添加“每个人”权限,则撤销该权限
c:\windows\system32> cacls cmd.exe /E /R everyone
c:\windows\system32> cacls whoami.exe /E /R everyone
Grant only the username found in step 5 with the Read+Execute permission (R) to cmd.exe
只将第5步中找到的用户名与Read+Execute权限(R)授予cmd.exe
c:\windows\system32> cacls cmd.exe /E /G ct29296\iusr_template:R
Remember to use the correct username for your own system.
记住要为自己的系统使用正确的用户名。
See: http://www.myfaqbase.com/index.php?q=php+shell_exec&ul=0&show=f
参见:http://www.myfaqbase.com/index.php?q=php显示= f + shell_exec&ul = 0
#2
2
Here's a few points:
这里有几点:
- Regarding PHP skipping the
shell_exec
function, make sure that PHP is not running in safe mode. From the PHP manual - on the shell_exe page: - 关于PHP跳过shell_exec函数,请确保PHP没有在安全模式下运行。从PHP手册-关于shell_exe页面:
Note: This function is disabled when PHP is running in safe mode.
注意:当PHP在安全模式下运行时,此函数将被禁用。
It also appears that this is quite a known problem with executing shell commands from PHP in Windows. The consensus seems to be that the best way to get it to work is to have PHP running in FastCGI mode (I know you tried this already and said you couldn't get it to work - hence my second point). You may find this Microsoft IIS Forum thread helpful.
在Windows中执行PHP的shell命令也是一个众所周知的问题。人们的共识似乎是,让PHP运行在FastCGI模式下是最好的方法(我知道您已经尝试过了,并且说您无法让它正常工作——这是我的第二个观点)。您可能会发现这个Microsoft IIS论坛线程很有用。
- Now, as far as having to run PHP on Windows in order to authenticate against Active Directory - you don't have to!
- 现在,就必须在Windows上运行PHP才能对Active Directory进行身份验证而言——您不必这么做!
Apache provides LDAP authentication via the mod_auth_ldap. And PHP provides LDAP support through the following functions:
Apache通过mod_auth_ldap提供LDAP身份验证。PHP通过以下函数提供LDAP支持:
- ldap_connect
- ldap_connect
- ldap_bind
- ldap_bind
- ldap_search
- ldap_search
- ldap_get_entries
- ldap_get_entries
Active Directory is an implementation of LDAP. So, you with any LDAP client you can perform authentication against Active Directory.
Active Directory是LDAP的一个实现。因此,对于任何LDAP客户端,都可以对活动目录执行身份验证。
- An example of how to authenticate with Active Directory from PHP.
- 如何使用PHP的活动目录进行身份验证的示例。
P.S. You can either use the Apache mod_auth_ldap, or the PHP LDAP functions - you don't need to use both at the same time to make this work. The Apache mod_auth_ldap works at the HTTP protocol level, whereas the PHP LDAP Functions give you more control over the authentication and authorization process.
您可以使用Apache mod_auth_ldap,也可以使用PHP LDAP函数——您不需要同时使用这两个函数来完成这项工作。Apache mod_auth_ldap在HTTP协议级别上工作,而PHP LDAP函数提供了对身份验证和授权过程的更多控制。
#3
1
couple of notes
两个笔记
if you want to execute a .exe directly, you can use proc_open() with $other_options=array('bypass_shell'=>TRUE)
如果您希望直接执行.exe,可以使用proc_open()和$other_options=数组('bypass_shell'=>TRUE)
also procmon.exe (sysinternals) is you best friend when digging into this class of problem
procmon。当你深入研究这类问题时,exe (sysinternals)是你最好的朋友
#4
0
I'd say Read & Execute
permission to the User thats running IIS (if thats not IUSR_MACHINENAME)
我要对运行IIS的用户说Read & Execute权限(如果不是IUSR_MACHINENAME)
#5
0
Unfortunately, I need to use IIS because I'm going to authenticate my users against active directory.
不幸的是,我需要使用IIS,因为我将根据active directory对我的用户进行身份验证。
The premise for basing your application on IIS is flawed. There's nothing to stop you doing this with Apache. Indeed, you don't even need to run it on a MS-Windows OS.
将应用程序基于IIS的前提是有缺陷的。没有什么可以阻止你用Apache做这件事。实际上,您甚至不需要在MS-Windows操作系统上运行它。
Have a google for how to set up all this up.
有一个谷歌如何设置这一切。
Note that with IIS and local clients potentially using NTLM, the security policy gets thrown out of the window. The IIS handler thread may run with the credentials of a NTLM MSIE client. Or not. Debugging this stuff will drive you mad!
注意,对于可能使用NTLM的IIS和本地客户端,安全策略将被抛出窗口。IIS处理程序线程可以使用NTLM MSIE客户机的凭据运行。与否。调试这些东西会让你发疯的!
C.
C。
#6
0
I added the user NETWORK SERVICE with READ & EXECUTE, READ to the directories where the executables of my application resides. Since this alteration, the problem is gone. Nevertheless, it's also neccessary to grant the permissions READ & EXECUTE, READ for IUSR_ to cmd.exe.
我添加了READ & EXECUTE的用户网络服务,并读取应用程序的可执行文件所在的目录。由于这种改变,问题就消失了。尽管如此,还需要向cmd.exe授予读和执行权限,为IUSR_读权限。
The solution I got from here http://forums.iis.net/t/1147892.aspx
我从这里得到的解决方案是http://forums.iis.net/t/1147892.aspx