目录
SQL注入
SQL注入是一种常见的网络安全攻击方式,它利用应用程序对用户输入数据的不当处理,向数据库中插入恶意的SQL代码,从而实现非法操作或者获取敏感信息。
原理:
SQL注入利用应用程序未正确过滤或转义用户输入的数据,使恶意用户能够在输入框中输入SQL代码,并在数据库中执行这些代码。攻击者可以利用这一漏洞来执行任意的数据库操作,例如读取、修改或删除数据库中的数据,甚至执行系统命令
攻击方式:
基于错误的注入:攻击者利用应用程序在处理用户输入数据时产生的错误信息,推断出数据库结构或执行SQL查询。
盲注:攻击者利用应用程序对输入数据的处理方式,逐位猜测数据库中的数据,通过分析应用程序的响应来推断出结果。
联合查询注入:攻击者通过注入特定的联合查询语句,将恶意代码与原始查询合并,从而执行恶意操作。
SQL注入实例:
渗透目的:
拿到该网站管理员的账号与密码。
实验环境:
本次实验以sqli-labs-master靶机第一关为例,来实现简单sql注入。以下为实验的过程:
判断sql注入类型:
我们在进入到第一关中,可以看到提示:Please input the ID as parameter with numeric value,让我们输入一个id,我们按照他的提示在地址栏中输入?id=1看看有什么变化。
它给出了login name和password,再试一试id值为其它的情况,都会显示不同的login name和password。
这时候我们就来判断以下它的注入类型:用id=2-1判断,如果页面显示的和id=1相同则为数字型注入,如果和id=2相同,则为字符型注入,字符型注入要看闭合条件(数字型就不用看),将id=1后面加',我们插入的'与前面的形成闭合,然后在后面加--+来注释掉后面的闭合,中间就可以插入我们的查询语句了。
找到所属库:
判断完注入类型之后,我们就可以开始完成我们的目的,要找到管理员的账号和密码我们就首先要找到管理员的账号和密码所处的表和列,在这之前我们首先要知道所在的库。
我们可以用 group by 来获取我们目前处于表的列数,在地址栏输入:?id=1' group by 5 --+,输入之后可以发现没有第五列,再试试4,3直到它不报错,即可找到该表的列数。 找到它的列数了,只有3列。那么我们就可以用union(联合查询)来达到我们的目的,我们试试?id=1' union select 1,2,3 --+,再试一试 id=1' union select 1,2,3 --+我们可以发现两次内容不一样,这是因为页面只能显示一个内容,第二句(即union 后面的内容)是不显示的,可以把第一句(id=1)的内容改成数据库不存在的数据,如id=-1 或id=0都可以,所以我们想得到什么信息就在2和3的位置上修改对应的语句即可,我们想得到该表所在的库,我们利用database()函数即可,则代码为:
?id=-1' union select 1,database(),3 --+
我们发现库名为security,快拿我们的小本本记好!!!
找到所属库的表:
现在我们拿到列数和库名那么我们现在的思路应该是:找到管理员账号和密码所在的表和表中的字段
不知道大家有没有发现我们数据库中有默认的几个库,其中有一个叫做information_schema的库,这个库中包含所有MySql数据库的简要信息,其中包含两个重要数据表tables和columns,那我们就先来看看这两张表中都有些什么吧,用我自己的数据库来看看 我们能看到tables表总共有357条数据
olumns表中有三千多条数据,tables表中记录该数据库中所有库的表名,columns表中记录该数据库中所有表的列名。
那么我们已经该网站的数据库库名所以我们可以通过where来筛选出该库中的表,则代码为: group_concat()这个函数是将内容一行输出,
?id=-1' union select 1,group_concat(table_name), 3 from information_schema.tables where table_schema='security' --+
找到存储账号和密码的表的字段并查出账号和密码:
我们现在已经拿到该网站所有的表名了,我们猜测管理员的账号和密码存储在users表中,但也不一定,我们试一试看,我们现在查找user表中的字段看一看,代码为:
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' --+
看来我们猜的没错,现在知道了表名、字段名现在开始查就完了,代码为:
?id=-1' union select 1,2,group_concat(username,':',password) from users --+
看看结果吧,很明显我们找到了全部用户的账号和密码包括管理员的,我们的目的达成了!!!
思路梳理总结:
在这一关中,我们首先判断了sql注入类型,发现是字符型注入,我们先是利用order by 来确定该表中的列数,有了列数我们就可以通过database()函数获取到该网站所在的库,我们在information_schema 库中通过刚才获取的库名作为我们的筛选条件在tables表中查询到了该库中的所有表,又在columns表通过过滤table_name和table_schema两个字段查找出users表中的列(字段)信息,到这一步之后我们就直接在users表中查找用户和密码,此时注入完成。
无列名注入:
在实际开发中,开发人员会通过一系列手段来限制我们的sql注入,比如当我们输入information_schema时,会将这个字段在传入数据库中之前替换成空格,这时我们就查不到我们想要fo,那该怎么半呢我们可以将库名进行“双写”:inforinformation_schemamation_schema,当程序检测到information_schema时,把中间的变成空之后两边又拼成information_schema了,他干了个寂寞,我们又可以进行攻击了。但现实是,开发人员已经发现我们会这么干,所以他们就开始用正则来检测我们的恶意输入了,只要开发人员够厉害,他就可以完全限制我们访问information_schema。
那现在应该怎么办呢,这是就要用到mysql自带的sys库,我们发现有一个叫做x$schema_table_statistics 的表,这张表中同样也存储着所有库的表名,但是也没有列名,这个时候就要用到无列名注入了:
1.我们先使用join将表进行自连接 2.mysql> select * from (select * from score a join score b) as c;
ERROR 1060 (42S21): Duplicate column name 'id' 3.我们发现它报错了,显示存在重复的列名 'id',我们正好可以利用这个报错来获取列名
此时我们也拿到了该表中的所有列名我们进行查询即可