SQL注入原理

1,原理

        SQL 注入就是指 Web 应用程序对用户输入的数据合法性没有过滤或者是判断,攻击者可以在Web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

        我的理解就是构造闭合,使用mysql语句,让后台执行mysql语句并泄露数据库信息

比如我们在传入用户名和密码时,或者最简单的传入id值,后台会有这样一句php

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

这是sql-labs less1中的sql注入关键语句,其中$id就是我们传入的参数id,如果我们正常传入一个参数,那它就会被正常的包裹起来。

        我们在url栏中传入1,那它的sql语句就是

$sql="SELECT * FROM users WHERE id='1' LIMIT 0,1";

这样显然是一个没有错误的sql语句,它会执行正常的功能,但要是我们传入1'会这么样呢

$sql="SELECT * FROM users WHERE id='1'' LIMIT 0,1";

 这样传入,明显多了一个',造成了闭合错误,那页面会是这么样呢?

可以看到,闭合错误后,页面会跳出提示我们mysql语句错误,这样也会提醒我们存在sql注入。

例题

这边就以sql-labs的less1作为例题,好好了解每个payload的作用是什么。

在sql注入前,先要了解什么是mysql

mysql就是一个用于存储数据的数据库,而它的结构通常由库,表,字段组成

而知道了结构我们就可以对其逐一的爆破,从库到字段全都可以知道。

1,联合注入

        sql-labs的第一题就是联合注入,这是最基本的注入方法,而联合注入分为get和post两种类型。但他们其实都是同一种方法,只是传参的方式不同。 

        union联合注入得名于union语句,union可以把多个表的数据一起显示,但这也是有条件的。

通常联合注入只适用于有回显的注入,并且union再联合时只能联合字段数一样的表,所以通常还需要知道字段数。(有些地方也叫做列数)

从less-1的源码我们可以知道,存在这样的sql语句

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

这句sql语句的意思就是

1,select * from users从uers表中,搜索所有字段(*是通配符)

2,where后面跟的过滤条件,从字段中匹配传入的id值,并只选择匹配的记录

3,limit 0,1表示从第0行(第一行),返回查询到所有数据中的第1条数据

那么在了解了基本的sql注入规则后,我们就可以开始注入了。

首先我们要判断字段数(列数) 

这需要用到order by,用法是order by + 数字

这个会对某个字段(列)进行排序,如果要排序的列数大于表中存在的列,sql就会报错。

如图传入?id=1' order by 3 --+        其中--+是注释符,用于省略掉后面的语句,就会如下图所示

$sql="SELECT * FROM users WHERE id='-1' union select 1,2,3 --+' LIMIT 0,1";

这样sql语句就变成了搜索id为1的记录,并对第三个字段进行排序

而当我们将3改为4,就会提示出现位置的字段

所以当前表中的字段是3行

然后就是判断回显位置

这里就要用到union了,我们传入

?id=-1' union select 1,2,3 --+
$sql="SELECT * FROM users WHERE id='-1' union select 1,2,database() --+' LIMIT 0,1";

这里传入-1是为了不然mysql在查找到数据并返回,方便判断回显。

这样就会在users表中搜索id='-1'的记录,同时搜索1,2,3(这三个数会直接拼接到对应的字段中,并会返回1,2,3)(从这里也可以看出当前表中的第一个字段是id,第二个字段是uname,第三个字段是pword)

之前也说过,union联合查询必须满足段数相等,因此我们在3后再加一个4,就会报错,因为sql不知道将4合并到哪一个字段中 查完回显后,我们就可以爆破库名

暴库名的操作很简单,随意替换1,2,3中任意一个为database()就行了

这里通常选择3,因为不用加括号(database()是mysql中用于查询当前数据库名的函数)

$sql="SELECT * FROM users WHERE id='-1' union select 1,2,database() --+' LIMIT 0,1";

 这就就爆出库名了

爆出库名之后就是查表名

传参数

?id=-1' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database())--+

这里就会用到常用的group_concat(),这个函数用于将字符串链接起来,这里链接的是表名

table_name就是表名的意思,而这个表名从哪里来的呢?

        在 MySQL5.0 版本后,MySQL 默认在数据库中存放一个information_schema的数据库,该数据库中包含了当前系统中所有的数据库、表、列、索引、视图等相关的元数据信息,是MySql自身信息元数据的存储库,我们需要记住三个表名,分别是 schemata,tables,columns

 所以我们是将数据库中的所有表名都连接在一起,但是这个数据也有范围,即where后面限制的table_schema=database()(当前数据库)。

然后就会回显出当前数据库的所有表名

爆完表名就可以爆字段名(列名)

 传入参数

?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+

这里就只是将合并字符串的参数换为column_name(字段名)并限定表名为'users'

这里注意一下,你爆表名就用information_schema.tables

爆字段名就用information_schema.columns 

点后面是所有数据库中具体要查询的内容

 然后就是爆字段

之前爆出字段名有id-username-password

传入参数

?id=-1' union select 1,2,(select group_concat(id,"-",username,"-",password) from users)--+

这里group_concat中传入的参数"-"意思是用-将他们链接起来,而且这里的users不用加双引号

总结 

至此,一道基本的sql注入就完毕了,至于post类与get一样,只用将参数用post传参即可.

sql注入的程序

查字段-查回显-爆库名-爆表名-爆字段名-爆字段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值