NewStarCTF 2023 week1-web题wp

闲来无事发现了buuctf上面正在进行一个比赛,貌似是八校合办的新手赛,特地来试试手,主要是好久没碰web了有点手生了。

一、Begin of Upload

先burp抓包一下,发现这个是在前端进行限制的上传题目,很简单了这样。

之后就是直接蚁剑连接,在上层目录中找到flag

二、泄漏的秘密

这个经过一顿Google,也是学到了一些知识,加上之前也做过类似的题,可以总结一下

最常见的泄露问题就是出现在

  • robots.txt

  • www.zip

  • index.php.swp/.bak

对于swp后缀就是当开发人员在线上环境中使用 vim 编辑器,在使用过程中会留下 vim 编辑器缓存,当vim异常退出时,缓存会一直留在服务器上,引起网站源码泄露。

而另一个常用的就是当开发人员在线上环境中对源代码进行了备份操作,并且将备份文件放在了 web 目录下,就会引起网站源码泄露,也就是后缀bak。

这题就直接先进入robots.txt目录,发现第一部分flag

对于www.zip的原理,如下

网站的文件都是放置在www 文件夹 下面的,zip是一种压缩格式。 也就是WWW文件夹里面的文件全部压缩在 www.zip 里面了。

所以直接访问/www.zip获取全部文件,也就拿到了flag

拿到flag

三、begin of http

进入之后提示如下,直接get

直接看源码发现secret

解码一下是n3wst4rCTF2023g00000d,然后post就行,之后就蚌埠住辣

怎么post都不会显示下一步,我放到了请求头里面没用,放在body里面也没用,服了

然后看别人的题解,就是这样的,就是显示不出来,难绷,下一题

这里有一个知识点,这题的后面需要在本地访问,则有三个选择

  • Client-ip: 127.0.0.1

  • X-Real-IP: 127.0.0.1

  • X-Forwarded-For: 127.0.0.1

三个都是伪造ip的请求头。请求一下就可以通过本题

四、ErrorFlask

这题还挺有意思的,刚进去网页提示输入number1和number2,他会相加,输入完之后会有提示,如下

提示是ssti,Google一下发现是flask模板ssti注入,然后根据网上找的文章随便找了一个参数注入一下,发现出现下面报错

这个报错是因为python无法直接将包含小数点的字符串转化为整数,就会出这个报错,我本以为止步于此了,但是突然发现这个代码可以打开,如下,加上前面提到的flag在源代码中,顺利找到flag:flag{Y0u_@re_3enset1ve_4bout_deb8g}

这个ssti注入应该也算一个知识点,之后有时间开一个专题记录一下

Bugku CTF——WEB之SSTI学习笔记_bugkuctf web-CSDN博客

五、Begin of PHP

又是我们熟悉的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
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
<?php
error_reporting(0);
highlight_file(__FILE__);

if(isset($_GET['key1']) && isset($_GET['key2'])){
echo "=Level 1=<br>";
if($_GET['key1'] !== $_GET['key2'] && md5($_GET['key1']) == md5($_GET['key2'])){
$flag1 = True;
}else{
die("nope,this is level 1");
}
}

if($flag1){
echo "=Level 2=<br>";
if(isset($_POST['key3'])){
if(md5($_POST['key3']) === sha1($_POST['key3'])){
$flag2 = True;
}
}else{
die("nope,this is level 2");
}
}

if($flag2){
echo "=Level 3=<br>";
if(isset($_GET['key4'])){
if(strcmp($_GET['key4'],file_get_contents("/flag")) == 0){
$flag3 = True;
}else{
die("nope,this is level 3");
}
}
}

if($flag3){
echo "=Level 4=<br>";
if(isset($_GET['key5'])){
if(!is_numeric($_GET['key5']) && $_GET['key5'] > 2023){
$flag4 = True;
}else{
die("nope,this is level 4");
}
}
}

if($flag4){
echo "=Level 5=<br>";
extract($_POST);
foreach($_POST as $var){
if(preg_match("/[a-zA-Z0-9]/",$var)){
die("nope,this is level 5");
}
}
if($flag5){
echo file_get_contents("/flag");
}else{
die("nope,this is level 5");
}
}

这个就一步一步的过关就行,看样子php的绕过问题也可以水一个专题了。

level1,是需要两个数不相等但是他们的哈希值一致。这里需要注意的是题中对于哈希值的对比用的是而不是=,而对于弱比较==只会比较值而不会比较类型,这里只需要两个哈希值算出来以0e开头即可,php会把他当做0的多少次方,所以都会变成0,就实现了绕过。这里可以记一下哪些值的哈希值以0e开头,如下

1
2
3
4
5
6
7
8
20610708:0e462097431906509019562988736854
QLTHNDT:0e405967825401955372549139051580
QNKCDZO:0e830400451993494058024219903391
PJNPDWY:0e291529052894702774557631701704
NWWKITQ:0e763082070976038347657360817689
NOOPCJF:0e818888003657176127862245791911
MMHUWUV:0e701732711630150438129209816536
MAUXXQC:0e478478466848439040434801845361

所以key1和key2随便选上面两个数就可通过

level2,这里需要同一个数经过两个函数计算出的值一样,这显然不可能,所以就要绕过。这里用到的知识点是对应sha1函数和md5函数,如果参数是数组的话都会返回null,这种情况下只需要key3传入数组,就可以实现null===null,实现绕过

level3,strcmp函数是比较两个字符串是否相等,如果str1<str2 则返回<0 如果str1大于str2返回>0 如果两者相等,返回0。但是strcmp只能比较字符串类型,如果传入的数组则会报错返回0,也就是利用了这点进行绕过。只需要让key4也传入数组即可

level4,这个更容易,我之前应该做过类似的题,先绕过第一个不是数字,并且第二个还要大于2023,则可以输入2024a,这样满足了不是数字,并且在比较的时候php会从前往后转数字,所以2024a就被转成了2024>2023,通过level4,同理1e5a也可以通过,变成10000>2023

level5,这关需要搜索一下extract函数的作用,如下

并且还需要绕过preg_match函数,这个函数绕过原理也是一样,就是传入数组会报错返回0,这样就不会触发if语句。最主要是extract函数的参数是post整体,我看到这个有点不确定,不知道我传入的数组会是什么形态存在,抱着试试看的态度我传入了flag5[]=1,发现通过了,但是后来我测试发现flag[]=0也可通过关卡,感觉还是不明白就问了chatgpt,原理如下:并且通过测试发现if语句里面如果是一个数组,不管怎样都会通过if语句所以会通关

最后的请求头和flag如下:

六、R!C!E!

看题目就知道有远程执行漏洞,点开网页,发现如下代码

1
2
3
4
5
6
7
8
9
10
11
<?php
highlight_file(__FILE__);
if(isset($_POST['password'])&&isset($_POST['e_v.a.l'])){
$password=md5($_POST['password']);
$code=$_POST['e_v.a.l'];
if(substr($password,0,6)==="c4d038"){
if(!preg_match("/flag|system|pass|cat|ls/i",$code)){
eval($code);
}
}
}

简单审计一下,发现逻辑很简单,就是需要password的哈希值的前六位等于c4d038才可以进入下一步,并且code里面不能有flag|system|pass|ls这些指令,

首先先绕过第一个吧,简单写一个php函数计算一下,如下,最开始100000的范围不行,加到1000000,出现结果,好臭的数字

所以直接password传入114514即可,紧接着就是e_v.a.l,参考[php文档](PHP: 来自 PHP 之外的变量 - Manual),可以了解到 “ . ” 是非法字符

但是题中要求的变量名就是含有“ . ”,这里就需要利用另一个漏洞,在php版本小于8的时候,会把 “ [ ” 这个字符转换为下划线,但是会出现转换错误导致后续的非法字符不会被转换,因此我们想传入名为 “e_v.a.l”的变量,只需要传入 “e[v.a.l”的变量名即可。

之后就是绕过正则表达式了,有一个简单的方法叫做参数逃逸,就是在传入的参数是另一个参数,然后通过另一个参数来执行我们想要的代码

如下

传入的字符串为eval($_POST[‘a’]),这样就可以将我们想要注入的代码写到a里面就可以绕过正则表达式了。

七、EasyLogin