主页 > 网络知识 > php中函数禁用绕过的原理与利用(6)

php中函数禁用绕过的原理与利用(6)

0ctf 2019中Wallbreaker Easy中的出题点就是采用了imagick在处理一些特定后缀文件时,会调用ffmpeg,也就是会开启子进程,从而达成加载共享库执行系统命令bypass disable。

Apache Mod CGI

前面的两种利用都需要putenv,如果putenv被ban了那么就需要这种方式,简单介绍一下原理。

原理

利用htaccess覆盖apache配置,增加cgi程序达成执行系统命令,事实上同上传htaccess解析png文件为php程序的利用方式大同小异。

mod cgi:

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

因此我们只需上传一个.htaccess:

Options +ExecCGI  //使运行cgi程序的执行 AddHandler cgi-script .test //将test后缀的文件解析为cgi程序 利用

利用就很简单了:

 

上传htaccess,内容为上文所给出的内容

 

 

上传a.test,内容为:

 

#!/bin/bash echo&&ls

给a.test权限,访问即可得到执行结果。

PHP-FPM

php-fpm相信有读者在配置php环境时会遇到,如使用nginx+php时会在配置文件中配置如下:

location ~ .php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }

那么看看百度百科中关于php-fpm的介绍:

PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个PHPFastCGI管理器,对于PHP 5.3.3之前的php来说,是一个补丁包 [1] ,旨在将FastCGI进程管理整合进PHP包中。如果你使用的是PHP5.3.3之前的PHP的话,就必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。

那么fastcgi又是什么?Fastcgi 是一种通讯协议,用于Web服务器与后端语言的数据交换。

原理

那么我们在配置了php-fpm后如访问?test=1,那么会被解析为如下键值对:

{     'GATEWAY_INTERFACE': 'FastCGI/1.0',     'REQUEST_METHOD': 'GET',     'SCRIPT_FILENAME': '/var/www/html/test.php',     'SCRIPT_NAME': '/test.php',     'QUERY_STRING': '?test=1',     'REQUEST_URI': '/test.php?test=1',     'DOCUMENT_ROOT': '/var/www/html',     'SERVER_SOFTWARE': 'php/fcgiclient',     'REMOTE_ADDR': '127.0.0.1',     'REMOTE_PORT': '12304',     'SERVER_ADDR': '127.0.0.1',     'SERVER_PORT': '80',     'SERVER_NAME': "localhost",     'SERVER_PROTOCOL': 'HTTP/1.1' }

这个数组很眼熟,会发现其实就是$_SERVER里面的一部分,那么php-fpm拿到这一个数组后会去找到SCRIPT_FILENAME的值,对于这里的/var/www/html/test.php,然后去执行它。

前面笔者留了一个配置,在配置中可以看到fastcgi的端口是9000,监听地址是127.0.0.1,那么如果地址为0.0.0.0,也即是将其暴露到公网中,倘若我们伪造与fastcgi通信,这样就会导致远程代码执行。

那么事实上php-fpm通信方式有tcp也就是9000端口的那个,以及socket的通信,因此也存在着两种攻击方式。

socket方式的话配置文件会有如下:

fastcgi_pass unix:/var/run/phpfpm.sock;

那么我们可以稍微了解一下fastcgi的协议组成,其由多个record组成,这里摘抄一下p神原文中的一段结构体:

typedef struct {   /* Header */   unsigned char version; // 版本   unsigned char type; // 本次record的类型   unsigned char requestIdB1; // 本次record对应的请求id   unsigned char requestIdB0;   unsigned char contentLengthB1; // body体的大小   unsigned char contentLengthB0;   unsigned char paddingLength; // 额外块大小   unsigned char reserved;    /* Body */   unsigned char contentData[contentLength];   unsigned char paddingData[paddingLength]; } FCGI_Record;

可以看到record分为header以及body,其中header固定为8字节,而body由其contentLength决定,而paddingData为保留段,不需要时长度置为0。

说点什么吧
  • 全部评论(0
    还没有评论,快来抢沙发吧!