一、引入
以sqli-labs靶场中Less-2关卡为例(注入点为数字型),进行sql手工注入流程的介绍。
【目标:获取当前网站的数据库中,所有用户账号、密码信息。】
1、sqli-labs靶场环境搭建
(P.S、sqli-labs靶场环境搭建,见下述文章:
2、sqli-labs靶场关卡Less-2
P.S、输入id=1,出现以下信息
P.S、查看Less-2的源码。【可用记事本打开】
(Less-2的源码位于:C:\phpstudy_pro\WWW\sqli-labs\Less-2路径下的index.php文件)
P.S、后端变量$id接收来自前端url网址中传递的id值,并用于sql语句查询中的一个参数。
P.S、注意:
①综上,上述GET提交方式中的id值在之后的服务器(业务逻辑层)中,会被当作sql语句执行的一个参数(例如where id = $id)。
②若服务器未对前端用户输入的id值做过滤和判断,直接将用户输入当作sql参数来执行。
③在存在注入点的情况下,此时我们可以注入一些额外的sql语句(例如union联合查询)。
二、sql手工注入的流程
0、补充:数据提交方式
数据提交方式:即数据在浏览器中进行数据提交到服务器的方式。
<1、数据提交方式
(1)GET提交:通过url网址提交到服务器
优点:速度快【get提交速度比post提交快很多】
缺点:安全性不高、可提交的数据长度受限(2KB)
适用于:对安全性要求不太高、数据容量较小网页的提交
(2)POST提交:直接通过服务器提交
优点:安全性更高、可提交的数据量更多。【相对于get提交方式而言】
P.S、【下述sql手工注入流程,仅针对于Less-2而言。对于其他关卡,可存在其他多种方法】。
1、判断是否有注入点
<1、没有注入点:
对上述用户输入的值做了过滤和判断,使前端用户只能输入数字,此时没有注入点。
<2、有注入点:
用户输入任意内容:
①若报错,则此处的id值处有注入点。【因为用户输入的内容,被传入到sql语句中,当作参数执行】
②若没有报错,则此处的id值处没有注入点。【没报错,说明用户传入的值被过滤】
P.S、当我们在id处随便输入一个peter值后,出现报错。
说明将我们的输入当作sql语句的一个参数来执行了,因为没有找到,进而返回报错。因此,id值输入处存在一个sql注入点。
2、猜解字段数量(即列名数量):order by
P.S、按照第一个字段进行排序(没报错,说明当前表中有1个字段)
P.S、按照第二个字段进行排序(没报错,说明当前表中有2个字段)
P.S、按照第三个字段进行排序(没报错,说明当前表中有3个字段)
P.S、按照第四个字段进行排序(报错,说明当前表中只有3个字段)
验证:
可查看sqli-labs靶场数据库中users表的信息,发现的确有3个字段(分别为id字段、username字段、password字段)
综上:当前表中只有3个字段(即3列)。
3、通过上述报错,来判断回显点:union联合查询
①补充:union联合查询的2个特点
<1、 union前面查询语句的字段数量与union后面查询字段的数量要一致。
所以需要通过上述的第二步来确定字段数量。
【例如union select 1,2,3】
<2、union前面的查询语句和后面的查询语句结果互不干扰。(即使union前面的查询没有执行成功,也不影响union后面查询语句的执行)
所以可以通过使union前面的语句报错,来仅执行union后面的查询语句、来进一步判断回显点。【例如:id=-1 union select 1,2,3】
综上,2和3位置处,为回显点。
4、信息收集:(通过回显点来进行信息收集)
①获取数据库版本号:version()
P.S、当前数据库的版本为5.7.26
P.S、数据库分为高版本、低版本:
<1、数据库5.0及以上【数据库的高版本才有系统库】
其中information_schema系统库中:schemata表:保存数据库信息。tables表:保存数据表信息。columns表:保存字段信息。
<2、数据库5.0及以下【无系统库】
②补充:MySQL的系统库
- <1、Information_schema:【重点】
- 内有61张数据表,重点掌握以下3张表:
- schemata表:保存当前整个MySQL服务器中所有数据库的信息。(例如:所有的数据库名、访问权限、类型等)
- schema_name字段:保存当前服务器中所有数据库的名字
- 执行show databases函数后,返回的结果就是取自Information_schema数据库中的schemata表中的schema_name字段。
- tables表:保存当前整个MySQL服务器中所有表的信息。(例如:表名)
- table_name字段:保存当前服务器中所有数据表的表名。
- 例如:只查看tables表中的第一条数据
- select * from tables limit 1,1;
- columns表:保存当前整个MySQL服务器中所有字段的信息。(例如:字段名)
- column_name字段:保存当前服务器中所有字段的字段名。
- 例如:只查看columns表中的第一条数据
- select * from columns limit 1,1;
- <2、Performance_schema:
- 内有87张表
- 作用:主要保存数据库服务器的性能参数。(例如:内存、读写速度等)
- <3、mysql:【重点】
- 作用:记录当前数据库中所有数据的权限(增、删、改、查)。当前服务器的(root)账号、密码信息也保存在此系统库中。
- <4、sys:
- 内有1张表,100个视图
- 作用:通过视图将Information_schema数据库和Performance_schema数据库结合。
- 例如:可以查询哪个用户使用的资源最多、对哪张表的访问最多等。
③获取当前数据库的库名:database()
P.S、sqli-labs靶场的数据库库名为security
5、实施相应的sql注入方法
目的:获取当前网站中所有的账号、密码信息
①获取数据库库名:
【已通过database()获取到】
②获取数据库表名:
【可通过系统库information_schema下的表tables中的table_name字段来获取数据库中所有表名】
P.S1、用where条件来指定查询的数据库名,来限定查找的范围。
P.S2、函数group_concat():
当数据库表名有多个的时候,页面中不一定可以显示的下,此时可以使用group_concat()函数。(用于分组、合并显示数据)
P.S3、'='的前后不能有空格
P.S4、查询security数据库下(可由database()获取)的所有表名
union select 1,group_concat(table_name),3 from information_schema.tables
where table_schema=database()
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()
P.S5、获取到4个表名(分别为emails表、referers表、uagents表、users表)。在这四个表中,推测users表最有可能存储着用户的账号和密码信息。
③数据库字段名
【获取users表中的字段名】
union select 1,group_concat(column_name),3 from information_schema.columns
where table_schema=database() and table_name=’users’
union select 1,group_concat(column_name),3 from information_schema.columns
where table_schema=database() and table_name=’users’
P.S1、 where条件中指定库名、表名
P.S2、若出现报错,可以将表名users转为十六进制
上述sql注入语句可改为
union select 1,group_concat(column_name),3 from information_schema.columns
where table_schema=database() and table_name=0x7573657273
union select 1,group_concat(column_name),3 from information_schema.columns
where table_schema=database() and table_name=0x7573657273
P.S3、获取到users表中的3个字段名(分别为id、username、password)
推测账号、密码信息分别放在username、password字段中。
④查询对应字段的数据信息
P.S1、0x3a:表示冒号’:’
P.S2、查询username、password字段的信息
union select 1,2,(select group_concat(username,0x3a,password) from users)
union select 1,2,(select group_concat(username,0x3a,password) from users)
综上,获取到该网站下的所有账号、密码信息。
三、后续
对于没有注入点、低版本数据库、没有回显点等情况,请看后续文章。