BuuCTF做题记录_2
初学者的一些做题记录
[安洵杯 2019]easy_web
进环境发现是这么个东西,URL
值得注意:
/index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
右键源码还可以发现一行字:md5 is funny ~
(和md5有关?),估计是被藏到图片后面了。
先在kali下用dirsearch扫一下看看有没有其它文件:
dirsearch -u http://55a28404-cd69-4529-9626-2cd4d4f499d1.node4.buuoj.cn:81/ --delay 3 -t 30
没有什么有用的信息。看看源码:
选中那段字符提示了base64,利用base64转图片工具转换结果就是左上角那张图片。但很明显URL中不是这个东西,应该是将文件名进行了变化。
img参数是大小写字母加数字的组合,猜测是base64
,而且随便输个abc
再看源码会发现这么个东西:
直接base64解码:MzUzNTM1MmU3MDZlNjc=
,又是一串base64
再解码:3535352e706e67
。看着像十六进制,解一下:555.png
现在这个参数怎么出来的就清楚了:字符串先经过十六进制,再经过两次base64加密。前面猜测这是个include
的参数,因为这个img
和cmd
参数都是在index.php下的,那就直接看index.php
是啥东西(用同样的方法转换):img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3
1 |
|
最开始正则匹配\
那里没弄明白,一开始觉得|\\|\\\\|
这俩东西就会把\
这东西给匹配了,去网上搜了wp发现都说直接l\s
就能绕过。后面发现自己想错了,|\\|\\\\|
这东西并不会匹配到\
,需要\\\
才行。举个栗子:
1 |
|
这时我们传?b=
任何值都会报错:
**Warning**: preg_match(): No ending delimiter '/' found in **D:\phpstudy_pro\WWW\wow.php** on line **4**
电脑没有找到/
这个结束定界符。想了下原因,既然\
这个东西是转义字符,那么\\
只不过是一个转义后的\
,这个东西和/
组合到一起会去正则匹配/
这个东西,这样一来导致缺少尾部界定符。修改一下:
1 |
|
这时不会报错而且回去正则匹配/
,现在思路就清晰了:如果我们想正则匹配\
,那么就需要\\\
才行:
1 |
|
现在再看看这段正则匹配怎么个事:
1 |
|
注意|\\|\\\\|
,这东西相当于去匹配|\\\\
。因为前两个\\
回去转义后面那个分隔符|
,再加上\\\\
,然后以|
收尾:
1 |
|
我们只有传?b=|\\\\
才会echo
检测到,所以我们仍可以利用\
进行命令拼接,比如l\s
,l\s%20/
,c\at%20fl\ag
等。
在burp中如果使用空格会被识别为其他的参数,所以这里空格用%20
替换。
综上,可以进行命令执行,得到flag。
[GWCTF 2019]我有一个数据库
???
用dirsearch扫一下,发现robots.txt
还有/phpmyadmin/
,看看都有啥:
robots.txt
提示phpinfo.php
,/phpmyadmin/
不登录可以直接访问数据库管理界面:
后面就无处下手了。。去网上查了一下wp
,这题考的是phpmyadmin4.8.1
版本存在任意文件读取漏洞:include $_REQUEST['target'];
直接利用现成的payload
:target=db_sql.php%253f/../../../../../../../../etc/passwd
,发现可以进行任意文件读取。后面再翻翻flag
的位置就行了。
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../../../../flag
flag{14b071f4-a712-4a14-b3ce-d6bc07df4506}
不过我看文章中都写了$_REQUEST['target']
,但尝试POST
提交拿不到结果。而且在?target
前加个/
就白屏了。。不过右键看源码还是能看到回显,不知道咋回事。
[MRCTF2020]PYWebsite
进环境发现有这么个东西:
看下源码:
1 |
|
看完想了一下,直接去flag.php
看看怎么个事:
http://node4.buuoj.cn:25037/flag.php
提示保存了购买者的IP,可以利用XFF
伪造。除了购买者和我自己,没有人可以看到flag
,直接XFF 127.0.0.1
试试?
[ASIS 2019]Unicorn shop
题目提示unicode
和python
了解了下unicode
:
1 |
|
试了试购买前三种都提示:
买最后一个会显示:Only one char(?) allowed!
,意思是这个Price
只能填一个字符?源码里面有下面这段提示:
1 |
|
去网上找了下wp,和提示的Unicode
有关:先把Item ID
和Price
都放空,看看报错信息:
可以发现他用了unicodedata.numeric()
函数去处理这个price
,这东西会获取 Unicode 字符的数值表示,比如:
1 |
|
然后利用这个网站https://www.compart.com/en/unicode
找numeric value
大于1337
的就行
直接把目标符号复制粘贴到Price
价格里就好了。
补充:这题源码里有段price = urlib.unquote(price).decode('utf-8')
,即先把输入url
解码后再经过utf-8
编码赋值给price
,然后用unicodedata.numeric()
处理price
。
所以可以通过先找目标字符的utf-8
编码,把它转换成对应的url
形式(把0x
换成%
就行,再去掉空格)
[网鼎杯 2020 朱雀组]Nmap(这题还没做完先放一放)
一个端口扫描网站,初步猜测存在RCE
或者文件包含。
先看源码里有啥:<!-- flag is in /flag -->
嗯,那应该是要RCE
了
随便输个127.0.0.1
看看怎么个事:
提供了一些端口信息,这个URL
值得注意:
/result.php?f=f7909
to index
就是返回首页,to list
是这么个界面:
File
那一栏就是result.php
底下的f
参数,尝试了六次发现文件名应该五六位十六进制的随机数。他这东西的运行过程大概就是扫描目标IP
的端口,然后给结果五位十六进制随机数的文件名,存储起来如果想读取利用result.php
进行了文件包含。
不过结果中存在一个警告,抓包看看怎么个事:
首先,输入IP
后会进行302重定向。
如果随便更改f
的值呢?会出现下面的报错:
simplexml_load_file()
会把把XML 文档载入对象中,所以应该是把结果以XML文件的形式存储。
127.0.0.1;ls
提示Host maybe down
,换成127.0.0.1 ;
发现会给;
前加一个\
进行转义变成127.0.0.1 \;
,但如果没有这个空格会直接报错host maybe down
后面捣鼓半天不知道怎么弄了,找了wp
发现是自己思路错了,这题考的是Nmap
的一些用法。
还没做完先放一放。。一看这两个escape
函数我就头疼
[NPUCTF2020]ReadlezPHP
进环境发现是这么个东西,尝试右键看源码没啥反应,直接在URL加view-source:
发现有这么个东西,直接访问:./time.php?source
(本来还想拿dirsearch扫来着,看来没必要了)
1 |
|
现在思路就清晰了,直接构造我们想执行的命令就行:
1 |
|
不过没有运行?后面换了其它的命令也是没有回显。感觉是被过滤了(可以执行命令的函数有很多),但也想不到其它思路,去看了其它师傅的wp发现要用assert
这个函数,正好借这个机会梳理一下RCE
中常用的几个命令执行函数,还有他们之间的关系:
我个人认为最常见的肯定是eval
和system
,先说下它俩之间最大的差别(个人观点):
eval类型函数是代码执行而不是命令执行
system类型函数是命令执行而不是代码执行,举几个栗子:
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
接下来这个echo $b($a)
也有点说法,这东西有人叫它变量函数
,比如:
1 |
|
先说下这个assert
函数:
1 |
|
至于为什么不能只单纯用一个eval
,原因是PHP中不能以变量函数的形式去调用它:eval 属于PHP语法构造的一部分,并不是一个函数,所以不能通过 变量函数 的形式来调用。
可以上传一个简单的一句话木马:
1 |
|
先用scandir
函数看看根目录底下都有啥东西:
time.php?data=O%3A8%3A"HelloPhp"%3A2%3A{s%3A1%3A"a"%3Bs%3A19%3A"eval(%24_REQUEST[3])%3B"%3Bs%3A1%3A"b"%3Bs%3A6%3A"assert"%3B}&3=var_dump(scandir('/'));
注意要用分号结尾!否则不能被执行!用var_dump
的原因是这函数会返回数组
有个FIag_!S_it
,system
被禁了所以用不了cat
,尝试file_get_contents
直接读,但是假的flag
:
echo(file_get_contents('/FIag_!S_it'));
注意这个不能写成:
echo("file_get_contents('/FIag_!S_it')");
,这个命令会显示file_get_contents('/FIag_!S_it')
用蚁剑连接看看怎么个事:
http://1730f221-b91f-4b8b-b19d-8ce0eb0211e5.node4.buuoj.cn:81/time.php?data=O%3A8%3A%22HelloPhp%22%3A2%3A{s%3A1%3A%22a%22%3Bs%3A19%3A%22eval(%24_REQUEST[3])%3B%22%3Bs%3A1%3A%22b%22%3Bs%3A6%3A%22assert%22%3B}
没有任何东西,应该是没权限。
看师傅们的wp
都是去phpinfo()
找,ctrl+f
搜索就行。
payload:time.php?data=O%3A8%3A"HelloPhp"%3A2%3A{s%3A1%3A"a"%3Bs%3A19%3A"eval(%24_REQUEST[3])%3B"%3Bs%3A1%3A"b"%3Bs%3A6%3A"assert"%3B}&3=phpinfo();
再补充下scandir()
这个函数:
scandir()
函数会接受一个目录路径作为参数,并返回一个数组,包含该目录中的所有文件和子目录的名称。返回的数组中,每个元素表示目录中的一个文件或子目录的名称。
1 |
|
结果:
[CISCN2019 华东南赛区]Web11
进去发现是个和IP
有关的页面,右上角显示了我们的公网IP
:
下面甚至有请求包的完整信息:
既然它获取了IP
那大概率可以想到XFF
伪造,抓包试试看:
确实是这样,但有什么用?这题明显不是利用XFF的SQL注入,想到之前做过一道好像叫cookie is so stable
的题,通过模板注入解题,试试看:
X-Forwarded-For:{7*7}
还真是,老规矩先判断是什么类型的,再试试:X-Forwarded-For:a{*comment*}b
应该是Smarty
模板,个人认为这个模板最大的特点就是可以直接执行命令,在XFF
直接输入:{system('ls /')}
去找flag
,然后直接cat
读就行了。
其实这题底下有行小字提示了:Build With Smarty !
[CISCN 2019 初赛]Love Math
看题目可能跟MD5
有关?
直接给了源码:
1 |
|
这题花了很长时间没解出来,因为一直在想怎么去绕过黑名单和正则匹配去执行命令,后面看了wp
才知道要利用给的函数去做,参考了这位师傅的文章https://www.cnblogs.com/20175211lyz/p/11588219.html
https://www.anquanke.com/post/id/220813#h3-2
思路一
主要是base_convert()
函数和dechex
函数的使用:
可以看到这东西的范围是2-36
,正好覆盖了0-9,a-z
。dechex
函数用于将十进制数转换为十六进制数。它接受一个十进制数作为参数,并返回一个表示相应十六进制数的字符串。
先看wp
怎么写的:
1 |
|
payload
:
/index.php?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){0}(($$pi){1})&0=system&1=<command>
因为师傅写的很详细还是很好理解的:先利用base_convert
函数转出一个hex2bin
,再利用dechex
转出一个十六进制字符串,前函后参组合转出_GET
.
base_convert
遇到36
进制时会转换成小写字母,举个栗子:
1 |
|
后面就很好理解了,它会直接eval
过滤后的c
。执行后c
=$pi
=_GET
,$$pi
=$_GET
。再利用$_GET{0}($_GET{1})去执行函数就好。即使[]
被过滤了仍可以使用{}
绕过。构造完_GET
后还需要引入一个变量来作为函数执行, 例如 $a()
, 我们用 $pi
以绕过白名单的检测。
思路二
利用getallheaders
去解题:
payload:/index.php?c=$pi=base_convert,$pi(696468,10,36)($pi(8768397090111664438,10,30)(){1})
注意这个getallheaders的用法
首先为什么是30进制(参考了bfengj
师傅的文章):
1 |
|
system(getallheaders(){1})
,这个{1}
应该是获取包头为1
部分的值,我说应该
是因为没找到相关文章说这个东西。。大多直接给了payload
(估计师傅们觉得这问题没必要说,哈哈)。我自己尝试把1
改成别的再改对应包头也能执行命令(我这里改成了333
):
[BSidesCF 2019]Kookie
让我们以admin
的身份登录,然后提示已经有cookie/monster
这两个账户了,选cookie
这个用户名再随便输个密码登录一下看看:
可以看到行为/用户名/密码都是直接以GET
方式传过去的(源码也有相应提示),那我们直接把username
后面的东西删掉看看能否登录:
/?action=login&username=cookie
这个登不上去,换monster
试试:
/?action=login&username=monster
登录成功:
抓包看看cookie
:
发现cookie
字段中username=monster
,直接改成admin
:
应该是新生赛的题目