sqli-lab笔记--less01 (Error Based- String)
sqli-lab less01--Error Based- String(基于字符串错误)
(第1节:基于错误 – 字符串)
字符型注入,也即是通过Get或者Post方式传进去的数据被单引号或者双引号包裹住
TEST
http://127.0.0.1/sqli/Less-1/?id=1'
提示语法错误:
具体代码如下:
注:id被单引号包裹;不报错的时候,会显示username和password这两个位置的内容
从上面的错误提示当中,我们可以看到提交到sql中的1'在经过sql语句构造后形成 '1'' LIMIT 0,1,多加了一个 ' 。接下来想如何将多余的 ' 去掉可以借鉴一下源码
通过打印的sql执行语句,我们可以看到多出一个’。我们可以让‘失效,具体方法注释掉多余的单引号
主要知识点:
(1)将单引号闭合,给单引号添加注释。常用注释符号:#,-- 两种注释。但仅仅通过这两种注释有的时候不管用需要绕过,常见的绕过方式如下:#,--,#号url编码为
%23,--+ (+后面有空格),-- ... (--后面有空格) 绕过,--%23,-- a等。
(2)order by语句只能显示查询字段的列数,并非所有表的列数。当查询内容为username,password则order by字段为2,若查询* 则order by字段为3 ,总共三个字段,id,username,password 有的教程说的是表的列数,实属瞎扯淡。
(3)尝试使用sql语句重复查询,查询最后一句下面不能有其他查询语句。因为最后注释掉sql语句闭合分号了。入坑很久才发现
(4)联合查询 查询条件为假。默认联合查询将查询所有字段联合起来。
联合查询(前提需要两个查询字段数量一样),查询结果为两个查询的组合。
当一个查询为false,则显示第二个查询内容。由于程序设计为查询内容显示,因此选择1,2等数字确定显示位。
(那么我们只要让第一行查询的结果是空集(即union左边的select子句查询结果为空),那么我们union右边的查询结果自然就成为了第一行,就打印在网页上了,)
这里显示位为2,3。因此可以查询数据库内容。常见查询内容:数据库版本,当前数据库等信息。
concat_ws(char(32,58,32),user(),database(),version())
concat函数及concat_ws 函数为数据库连接函数。其中concat为连接1,2,3,4 查询结果,concat_ws 第一个参数为查询数据连接字符。通常使用
concat_ws(char(32,58,32),user(),database(),version())
具体效果如下:
基础知识:
(1)mysql系统表熟悉,information_scheman内容。
(2)会使用limit 逐条查询数据库内容。
(1)系统表介绍
接下来查询security数据库中有哪些表
首先说一下mysql的数据库information_schema,他是系统数据库,安装完就有,记录是当前数据库的数据库,表,列,用户权限等信息,下面说一下常用的几个表
SCHEMATA表:储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等,show databases的结果取之此表。
TABLES表:储存mysql中的表信息,(当然也有数据库名这一列,这样才能找到哪个数据库有哪些表嘛)包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。show tables from schemaname的结果取之此表
COLUMNS表:提供了表中的列信息,(当然也有数据库名和表名称这两列)详细表述了某张表的所有列以及每个列的信息,包括该列是那个表中的第几列,列的数据类型,列的编码类型,列的权限,猎德注释等。是show columns from schemaname.tablename的结果取之此表。
查询数据库时可以使用单引号包裹数据库名称或者将数据库名编码为十六进制。
如 security对应 16进制代码--------》 7365637572697479
等价于:
通过一次增加limit的起始值,可以逐个查出security的表名称。这里users为存在敏感信息的表。接下来通过表来查询字段名,字段值,类似。
常见的查询语句如下:
select 1,2,table_name from information_schema.tables where table_schema='security' limit 2,1--+ (查询表security存在的表名称)
select 1,2,column_name from information_schema.columns where table_name='users' limit 0,1 --+ (查询表中存在的列名)
然后,通过连接数据库函数(concat)一次查询多个值。已经知道数据库以及所在的表名称。
具体如下:
http://127.0.0.1/sqli/Less-1/?id=1' and 1=2 union select 1,2,concat_ws(':',id,username,password) from users limit 0,1--+
至此,less01 已经完成。
总结:
1、基于错误的GET单引号字符型注入 判断注入点,通过单引号,报错并显示数据库类型。闭合单引号。(这里可能是单引号、双引号、小括号等)
2、order by 理解的判断。(order by用于判断该条查询语句的查询字段个数,并不是查询表的字段个数)
order by 默认的是排序,将通过某个字段进行升序或者降序。然而数字对应于查询字段的个数一一对应,当超过查询字段的个数将会报错。因此可以判断查询字段个数。
3、union 查询,联合查询需要两个select语句,查询字段数量一样。上一步order by已经判断出。默认将两个表联合字段输出,但是为了显示回显位置,通常让查询条件为false,这样就可以让第二个查询的内容显示出来。
4、构造查询语句,查询库名、版本、登陆用户(database(),verison(),user())
http://127.0.0.1/sqli/less-1/?id=1' and 1=-1 union select 1,2,concat_ws(":",user(),database(),version()) --+
5、查询到数据,就要查询表名、字段名称。(mysql系统库)
其中information_shema 库可以查询所有数据库名称、表名、字段、编码等信息。
具体如下:schemata 包含所有的数据库。
tables包含所有的库名、表名
columns包含所有的库名、表名、字段名。
通过构造可以查询到,所有的数据库、表名称、字段名。最后通过查询查到,最后的数据值。逐条limit 0,1 增加,查询。
问题:
1、奇葩思想问题,通过查询时候为什么不能显示在第一个回显位呢?
select username,password from users where id =1;
from语句只能放在最后一个字段那里!!!!
有用记录统计:
查询数据库中系统库的库, information_schema 这个库中有用表 schemata 库信息,tables 表信息 ,columns 字段信息
查询库信息语句: select schema_name from information_schema.schemata;
查询表信息语句:select table_name from information_schema.tables where table_schema='security';
查询字段信息语句: select column_name from information_schema.columns where talbe_name='users';
通过依次获取到数据库字段名后,直接查询字段名对应的值就可以获取数据。具体如下id,username,password