ubuntu下 Apache2 Fastcgi 配置及root权限运行(c/c++版本)

我所用Ubuntu版本为ubuntu 16.04 64bit

一、安装

apt install apache2 libapache2-mod-fcgid libfcgi-dev

二、配置

检查 /etc/apache2/mods-enabled目录下是否已经有了fcgid相关软连接,如果没有可以自己添加软连接,我的如下:

fcgid.conf -> ../mods-available/fcgid.conf
fcgid.load -> ../mods-available/fcgid.load

修改 /etc/apache2/sites-enabled/000-default.conf添加如下内容:

    
        SetHandler fcgid-script
        Options +ExecCGI

        # Customize the next two directives for your requirements.
        Order allow,deny
        Allow from all
    

最后重启apache2:

/etc/init.d/apache2 restart

三、开发fastcgi程序

示例代码如下(tiny-fcgi.c):

#include   
#include   
#include 
#include 
#include 
 
#include 
  
int main()  
{  
    extern char   **environ;  
    int nlen = 0;  
    int i;  
    char *psz_content = NULL;  
    char **pp_env;

    setuid(geteuid()); //设置实际用户id为有效用户id

    while(FCGI_Accept() >= 0)
    {
        printf("Content-type: text/html\n\n");  
         
        for ( pp_env = environ; *pp_env; pp_env++ )  
            printf("%s
", *pp_env); if ( strcmp("GET", getenv("REQUEST_METHOD")) == 0 ) { char buf[128]; printf("

%s

", getenv("QUERY_STRING")); sprintf(buf, "mkdir -p /var/www/cgi-bin/%s", getenv("QUERY_STRING")); printf("%s\n", buf); system(buf); } else { nlen = atoi(getenv("CONTENT_LENGTH")); psz_content = ( char * )malloc( nlen + 1 ); memset( psz_content, 0, nlen + 1 ); printf("

char value:

"); for (i = 0; i < nlen; i++ ) { psz_content[i] = fgetc(stdin); printf( "%c", psz_content[i] ); } printf("

string value: %s

", psz_content); } } return 0; }

下面操作都是在root用户下进行:

编译:gcc tiny-fcgi.c -o tiny-fcgi -lfcgi

设置程序suid:chmod a+s tiny-fcgi

把编译完成的tiny-fcgi拷贝到/var/www/cgi-bin/目录下(在步骤二里面配置的)

打开浏览器,输入http://192.168.99.1/cgi-bin/tiny-fcgi?dir  (这里假设你主机ip地址为192.168.99.1),会发现fcgi程序运行成功,打印了一些环境变量,同时在/var/www/cgi-bin目录下创建了dir目录(该目录下创建文件夹需要root权限),说明该程序具有root权限

四、实际使用的总结

fastcgi root运行经验CGI程序如果通过C代码执行存取,设置该程序的拥有者为root(chown),再设置suid(chmod +s fastcgi)即可具有root存取权限; 如果在该C代码内通过system()函数执行外部脚本,则需要在system()之前通过setuid()函数设置实际用户ID为有效用户id(setuid(geteuid());)。

五、自己的理解

        首先,我们要知道一点:进程在运行的时候,有一些属性,其中包括 实际用户ID,实际组ID,有效用户ID,有效组ID等。 实际用户ID和实际组ID标识我们是谁,谁在运行这个程序。 而有效用户ID和有效组ID则决定了进程在运行时的权限。内核在决定进程是否有文件存取权限时,是采用了进程的有效用户ID来进行判断的

设置用户ID位:用于对外的权限的开发,它的作用是我们如何去修改有效用户ID,在后面的例子中在展开。借用别人的一张图片:

ubuntu下 Apache2 Fastcgi 配置及root权限运行(c/c++版本)_第1张图片

自己的理解如下:

        当设置用户ID位打开时,非root用户在执行该程序时,有效用户ID被设置为该文件的用户ID。试想如果该文件为root所有,同时设置了设置用户ID位,则其他用户在执行该程序时就有root的存取权限了;实际上这时候因为有了root权限,程序代码中调用setuid(geteuid())也是成功的,即实际用户ID和有效用户都为root。

        Apache2程序默认是以www-data用户和组运行的,默认情况下不允许以root用户运行(除非自己编译,改变编译选项,但是这样运行不安全)。我们的fastcgi程序由Apache2启动,继承了Apache2的用户和组,该用户没有root权限。

        如果我们设置自己的fastcgi程序的有效用户ID(chmod +s fastcgi),则我们的程序具有root权限了(内核在决定进程是否有文件存取权限时,是采用了进程的有效用户ID来进行判断的);但是如果我们在程序中运行外部脚本,该脚本继承的是实际用户ID,不具有root权限;如果我们在运行脚本之前,设置自己的UID为0(即root),则可以使脚本继承该UID,以root用户执行

六、参考

http://bigbang.waterlin.org/bang/using-apache-with-cpp-to-develop-fastcgi-web-server/

Apache下root权限运行CGI:https://blog.csdn.net/a_nervous_free_man/article/details/49914491

无死角理解保存设置用户ID,设置用户ID位,有效用户ID,实际用户ID:                                                                                  https://blog.csdn.net/demiaowu/article/details/39370355

你可能感兴趣的:(C/C++)