LWP无法在CGI脚本中运行

时间:2018-07-25 16:38:27

标签: perl cgi lwp

我有一个CGI脚本可以从BibBase加载出版物:

#!/usr/bin/perl

use LWP::UserAgent;

my $url = 'https://bibbase.org/show?bib=http://www.example.com/pubs.bib';
my $ua = LWP::UserAgent->new;
my $can_accept = HTTP::Message::decodable;
my $response = $ua->get($url, 'Accept-Encoding' => $can_accept);

print "Content-type: text/html\n\n";
print $response->decoded_content;

(这是从BibBase复制的,但URL是硬编码的。)

我有三个运行RHEL7和Apache 2.4的Web服务器,它们由Puppet进行相同配置。在这三个脚本上,我都可以在命令行上运行脚本并获得预期的结果:

[root@server1 cgi-bin]# ./bibbase_proxy2.cgi | head
Content-type: text/html

<img src="//bibbase.org/img/ajax-loader.gif" id="spinner" style="display: none;" alt="Loading.." />

<div id="bibbase">

  <script type="text/javascript">
    var bibbase = {
      params: {"bib":"http://www.example.com/pubs.bib","host":"bibbase.org"},

当我尝试使用CGI运行脚本时,我得到三个不同的结果:

  • Server1
    Unrecognised protocol tcp at /usr/share/perl5/LWP/Protocol/http.pm line 31.
  • Server2
    Can't connect to bibbase.org:443 System error at /usr/share/perl5/LWP/Protocol/http.pm line 51.
  • Server3
    没有http输出,错误日志显示AH01215: Out of memory!

我在这三台服务器之间找不到任何不同之处,也无法弄清为什么该脚本在命令行上可以正常工作,而在作为CGI运行时却无法正常工作。

我的selinux处于宽松模式,它正在记录传出的请求,因此我知道脚本已经达到了这么远:

type=AVC msg=audit(1532465859.921:331235): avc:  denied  { name_connect } for  pid=161178 comm="perl" dest=80 scontext=system_u:system_r:httpd_sys_script_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket 

为了进行测试,我将selinux设置为disabled,然后重新启动了服务器。

2 个答案:

答案 0 :(得分:4)

SE-Linux denied the TCP connection

avc:  denied  { name_connect }
  

SELinux的默认网络访问控制基于分配给TCP和UDP端口和套接字的标签。例如,TCP端口80标记为http_port_t(和类tcp_socket)。然后,通过SELinux访问控制(例如name_connect和name_bind)来控制对该端口的访问。

     

当应用程序连接到端口时,将检查name_connect权限。但是,当应用程序绑定到端口时,将检查name_bind权限。

是否采用许可模式,Perl的行为就像拒绝了TCP连接一样。 Unrecognised protocol tcp的意思是getprotobyname("tcp") failed inside IO::Socket::IP。那是非常非常不寻常的。发生这种情况的方法之一就是完全拒绝SELinux。

我不是SELinux专家,但是根据RedHat和Gentoo some SELinux aware applications will ignore the global permissive setting的说法,一个人去吧。 RHEL 7 Apache appears to be one of them。似乎在have its own domain which must be set permissive中。


  

在这三者中,我都可以在命令行上运行脚本并获得预期的结果:

有两个原因,它们都与用户有关。

运行程序时,您将以自己的用户身份运行,并具有自己的配置,权限和环境变量。实际上,您以root的身份运行它,通常会绕过限制。当它在服务器上运行时,它将以其他用户身份运行,可能是网络服务器用户受到严格限制。

为了进行实际测试,您需要以与Web服务器相同的用户身份运行它。您可以为此使用sudo -u。例如,如果用户为apache ...

sudo -u apache ./bibbase_proxy2.cgi

顺便说一句 请勿以root用户身份测试软件! 不仅不会给您带来明智的结果,而且如果软件中存在错误,也无法防止任何安全措施它会破坏系统。


第二个问题是#!/usr/bin/env perl。这意味着要运行PATH中的任何perl。 PATH对于不同的用户将有所不同。运行./bibbase_proxy2.cgi可以在命令行上运行一个Perl,并通过Web服务器运行另一个。

在服务器环境中,使用类似于#!/usr/bin/perl的Perl硬编码路径。

答案 1 :(得分:1)

我们通过用Python和PHP重写相同的脚本进行了测试。他们两个都显示出错误,将我们引向正确的方向。

Python urllib2产生了错误

<class 'urllib2.URLError'>: <urlopen error [Errno 16] Device or resource busy>
      args = (error(16, 'Device or resource busy'),)
      errno = None
      filename = None
      message = ''
      reason = error(16, 'Device or resource busy')
      strerror = None 

PHP(以CGI运行)甚至无法启动:

[Wed Jul 25 15:24:52.988582 2018] [cgi:error] [pid 10369] [client 172.28.6.200:44387] AH01215: PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/curl.so' - libssh2.so.1: failed to map segment from shared object: Cannot allocate memory in Unknown on line 0
[Wed Jul 25 15:24:52.988980 2018] [cgi:error] [pid 10369] [client 172.28.6.200:44387] AH01215: PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/dba.so' - libtokyocabinet.so.9: failed to map segment from shared object: Cannot allocate memory in Unknown on line 0
    ---- Similar lines for all extensions. ----

看来RLimitMEM阻止了对共享内存的访问,而这是打开套接字所必需的。我找不到任何文档,但是删除该行使其可以工作。